97e6e1313f90f024740e613d8e6452388a2c89aa
[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     
4883     Ext.isReady = initExtCss();
4884     
4885     if (!Ext.isReady) {
4886         Ext.onReady(initExtCss);
4887     }
4888 })();
4889
4890
4891 (function(){
4892     var supports = Ext.apply(Ext.supports, {
4893         
4894         correctRightMargin: true,
4895         
4896         
4897         correctTransparentColor: true,
4898         
4899         
4900         cssFloat: true
4901     });
4902     
4903     var supportTests = function(){
4904             var div = document.createElement('div'),
4905                 doc = document,
4906                 view,
4907                 last;
4908                 
4909             div.innerHTML = '<div style="height:30px;width:50px;"><div style="height:20px;width:20px;"></div></div><div style="float:left;background-color:transparent;">';
4910             doc.body.appendChild(div);
4911             last = div.lastChild;
4912             
4913             if((view = doc.defaultView)){
4914                 if(view.getComputedStyle(div.firstChild.firstChild, null).marginRight != '0px'){
4915                     supports.correctRightMargin = false;
4916                 }
4917                 if(view.getComputedStyle(last, null).backgroundColor != 'transparent'){
4918                     supports.correctTransparentColor = false;
4919                 }
4920             }
4921             supports.cssFloat = !!last.style.cssFloat;
4922             doc.body.removeChild(div);
4923     };
4924     
4925     if (Ext.isReady) {
4926         supportTests();    
4927     } else {
4928         Ext.onReady(supportTests);
4929     }
4930 })();
4931
4932
4933
4934 Ext.EventObject = function(){
4935     var E = Ext.lib.Event,
4936         clickRe = /(dbl)?click/,
4937         
4938         safariKeys = {
4939             3 : 13, 
4940             63234 : 37, 
4941             63235 : 39, 
4942             63232 : 38, 
4943             63233 : 40, 
4944             63276 : 33, 
4945             63277 : 34, 
4946             63272 : 46, 
4947             63273 : 36, 
4948             63275 : 35  
4949         },
4950         
4951         btnMap = Ext.isIE ? {1:0,4:1,2:2} : {0:0,1:1,2:2};
4952
4953     Ext.EventObjectImpl = function(e){
4954         if(e){
4955             this.setEvent(e.browserEvent || e);
4956         }
4957     };
4958
4959     Ext.EventObjectImpl.prototype = {
4960            
4961         setEvent : function(e){
4962             var me = this;
4963             if(e == me || (e && e.browserEvent)){ 
4964                 return e;
4965             }
4966             me.browserEvent = e;
4967             if(e){
4968                 
4969                 me.button = e.button ? btnMap[e.button] : (e.which ? e.which - 1 : -1);
4970                 if(clickRe.test(e.type) && me.button == -1){
4971                     me.button = 0;
4972                 }
4973                 me.type = e.type;
4974                 me.shiftKey = e.shiftKey;
4975                 
4976                 me.ctrlKey = e.ctrlKey || e.metaKey || false;
4977                 me.altKey = e.altKey;
4978                 
4979                 me.keyCode = e.keyCode;
4980                 me.charCode = e.charCode;
4981                 
4982                 me.target = E.getTarget(e);
4983                 
4984                 me.xy = E.getXY(e);
4985             }else{
4986                 me.button = -1;
4987                 me.shiftKey = false;
4988                 me.ctrlKey = false;
4989                 me.altKey = false;
4990                 me.keyCode = 0;
4991                 me.charCode = 0;
4992                 me.target = null;
4993                 me.xy = [0, 0];
4994             }
4995             return me;
4996         },
4997
4998         
4999         stopEvent : function(){
5000             var me = this;
5001             if(me.browserEvent){
5002                 if(me.browserEvent.type == 'mousedown'){
5003                     Ext.EventManager.stoppedMouseDownEvent.fire(me);
5004                 }
5005                 E.stopEvent(me.browserEvent);
5006             }
5007         },
5008
5009         
5010         preventDefault : function(){
5011             if(this.browserEvent){
5012                 E.preventDefault(this.browserEvent);
5013             }
5014         },
5015
5016         
5017         stopPropagation : function(){
5018             var me = this;
5019             if(me.browserEvent){
5020                 if(me.browserEvent.type == 'mousedown'){
5021                     Ext.EventManager.stoppedMouseDownEvent.fire(me);
5022                 }
5023                 E.stopPropagation(me.browserEvent);
5024             }
5025         },
5026
5027         
5028         getCharCode : function(){
5029             return this.charCode || this.keyCode;
5030         },
5031
5032         
5033         getKey : function(){
5034             return this.normalizeKey(this.keyCode || this.charCode);
5035         },
5036
5037         
5038         normalizeKey: function(k){
5039             return Ext.isSafari ? (safariKeys[k] || k) : k;
5040         },
5041
5042         
5043         getPageX : function(){
5044             return this.xy[0];
5045         },
5046
5047         
5048         getPageY : function(){
5049             return this.xy[1];
5050         },
5051
5052         
5053         getXY : function(){
5054             return this.xy;
5055         },
5056
5057         
5058         getTarget : function(selector, maxDepth, returnEl){
5059             return selector ? Ext.fly(this.target).findParent(selector, maxDepth, returnEl) : (returnEl ? Ext.get(this.target) : this.target);
5060         },
5061
5062         
5063         getRelatedTarget : function(){
5064             return this.browserEvent ? E.getRelatedTarget(this.browserEvent) : null;
5065         },
5066
5067         
5068         getWheelDelta : function(){
5069             var e = this.browserEvent;
5070             var delta = 0;
5071             if(e.wheelDelta){ 
5072                 delta = e.wheelDelta/120;
5073             }else if(e.detail){ 
5074                 delta = -e.detail/3;
5075             }
5076             return delta;
5077         },
5078
5079         
5080         within : function(el, related, allowEl){
5081             if(el){
5082                 var t = this[related ? "getRelatedTarget" : "getTarget"]();
5083                 return t && ((allowEl ? (t == Ext.getDom(el)) : false) || Ext.fly(el).contains(t));
5084             }
5085             return false;
5086         }
5087      };
5088
5089     return new Ext.EventObjectImpl();
5090 }();
5091
5092
5093 Ext.ns("Ext.grid", "Ext.list", "Ext.dd", "Ext.tree", "Ext.form", "Ext.menu",
5094        "Ext.state", "Ext.layout", "Ext.app", "Ext.ux", "Ext.chart", "Ext.direct");
5095     
5096
5097 Ext.apply(Ext, function(){
5098     var E = Ext,
5099         idSeed = 0,
5100         scrollWidth = null;
5101
5102     return {
5103         
5104         emptyFn : function(){},
5105
5106         
5107         BLANK_IMAGE_URL : Ext.isIE6 || Ext.isIE7 || Ext.isAir ?
5108                             'http:/' + '/www.extjs.com/s.gif' :
5109                             'data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==',
5110
5111         extendX : function(supr, fn){
5112             return Ext.extend(supr, fn(supr.prototype));
5113         },
5114
5115         
5116         getDoc : function(){
5117             return Ext.get(document);
5118         },
5119
5120         
5121         num : function(v, defaultValue){
5122             v = Number(Ext.isEmpty(v) || Ext.isArray(v) || typeof v == 'boolean' || (typeof v == 'string' && v.trim().length == 0) ? NaN : v);
5123             return isNaN(v) ? defaultValue : v;
5124         },
5125
5126         
5127         value : function(v, defaultValue, allowBlank){
5128             return Ext.isEmpty(v, allowBlank) ? defaultValue : v;
5129         },
5130
5131         
5132         escapeRe : function(s) {
5133             return s.replace(/([-.*+?^${}()|[\]\/\\])/g, "\\$1");
5134         },
5135
5136         sequence : function(o, name, fn, scope){
5137             o[name] = o[name].createSequence(fn, scope);
5138         },
5139
5140         
5141         addBehaviors : function(o){
5142             if(!Ext.isReady){
5143                 Ext.onReady(function(){
5144                     Ext.addBehaviors(o);
5145                 });
5146             } else {
5147                 var cache = {}, 
5148                     parts,
5149                     b,
5150                     s;
5151                 for (b in o) {
5152                     if ((parts = b.split('@'))[1]) { 
5153                         s = parts[0];
5154                         if(!cache[s]){
5155                             cache[s] = Ext.select(s);
5156                         }
5157                         cache[s].on(parts[1], o[b]);
5158                     }
5159                 }
5160                 cache = null;
5161             }
5162         },
5163
5164         
5165         getScrollBarWidth: function(force){
5166             if(!Ext.isReady){
5167                 return 0;
5168             }
5169
5170             if(force === true || scrollWidth === null){
5171                     
5172                 var div = Ext.getBody().createChild('<div class="x-hide-offsets" style="width:100px;height:50px;overflow:hidden;"><div style="height:200px;"></div></div>'),
5173                     child = div.child('div', true);
5174                 var w1 = child.offsetWidth;
5175                 div.setStyle('overflow', (Ext.isWebKit || Ext.isGecko) ? 'auto' : 'scroll');
5176                 var w2 = child.offsetWidth;
5177                 div.remove();
5178                 
5179                 scrollWidth = w1 - w2 + 2;
5180             }
5181             return scrollWidth;
5182         },
5183
5184
5185         
5186         combine : function(){
5187             var as = arguments, l = as.length, r = [];
5188             for(var i = 0; i < l; i++){
5189                 var a = as[i];
5190                 if(Ext.isArray(a)){
5191                     r = r.concat(a);
5192                 }else if(a.length !== undefined && !a.substr){
5193                     r = r.concat(Array.prototype.slice.call(a, 0));
5194                 }else{
5195                     r.push(a);
5196                 }
5197             }
5198             return r;
5199         },
5200
5201         
5202         copyTo : function(dest, source, names){
5203             if(typeof names == 'string'){
5204                 names = names.split(/[,;\s]/);
5205             }
5206             Ext.each(names, function(name){
5207                 if(source.hasOwnProperty(name)){
5208                     dest[name] = source[name];
5209                 }
5210             }, this);
5211             return dest;
5212         },
5213
5214         
5215         destroy : function(){
5216             Ext.each(arguments, function(arg){
5217                 if(arg){
5218                     if(Ext.isArray(arg)){
5219                         this.destroy.apply(this, arg);
5220                     }else if(typeof arg.destroy == 'function'){
5221                         arg.destroy();
5222                     }else if(arg.dom){
5223                         arg.remove();
5224                     }
5225                 }
5226             }, this);
5227         },
5228
5229         
5230         destroyMembers : function(o, arg1, arg2, etc){
5231             for(var i = 1, a = arguments, len = a.length; i < len; i++) {
5232                 Ext.destroy(o[a[i]]);
5233                 delete o[a[i]];
5234             }
5235         },
5236
5237         
5238         clean : function(arr){
5239             var ret = [];
5240             Ext.each(arr, function(v){
5241                 if(!!v){
5242                     ret.push(v);
5243                 }
5244             });
5245             return ret;
5246         },
5247
5248         
5249         unique : function(arr){
5250             var ret = [],
5251                 collect = {};
5252
5253             Ext.each(arr, function(v) {
5254                 if(!collect[v]){
5255                     ret.push(v);
5256                 }
5257                 collect[v] = true;
5258             });
5259             return ret;
5260         },
5261
5262         
5263         flatten : function(arr){
5264             var worker = [];
5265             function rFlatten(a) {
5266                 Ext.each(a, function(v) {
5267                     if(Ext.isArray(v)){
5268                         rFlatten(v);
5269                     }else{
5270                         worker.push(v);
5271                     }
5272                 });
5273                 return worker;
5274             }
5275             return rFlatten(arr);
5276         },
5277
5278         
5279         min : function(arr, comp){
5280             var ret = arr[0];
5281             comp = comp || function(a,b){ return a < b ? -1 : 1; };
5282             Ext.each(arr, function(v) {
5283                 ret = comp(ret, v) == -1 ? ret : v;
5284             });
5285             return ret;
5286         },
5287
5288         
5289         max : function(arr, comp){
5290             var ret = arr[0];
5291             comp = comp || function(a,b){ return a > b ? 1 : -1; };
5292             Ext.each(arr, function(v) {
5293                 ret = comp(ret, v) == 1 ? ret : v;
5294             });
5295             return ret;
5296         },
5297
5298         
5299         mean : function(arr){
5300            return arr.length > 0 ? Ext.sum(arr) / arr.length : undefined;
5301         },
5302
5303         
5304         sum : function(arr){
5305            var ret = 0;
5306            Ext.each(arr, function(v) {
5307                ret += v;
5308            });
5309            return ret;
5310         },
5311
5312         
5313         partition : function(arr, truth){
5314             var ret = [[],[]];
5315             Ext.each(arr, function(v, i, a) {
5316                 ret[ (truth && truth(v, i, a)) || (!truth && v) ? 0 : 1].push(v);
5317             });
5318             return ret;
5319         },
5320
5321         
5322         invoke : function(arr, methodName){
5323             var ret = [],
5324                 args = Array.prototype.slice.call(arguments, 2);
5325             Ext.each(arr, function(v,i) {
5326                 if (v && typeof v[methodName] == 'function') {
5327                     ret.push(v[methodName].apply(v, args));
5328                 } else {
5329                     ret.push(undefined);
5330                 }
5331             });
5332             return ret;
5333         },
5334
5335         
5336         pluck : function(arr, prop){
5337             var ret = [];
5338             Ext.each(arr, function(v) {
5339                 ret.push( v[prop] );
5340             });
5341             return ret;
5342         },
5343
5344         
5345         zip : function(){
5346             var parts = Ext.partition(arguments, function( val ){ return typeof val != 'function'; }),
5347                 arrs = parts[0],
5348                 fn = parts[1][0],
5349                 len = Ext.max(Ext.pluck(arrs, "length")),
5350                 ret = [];
5351
5352             for (var i = 0; i < len; i++) {
5353                 ret[i] = [];
5354                 if(fn){
5355                     ret[i] = fn.apply(fn, Ext.pluck(arrs, i));
5356                 }else{
5357                     for (var j = 0, aLen = arrs.length; j < aLen; j++){
5358                         ret[i].push( arrs[j][i] );
5359                     }
5360                 }
5361             }
5362             return ret;
5363         },
5364
5365         
5366         getCmp : function(id){
5367             return Ext.ComponentMgr.get(id);
5368         },
5369
5370         
5371         useShims: E.isIE6 || (E.isMac && E.isGecko2),
5372
5373         
5374         
5375         type : function(o){
5376             if(o === undefined || o === null){
5377                 return false;
5378             }
5379             if(o.htmlElement){
5380                 return 'element';
5381             }
5382             var t = typeof o;
5383             if(t == 'object' && o.nodeName) {
5384                 switch(o.nodeType) {
5385                     case 1: return 'element';
5386                     case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
5387                 }
5388             }
5389             if(t == 'object' || t == 'function') {
5390                 switch(o.constructor) {
5391                     case Array: return 'array';
5392                     case RegExp: return 'regexp';
5393                     case Date: return 'date';
5394                 }
5395                 if(typeof o.length == 'number' && typeof o.item == 'function') {
5396                     return 'nodelist';
5397                 }
5398             }
5399             return t;
5400         },
5401
5402         intercept : function(o, name, fn, scope){
5403             o[name] = o[name].createInterceptor(fn, scope);
5404         },
5405
5406         
5407         callback : function(cb, scope, args, delay){
5408             if(typeof cb == 'function'){
5409                 if(delay){
5410                     cb.defer(delay, scope, args || []);
5411                 }else{
5412                     cb.apply(scope, args || []);
5413                 }
5414             }
5415         }
5416     };
5417 }());
5418
5419
5420 Ext.apply(Function.prototype, {
5421     
5422     createSequence : function(fcn, scope){
5423         var method = this;
5424         return (typeof fcn != 'function') ?
5425                 this :
5426                 function(){
5427                     var retval = method.apply(this || window, arguments);
5428                     fcn.apply(scope || this || window, arguments);
5429                     return retval;
5430                 };
5431     }
5432 });
5433
5434
5435
5436 Ext.applyIf(String, {
5437
5438     
5439     escape : function(string) {
5440         return string.replace(/('|\\)/g, "\\$1");
5441     },
5442
5443     
5444     leftPad : function (val, size, ch) {
5445         var result = String(val);
5446         if(!ch) {
5447             ch = " ";
5448         }
5449         while (result.length < size) {
5450             result = ch + result;
5451         }
5452         return result;
5453     }
5454 });
5455
5456
5457 String.prototype.toggle = function(value, other){
5458     return this == value ? other : value;
5459 };
5460
5461
5462 String.prototype.trim = function(){
5463     var re = /^\s+|\s+$/g;
5464     return function(){ return this.replace(re, ""); };
5465 }();
5466
5467
5468
5469 Date.prototype.getElapsed = function(date) {
5470     return Math.abs((date || new Date()).getTime()-this.getTime());
5471 };
5472
5473
5474
5475 Ext.applyIf(Number.prototype, {
5476     
5477     constrain : function(min, max){
5478         return Math.min(Math.max(this, min), max);
5479     }
5480 });
5481 Ext.lib.Dom.getRegion = function(el) {
5482     return Ext.lib.Region.getRegion(el);
5483 };      Ext.lib.Region = function(t, r, b, l) {
5484                 var me = this;
5485         me.top = t;
5486         me[1] = t;
5487         me.right = r;
5488         me.bottom = b;
5489         me.left = l;
5490         me[0] = l;
5491     };
5492
5493     Ext.lib.Region.prototype = {
5494         contains : function(region) {
5495                 var me = this;
5496             return ( region.left >= me.left &&
5497                      region.right <= me.right &&
5498                      region.top >= me.top &&
5499                      region.bottom <= me.bottom );
5500
5501         },
5502
5503         getArea : function() {
5504                 var me = this;
5505             return ( (me.bottom - me.top) * (me.right - me.left) );
5506         },
5507
5508         intersect : function(region) {
5509             var me = this,
5510                 t = Math.max(me.top, region.top),
5511                 r = Math.min(me.right, region.right),
5512                 b = Math.min(me.bottom, region.bottom),
5513                 l = Math.max(me.left, region.left);
5514
5515             if (b >= t && r >= l) {
5516                 return new Ext.lib.Region(t, r, b, l);
5517             }
5518         },
5519         
5520         union : function(region) {
5521                 var me = this,
5522                 t = Math.min(me.top, region.top),
5523                 r = Math.max(me.right, region.right),
5524                 b = Math.max(me.bottom, region.bottom),
5525                 l = Math.min(me.left, region.left);
5526
5527             return new Ext.lib.Region(t, r, b, l);
5528         },
5529
5530         constrainTo : function(r) {
5531                 var me = this;
5532             me.top = me.top.constrain(r.top, r.bottom);
5533             me.bottom = me.bottom.constrain(r.top, r.bottom);
5534             me.left = me.left.constrain(r.left, r.right);
5535             me.right = me.right.constrain(r.left, r.right);
5536             return me;
5537         },
5538
5539         adjust : function(t, l, b, r) {
5540                 var me = this;
5541             me.top += t;
5542             me.left += l;
5543             me.right += r;
5544             me.bottom += b;
5545             return me;
5546         }
5547     };
5548
5549     Ext.lib.Region.getRegion = function(el) {
5550         var p = Ext.lib.Dom.getXY(el),
5551                 t = p[1],
5552                 r = p[0] + el.offsetWidth,
5553                 b = p[1] + el.offsetHeight,
5554                 l = p[0];
5555
5556         return new Ext.lib.Region(t, r, b, l);
5557     };  Ext.lib.Point = function(x, y) {
5558         if (Ext.isArray(x)) {
5559             y = x[1];
5560             x = x[0];
5561         }
5562         var me = this;
5563         me.x = me.right = me.left = me[0] = x;
5564         me.y = me.top = me.bottom = me[1] = y;
5565     };
5566
5567     Ext.lib.Point.prototype = new Ext.lib.Region();
5568
5569 Ext.apply(Ext.DomHelper,
5570 function(){
5571     var pub,
5572         afterbegin = 'afterbegin',
5573         afterend = 'afterend',
5574         beforebegin = 'beforebegin',
5575         beforeend = 'beforeend',
5576         confRe = /tag|children|cn|html$/i;
5577
5578     
5579     function doInsert(el, o, returnElement, pos, sibling, append){
5580         el = Ext.getDom(el);
5581         var newNode;
5582         if (pub.useDom) {
5583             newNode = createDom(o, null);
5584             if (append) {
5585                 el.appendChild(newNode);
5586             } else {
5587                 (sibling == 'firstChild' ? el : el.parentNode).insertBefore(newNode, el[sibling] || el);
5588             }
5589         } else {
5590             newNode = Ext.DomHelper.insertHtml(pos, el, Ext.DomHelper.createHtml(o));
5591         }
5592         return returnElement ? Ext.get(newNode, true) : newNode;
5593     }
5594
5595     
5596     
5597     function createDom(o, parentNode){
5598         var el,
5599             doc = document,
5600             useSet,
5601             attr,
5602             val,
5603             cn;
5604
5605         if (Ext.isArray(o)) {                       
5606             el = doc.createDocumentFragment(); 
5607             for (var i = 0, l = o.length; i < l; i++) {
5608                 createDom(o[i], el);
5609             }
5610         } else if (typeof o == 'string') {         
5611             el = doc.createTextNode(o);
5612         } else {
5613             el = doc.createElement( o.tag || 'div' );
5614             useSet = !!el.setAttribute; 
5615             for (var attr in o) {
5616                 if(!confRe.test(attr)){
5617                     val = o[attr];
5618                     if(attr == 'cls'){
5619                         el.className = val;
5620                     }else{
5621                         if(useSet){
5622                             el.setAttribute(attr, val);
5623                         }else{
5624                             el[attr] = val;
5625                         }
5626                     }
5627                 }
5628             }
5629             Ext.DomHelper.applyStyles(el, o.style);
5630
5631             if ((cn = o.children || o.cn)) {
5632                 createDom(cn, el);
5633             } else if (o.html) {
5634                 el.innerHTML = o.html;
5635             }
5636         }
5637         if(parentNode){
5638            parentNode.appendChild(el);
5639         }
5640         return el;
5641     }
5642
5643     pub = {
5644         
5645         createTemplate : function(o){
5646             var html = Ext.DomHelper.createHtml(o);
5647             return new Ext.Template(html);
5648         },
5649
5650         
5651         useDom : false,
5652
5653         
5654         insertBefore : function(el, o, returnElement){
5655             return doInsert(el, o, returnElement, beforebegin);
5656         },
5657
5658         
5659         insertAfter : function(el, o, returnElement){
5660             return doInsert(el, o, returnElement, afterend, 'nextSibling');
5661         },
5662
5663         
5664         insertFirst : function(el, o, returnElement){
5665             return doInsert(el, o, returnElement, afterbegin, 'firstChild');
5666         },
5667
5668         
5669         append: function(el, o, returnElement){
5670             return doInsert(el, o, returnElement, beforeend, '', true);
5671         },
5672
5673         
5674         createDom: createDom
5675     };
5676     return pub;
5677 }());
5678
5679 Ext.apply(Ext.Template.prototype, {
5680     
5681     disableFormats : false,
5682     
5683
5684     
5685     re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
5686     argsRe : /^\s*['"](.*)["']\s*$/,
5687     compileARe : /\\/g,
5688     compileBRe : /(\r\n|\n)/g,
5689     compileCRe : /'/g,
5690
5691     /**
5692      * Returns an HTML fragment of this template with the specified values applied.
5693      * @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'})
5694      * @return {String} The HTML fragment
5695      * @hide repeat doc
5696      */
5697     applyTemplate : function(values){
5698         var me = this,
5699             useF = me.disableFormats !== true,
5700             fm = Ext.util.Format,
5701             tpl = me;
5702
5703         if(me.compiled){
5704             return me.compiled(values);
5705         }
5706         function fn(m, name, format, args){
5707             if (format && useF) {
5708                 if (format.substr(0, 5) == "this.") {
5709                     return tpl.call(format.substr(5), values[name], values);
5710                 } else {
5711                     if (args) {
5712                         // quoted values are required for strings in compiled templates,
5713                         // but for non compiled we need to strip them
5714                         // quoted reversed for jsmin
5715                         var re = me.argsRe;
5716                         args = args.split(',');
5717                         for(var i = 0, len = args.length; i < len; i++){
5718                             args[i] = args[i].replace(re, "$1");
5719                         }
5720                         args = [values[name]].concat(args);
5721                     } else {
5722                         args = [values[name]];
5723                     }
5724                     return fm[format].apply(fm, args);
5725                 }
5726             } else {
5727                 return values[name] !== undefined ? values[name] : "";
5728             }
5729         }
5730         return me.html.replace(me.re, fn);
5731     },
5732
5733     /**
5734      * Compiles the template into an internal function, eliminating the RegEx overhead.
5735      * @return {Ext.Template} this
5736      * @hide repeat doc
5737      */
5738     compile : function(){
5739         var me = this,
5740             fm = Ext.util.Format,
5741             useF = me.disableFormats !== true,
5742             sep = Ext.isGecko ? "+" : ",",
5743             body;
5744
5745         function fn(m, name, format, args){
5746             if(format && useF){
5747                 args = args ? ',' + args : "";
5748                 if(format.substr(0, 5) != "this."){
5749                     format = "fm." + format + '(';
5750                 }else{
5751                     format = 'this.call("'+ format.substr(5) + '", ';
5752                     args = ", values";
5753                 }
5754             }else{
5755                 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
5756             }
5757             return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
5758         }
5759
5760         // branched to use + in gecko and [].join() in others
5761         if(Ext.isGecko){
5762             body = "this.compiled = function(values){ return '" +
5763                    me.html.replace(me.compileARe, '\\\\').replace(me.compileBRe, '\\n').replace(me.compileCRe, "\\'").replace(me.re, fn) +
5764                     "';};";
5765         }else{
5766             body = ["this.compiled = function(values){ return ['"];
5767             body.push(me.html.replace(me.compileARe, '\\\\').replace(me.compileBRe, '\\n').replace(me.compileCRe, "\\'").replace(me.re, fn));
5768             body.push("'].join('');};");
5769             body = body.join('');
5770         }
5771         eval(body);
5772         return me;
5773     },
5774
5775     // private function used to call members
5776     call : function(fnName, value, allValues){
5777         return this[fnName](value, allValues);
5778     }
5779 });
5780 Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate;
5781 /**
5782  * @class Ext.util.Functions
5783  * @singleton
5784  */
5785 Ext.util.Functions = {
5786     /**
5787      * Creates an interceptor function. The passed function is called before the original one. If it returns false,
5788      * the original one is not called. The resulting function returns the results of the original function.
5789      * The passed function is called with the parameters of the original function. Example usage:
5790      * <pre><code>
5791 var sayHi = function(name){
5792     alert('Hi, ' + name);
5793 }
5794
5795 sayHi('Fred'); // alerts "Hi, Fred"
5796
5797 // create a new function that validates input without
5798 // directly modifying the original function:
5799 var sayHiToFriend = Ext.createInterceptor(sayHi, function(name){
5800     return name == 'Brian';
5801 });
5802
5803 sayHiToFriend('Fred');  // no alert
5804 sayHiToFriend('Brian'); // alerts "Hi, Brian"
5805        </code></pre>
5806      * @param {Function} origFn The original function.
5807      * @param {Function} newFn The function to call before the original
5808      * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the passed function is executed.
5809      * <b>If omitted, defaults to the scope in which the original function is called or the browser window.</b>
5810      * @return {Function} The new function
5811      */
5812     createInterceptor: function(origFn, newFn, scope) { 
5813         var method = origFn;
5814         if (!Ext.isFunction(newFn)) {
5815             return origFn;
5816         }
5817         else {
5818             return function() {
5819                 var me = this,
5820                     args = arguments;
5821                 newFn.target = me;
5822                 newFn.method = origFn;
5823                 return (newFn.apply(scope || me || window, args) !== false) ?
5824                         origFn.apply(me || window, args) :
5825                         null;
5826             };
5827         }
5828     },
5829
5830     /**
5831      * Creates a delegate (callback) that sets the scope to obj.
5832      * Call directly on any function. Example: <code>Ext.createDelegate(this.myFunction, this, [arg1, arg2])</code>
5833      * Will create a function that is automatically scoped to obj so that the <tt>this</tt> variable inside the
5834      * callback points to obj. Example usage:
5835      * <pre><code>
5836 var sayHi = function(name){
5837     // Note this use of "this.text" here.  This function expects to
5838     // execute within a scope that contains a text property.  In this
5839     // example, the "this" variable is pointing to the btn object that
5840     // was passed in createDelegate below.
5841     alert('Hi, ' + name + '. You clicked the "' + this.text + '" button.');
5842 }
5843
5844 var btn = new Ext.Button({
5845     text: 'Say Hi',
5846     renderTo: Ext.getBody()
5847 });
5848
5849 // This callback will execute in the scope of the
5850 // button instance. Clicking the button alerts
5851 // "Hi, Fred. You clicked the "Say Hi" button."
5852 btn.on('click', Ext.createDelegate(sayHi, btn, ['Fred']));
5853        </code></pre>
5854      * @param {Function} fn The function to delegate.
5855      * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the function is executed.
5856      * <b>If omitted, defaults to the browser window.</b>
5857      * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
5858      * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
5859      * if a number the args are inserted at the specified position
5860      * @return {Function} The new function
5861      */
5862     createDelegate: function(fn, obj, args, appendArgs) {
5863         if (!Ext.isFunction(fn)) {
5864             return fn;
5865         }
5866         return function() {
5867             var callArgs = args || arguments;
5868             if (appendArgs === true) {
5869                 callArgs = Array.prototype.slice.call(arguments, 0);
5870                 callArgs = callArgs.concat(args);
5871             }
5872             else if (Ext.isNumber(appendArgs)) {
5873                 callArgs = Array.prototype.slice.call(arguments, 0);
5874                 // copy arguments first
5875                 var applyArgs = [appendArgs, 0].concat(args);
5876                 // create method call params
5877                 Array.prototype.splice.apply(callArgs, applyArgs);
5878                 // splice them in
5879             }
5880             return fn.apply(obj || window, callArgs);
5881         };
5882     },
5883
5884     /**
5885      * Calls this function after the number of millseconds specified, optionally in a specific scope. Example usage:
5886      * <pre><code>
5887 var sayHi = function(name){
5888     alert('Hi, ' + name);
5889 }
5890
5891 // executes immediately:
5892 sayHi('Fred');
5893
5894 // executes after 2 seconds:
5895 Ext.defer(sayHi, 2000, this, ['Fred']);
5896
5897 // this syntax is sometimes useful for deferring
5898 // execution of an anonymous function:
5899 Ext.defer(function(){
5900     alert('Anonymous');
5901 }, 100);
5902        </code></pre>
5903      * @param {Function} fn The function to defer.
5904      * @param {Number} millis The number of milliseconds for the setTimeout call (if less than or equal to 0 the function is executed immediately)
5905      * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the function is executed.
5906      * <b>If omitted, defaults to the browser window.</b>
5907      * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
5908      * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
5909      * if a number the args are inserted at the specified position
5910      * @return {Number} The timeout id that can be used with clearTimeout
5911      */
5912     defer: function(fn, millis, obj, args, appendArgs) {
5913         fn = Ext.util.Functions.createDelegate(fn, obj, args, appendArgs);
5914         if (millis > 0) {
5915             return setTimeout(fn, millis);
5916         }
5917         fn();
5918         return 0;
5919     },
5920
5921
5922     /**
5923      * Create a combined function call sequence of the original function + the passed function.
5924      * The resulting function returns the results of the original function.
5925      * The passed fcn is called with the parameters of the original function. Example usage:
5926      * 
5927
5928 var sayHi = function(name){
5929     alert('Hi, ' + name);
5930 }
5931
5932 sayHi('Fred'); // alerts "Hi, Fred"
5933
5934 var sayGoodbye = Ext.createSequence(sayHi, function(name){
5935     alert('Bye, ' + name);
5936 });
5937
5938 sayGoodbye('Fred'); // both alerts show
5939
5940      * @param {Function} origFn The original function.
5941      * @param {Function} newFn The function to sequence
5942      * @param {Object} scope (optional) The scope (this reference) in which the passed function is executed.
5943      * If omitted, defaults to the scope in which the original function is called or the browser window.
5944      * @return {Function} The new function
5945      */
5946     createSequence: function(origFn, newFn, scope) {
5947         if (!Ext.isFunction(newFn)) {
5948             return origFn;
5949         }
5950         else {
5951             return function() {
5952                 var retval = origFn.apply(this || window, arguments);
5953                 newFn.apply(scope || this || window, arguments);
5954                 return retval;
5955             };
5956         }
5957     }
5958 };
5959
5960 /**
5961  * Shorthand for {@link Ext.util.Functions#defer}   
5962  * @param {Function} fn The function to defer.
5963  * @param {Number} millis The number of milliseconds for the setTimeout call (if less than or equal to 0 the function is executed immediately)
5964  * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the function is executed.
5965  * <b>If omitted, defaults to the browser window.</b>
5966  * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
5967  * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
5968  * if a number the args are inserted at the specified position
5969  * @return {Number} The timeout id that can be used with clearTimeout
5970  * @member Ext
5971  * @method defer
5972  */
5973
5974 Ext.defer = Ext.util.Functions.defer;
5975
5976 /**
5977  * Shorthand for {@link Ext.util.Functions#createInterceptor}   
5978  * @param {Function} origFn The original function.
5979  * @param {Function} newFn The function to call before the original
5980  * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the passed function is executed.
5981  * <b>If omitted, defaults to the scope in which the original function is called or the browser window.</b>
5982  * @return {Function} The new function
5983  * @member Ext
5984  * @method defer
5985  */
5986
5987 Ext.createInterceptor = Ext.util.Functions.createInterceptor;
5988
5989 /**
5990  * Shorthand for {@link Ext.util.Functions#createSequence}
5991  * @param {Function} origFn The original function.
5992  * @param {Function} newFn The function to sequence
5993  * @param {Object} scope (optional) The scope (this reference) in which the passed function is executed.
5994  * If omitted, defaults to the scope in which the original function is called or the browser window.
5995  * @return {Function} The new function
5996  * @member Ext
5997  * @method defer
5998  */
5999
6000 Ext.createSequence = Ext.util.Functions.createSequence;
6001
6002 /**
6003  * Shorthand for {@link Ext.util.Functions#createDelegate}
6004  * @param {Function} fn The function to delegate.
6005  * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the function is executed.
6006  * <b>If omitted, defaults to the browser window.</b>
6007  * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
6008  * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
6009  * if a number the args are inserted at the specified position
6010  * @return {Function} The new function
6011  * @member Ext
6012  * @method defer
6013  */
6014 Ext.createDelegate = Ext.util.Functions.createDelegate;
6015 /**
6016  * @class Ext.util.Observable
6017  */
6018 Ext.apply(Ext.util.Observable.prototype, function(){
6019     // this is considered experimental (along with beforeMethod, afterMethod, removeMethodListener?)
6020     // allows for easier interceptor and sequences, including cancelling and overwriting the return value of the call
6021     // private
6022     function getMethodEvent(method){
6023         var e = (this.methodEvents = this.methodEvents ||
6024         {})[method], returnValue, v, cancel, obj = this;
6025
6026         if (!e) {
6027             this.methodEvents[method] = e = {};
6028             e.originalFn = this[method];
6029             e.methodName = method;
6030             e.before = [];
6031             e.after = [];
6032
6033             var makeCall = function(fn, scope, args){
6034                 if((v = fn.apply(scope || obj, args)) !== undefined){
6035                     if (typeof v == 'object') {
6036                         if(v.returnValue !== undefined){
6037                             returnValue = v.returnValue;
6038                         }else{
6039                             returnValue = v;
6040                         }
6041                         cancel = !!v.cancel;
6042                     }
6043                     else
6044                         if (v === false) {
6045                             cancel = true;
6046                         }
6047                         else {
6048                             returnValue = v;
6049                         }
6050                 }
6051             };
6052
6053             this[method] = function(){
6054                 var args = Array.prototype.slice.call(arguments, 0),
6055                     b;
6056                 returnValue = v = undefined;
6057                 cancel = false;
6058
6059                 for(var i = 0, len = e.before.length; i < len; i++){
6060                     b = e.before[i];
6061                     makeCall(b.fn, b.scope, args);
6062                     if (cancel) {
6063                         return returnValue;
6064                     }
6065                 }
6066
6067                 if((v = e.originalFn.apply(obj, args)) !== undefined){
6068                     returnValue = v;
6069                 }
6070
6071                 for(var i = 0, len = e.after.length; i < len; i++){
6072                     b = e.after[i];
6073                     makeCall(b.fn, b.scope, args);
6074                     if (cancel) {
6075                         return returnValue;
6076                     }
6077                 }
6078                 return returnValue;
6079             };
6080         }
6081         return e;
6082     }
6083
6084     return {
6085         // these are considered experimental
6086         // allows for easier interceptor and sequences, including cancelling and overwriting the return value of the call
6087         // adds an 'interceptor' called before the original method
6088         beforeMethod : function(method, fn, scope){
6089             getMethodEvent.call(this, method).before.push({
6090                 fn: fn,
6091                 scope: scope
6092             });
6093         },
6094
6095         // adds a 'sequence' called after the original method
6096         afterMethod : function(method, fn, scope){
6097             getMethodEvent.call(this, method).after.push({
6098                 fn: fn,
6099                 scope: scope
6100             });
6101         },
6102
6103         removeMethodListener: function(method, fn, scope){
6104             var e = this.getMethodEvent(method);
6105             for(var i = 0, len = e.before.length; i < len; i++){
6106                 if(e.before[i].fn == fn && e.before[i].scope == scope){
6107                     e.before.splice(i, 1);
6108                     return;
6109                 }
6110             }
6111             for(var i = 0, len = e.after.length; i < len; i++){
6112                 if(e.after[i].fn == fn && e.after[i].scope == scope){
6113                     e.after.splice(i, 1);
6114                     return;
6115                 }
6116             }
6117         },
6118
6119         /**
6120          * Relays selected events from the specified Observable as if the events were fired by <tt><b>this</b></tt>.
6121          * @param {Object} o The Observable whose events this object is to relay.
6122          * @param {Array} events Array of event names to relay.
6123          */
6124         relayEvents : function(o, events){
6125             var me = this;
6126             function createHandler(ename){
6127                 return function(){
6128                     return me.fireEvent.apply(me, [ename].concat(Array.prototype.slice.call(arguments, 0)));
6129                 };
6130             }
6131             for(var i = 0, len = events.length; i < len; i++){
6132                 var ename = events[i];
6133                 me.events[ename] = me.events[ename] || true;
6134                 o.on(ename, createHandler(ename), me);
6135             }
6136         },
6137
6138         /**
6139          * <p>Enables events fired by this Observable to bubble up an owner hierarchy by calling
6140          * <code>this.getBubbleTarget()</code> if present. There is no implementation in the Observable base class.</p>
6141          * <p>This is commonly used by Ext.Components to bubble events to owner Containers. See {@link Ext.Component.getBubbleTarget}. The default
6142          * implementation in Ext.Component returns the Component's immediate owner. But if a known target is required, this can be overridden to
6143          * access the required target more quickly.</p>
6144          * <p>Example:</p><pre><code>
6145 Ext.override(Ext.form.Field, {
6146     
6147     initComponent : Ext.form.Field.prototype.initComponent.createSequence(function() {
6148         this.enableBubble('change');
6149     }),
6150
6151     
6152     getBubbleTarget : function() {
6153         if (!this.formPanel) {
6154             this.formPanel = this.findParentByType('form');
6155         }
6156         return this.formPanel;
6157     }
6158 });
6159
6160 var myForm = new Ext.formPanel({
6161     title: 'User Details',
6162     items: [{
6163         ...
6164     }],
6165     listeners: {
6166         change: function() {
6167             
6168             myForm.header.setStyle('color', 'red');
6169         }
6170     }
6171 });
6172 </code></pre>
6173          * @param {String/Array} events The event name to bubble, or an Array of event names.
6174          */
6175         enableBubble : function(events){
6176             var me = this;
6177             if(!Ext.isEmpty(events)){
6178                 events = Ext.isArray(events) ? events : Array.prototype.slice.call(arguments, 0);
6179                 for(var i = 0, len = events.length; i < len; i++){
6180                     var ename = events[i];
6181                     ename = ename.toLowerCase();
6182                     var ce = me.events[ename] || true;
6183                     if (typeof ce == 'boolean') {
6184                         ce = new Ext.util.Event(me, ename);
6185                         me.events[ename] = ce;
6186                     }
6187                     ce.bubble = true;
6188                 }
6189             }
6190         }
6191     };
6192 }());
6193
6194
6195
6196 Ext.util.Observable.capture = function(o, fn, scope){
6197     o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
6198 };
6199
6200
6201
6202 Ext.util.Observable.observeClass = function(c, listeners){
6203     if(c){
6204       if(!c.fireEvent){
6205           Ext.apply(c, new Ext.util.Observable());
6206           Ext.util.Observable.capture(c.prototype, c.fireEvent, c);
6207       }
6208       if(typeof listeners == 'object'){
6209           c.on(listeners);
6210       }
6211       return c;
6212    }
6213 };
6214
6215 Ext.apply(Ext.EventManager, function(){
6216    var resizeEvent,
6217        resizeTask,
6218        textEvent,
6219        textSize,
6220        D = Ext.lib.Dom,
6221        propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/,
6222        curWidth = 0,
6223        curHeight = 0,
6224        
6225        
6226        
6227        useKeydown = Ext.isWebKit ?
6228                    Ext.num(navigator.userAgent.match(/AppleWebKit\/(\d+)/)[1]) >= 525 :
6229                    !((Ext.isGecko && !Ext.isWindows) || Ext.isOpera);
6230
6231    return {
6232        
6233        doResizeEvent: function(){
6234            var h = D.getViewHeight(),
6235                w = D.getViewWidth();
6236
6237             
6238             if(curHeight != h || curWidth != w){
6239                resizeEvent.fire(curWidth = w, curHeight = h);
6240             }
6241        },
6242
6243        
6244        onWindowResize : function(fn, scope, options){
6245            if(!resizeEvent){
6246                resizeEvent = new Ext.util.Event();
6247                resizeTask = new Ext.util.DelayedTask(this.doResizeEvent);
6248                Ext.EventManager.on(window, "resize", this.fireWindowResize, this);
6249            }
6250            resizeEvent.addListener(fn, scope, options);
6251        },
6252
6253        
6254        fireWindowResize : function(){
6255            if(resizeEvent){
6256                resizeTask.delay(100);
6257            }
6258        },
6259
6260        
6261        onTextResize : function(fn, scope, options){
6262            if(!textEvent){
6263                textEvent = new Ext.util.Event();
6264                var textEl = new Ext.Element(document.createElement('div'));
6265                textEl.dom.className = 'x-text-resize';
6266                textEl.dom.innerHTML = 'X';
6267                textEl.appendTo(document.body);
6268                textSize = textEl.dom.offsetHeight;
6269                setInterval(function(){
6270                    if(textEl.dom.offsetHeight != textSize){
6271                        textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
6272                    }
6273                }, this.textResizeInterval);
6274            }
6275            textEvent.addListener(fn, scope, options);
6276        },
6277
6278        
6279        removeResizeListener : function(fn, scope){
6280            if(resizeEvent){
6281                resizeEvent.removeListener(fn, scope);
6282            }
6283        },
6284
6285        
6286        fireResize : function(){
6287            if(resizeEvent){
6288                resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6289            }
6290        },
6291
6292         
6293        textResizeInterval : 50,
6294
6295        
6296        ieDeferSrc : false,
6297        
6298        
6299        getKeyEvent : function(){
6300            return useKeydown ? 'keydown' : 'keypress';
6301        },
6302
6303        
6304        
6305        useKeydown: useKeydown
6306    };
6307 }());
6308
6309 Ext.EventManager.on = Ext.EventManager.addListener;
6310
6311
6312 Ext.apply(Ext.EventObjectImpl.prototype, {
6313    
6314    BACKSPACE: 8,
6315    
6316    TAB: 9,
6317    
6318    NUM_CENTER: 12,
6319    
6320    ENTER: 13,
6321    
6322    RETURN: 13,
6323    
6324    SHIFT: 16,
6325    
6326    CTRL: 17,
6327    CONTROL : 17, 
6328    
6329    ALT: 18,
6330    
6331    PAUSE: 19,
6332    
6333    CAPS_LOCK: 20,
6334    
6335    ESC: 27,
6336    
6337    SPACE: 32,
6338    
6339    PAGE_UP: 33,
6340    PAGEUP : 33, 
6341    
6342    PAGE_DOWN: 34,
6343    PAGEDOWN : 34, 
6344    
6345    END: 35,
6346    
6347    HOME: 36,
6348    
6349    LEFT: 37,
6350    
6351    UP: 38,
6352    
6353    RIGHT: 39,
6354    
6355    DOWN: 40,
6356    
6357    PRINT_SCREEN: 44,
6358    
6359    INSERT: 45,
6360    
6361    DELETE: 46,
6362    
6363    ZERO: 48,
6364    
6365    ONE: 49,
6366    
6367    TWO: 50,
6368    
6369    THREE: 51,
6370    
6371    FOUR: 52,
6372    
6373    FIVE: 53,
6374    
6375    SIX: 54,
6376    
6377    SEVEN: 55,
6378    
6379    EIGHT: 56,
6380    
6381    NINE: 57,
6382    
6383    A: 65,
6384    
6385    B: 66,
6386    
6387    C: 67,
6388    
6389    D: 68,
6390    
6391    E: 69,
6392    
6393    F: 70,
6394    
6395    G: 71,
6396    
6397    H: 72,
6398    
6399    I: 73,
6400    
6401    J: 74,
6402    
6403    K: 75,
6404    
6405    L: 76,
6406    
6407    M: 77,
6408    
6409    N: 78,
6410    
6411    O: 79,
6412    
6413    P: 80,
6414    
6415    Q: 81,
6416    
6417    R: 82,
6418    
6419    S: 83,
6420    
6421    T: 84,
6422    
6423    U: 85,
6424    
6425    V: 86,
6426    
6427    W: 87,
6428    
6429    X: 88,
6430    
6431    Y: 89,
6432    
6433    Z: 90,
6434    
6435    CONTEXT_MENU: 93,
6436    
6437    NUM_ZERO: 96,
6438    
6439    NUM_ONE: 97,
6440    
6441    NUM_TWO: 98,
6442    
6443    NUM_THREE: 99,
6444    
6445    NUM_FOUR: 100,
6446    
6447    NUM_FIVE: 101,
6448    
6449    NUM_SIX: 102,
6450    
6451    NUM_SEVEN: 103,
6452    
6453    NUM_EIGHT: 104,
6454    
6455    NUM_NINE: 105,
6456    
6457    NUM_MULTIPLY: 106,
6458    
6459    NUM_PLUS: 107,
6460    
6461    NUM_MINUS: 109,
6462    
6463    NUM_PERIOD: 110,
6464    
6465    NUM_DIVISION: 111,
6466    
6467    F1: 112,
6468    
6469    F2: 113,
6470    
6471    F3: 114,
6472    
6473    F4: 115,
6474    
6475    F5: 116,
6476    
6477    F6: 117,
6478    
6479    F7: 118,
6480    
6481    F8: 119,
6482    
6483    F9: 120,
6484    
6485    F10: 121,
6486    
6487    F11: 122,
6488    
6489    F12: 123,
6490
6491    
6492    isNavKeyPress : function(){
6493        var me = this,
6494            k = this.normalizeKey(me.keyCode);
6495        return (k >= 33 && k <= 40) ||  
6496        k == me.RETURN ||
6497        k == me.TAB ||
6498        k == me.ESC;
6499    },
6500
6501    isSpecialKey : function(){
6502        var k = this.normalizeKey(this.keyCode);
6503        return (this.type == 'keypress' && this.ctrlKey) ||
6504        this.isNavKeyPress() ||
6505        (k == this.BACKSPACE) || 
6506        (k >= 16 && k <= 20) || 
6507        (k >= 44 && k <= 46);   
6508    },
6509
6510    getPoint : function(){
6511        return new Ext.lib.Point(this.xy[0], this.xy[1]);
6512    },
6513
6514    
6515    hasModifier : function(){
6516        return ((this.ctrlKey || this.altKey) || this.shiftKey);
6517    }
6518 });
6519 Ext.Element.addMethods({
6520     
6521     swallowEvent : function(eventName, preventDefault) {
6522         var me = this;
6523         function fn(e) {
6524             e.stopPropagation();
6525             if (preventDefault) {
6526                 e.preventDefault();
6527             }
6528         }
6529         
6530         if (Ext.isArray(eventName)) {
6531             Ext.each(eventName, function(e) {
6532                  me.on(e, fn);
6533             });
6534             return me;
6535         }
6536         me.on(eventName, fn);
6537         return me;
6538     },
6539
6540     
6541     relayEvent : function(eventName, observable) {
6542         this.on(eventName, function(e) {
6543             observable.fireEvent(eventName, e);
6544         });
6545     },
6546
6547     
6548     clean : function(forceReclean) {
6549         var me  = this,
6550             dom = me.dom,
6551             n   = dom.firstChild,
6552             ni  = -1;
6553
6554         if (Ext.Element.data(dom, 'isCleaned') && forceReclean !== true) {
6555             return me;
6556         }
6557
6558         while (n) {
6559             var nx = n.nextSibling;
6560             if (n.nodeType == 3 && !(/\S/.test(n.nodeValue))) {
6561                 dom.removeChild(n);
6562             } else {
6563                 n.nodeIndex = ++ni;
6564             }
6565             n = nx;
6566         }
6567         
6568         Ext.Element.data(dom, 'isCleaned', true);
6569         return me;
6570     },
6571
6572     
6573     load : function() {
6574         var updateManager = this.getUpdater();
6575         updateManager.update.apply(updateManager, arguments);
6576         
6577         return this;
6578     },
6579
6580     
6581     getUpdater : function() {
6582         return this.updateManager || (this.updateManager = new Ext.Updater(this));
6583     },
6584
6585     
6586     update : function(html, loadScripts, callback) {
6587         if (!this.dom) {
6588             return this;
6589         }
6590         html = html || "";
6591
6592         if (loadScripts !== true) {
6593             this.dom.innerHTML = html;
6594             if (typeof callback == 'function') {
6595                 callback();
6596             }
6597             return this;
6598         }
6599
6600         var id  = Ext.id(),
6601             dom = this.dom;
6602
6603         html += '<span id="' + id + '"></span>';
6604
6605         Ext.lib.Event.onAvailable(id, function() {
6606             var DOC    = document,
6607                 hd     = DOC.getElementsByTagName("head")[0],
6608                 re     = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig,
6609                 srcRe  = /\ssrc=([\'\"])(.*?)\1/i,
6610                 typeRe = /\stype=([\'\"])(.*?)\1/i,
6611                 match,
6612                 attrs,
6613                 srcMatch,
6614                 typeMatch,
6615                 el,
6616                 s;
6617
6618             while ((match = re.exec(html))) {
6619                 attrs = match[1];
6620                 srcMatch = attrs ? attrs.match(srcRe) : false;
6621                 if (srcMatch && srcMatch[2]) {
6622                    s = DOC.createElement("script");
6623                    s.src = srcMatch[2];
6624                    typeMatch = attrs.match(typeRe);
6625                    if (typeMatch && typeMatch[2]) {
6626                        s.type = typeMatch[2];
6627                    }
6628                    hd.appendChild(s);
6629                 } else if (match[2] && match[2].length > 0) {
6630                     if (window.execScript) {
6631                        window.execScript(match[2]);
6632                     } else {
6633                        window.eval(match[2]);
6634                     }
6635                 }
6636             }
6637             
6638             el = DOC.getElementById(id);
6639             if (el) {
6640                 Ext.removeNode(el);
6641             }
6642             
6643             if (typeof callback == 'function') {
6644                 callback();
6645             }
6646         });
6647         dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
6648         return this;
6649     },
6650
6651     
6652     removeAllListeners : function() {
6653         this.removeAnchor();
6654         Ext.EventManager.removeAll(this.dom);
6655         return this;
6656     },
6657
6658     
6659     createProxy : function(config, renderTo, matchBox) {
6660         config = (typeof config == 'object') ? config : {tag : "div", cls: config};
6661
6662         var me = this,
6663             proxy = renderTo ? Ext.DomHelper.append(renderTo, config, true) :
6664                                Ext.DomHelper.insertBefore(me.dom, config, true);
6665
6666         if (matchBox && me.setBox && me.getBox) { 
6667            proxy.setBox(me.getBox());
6668         }
6669         return proxy;
6670     }
6671 });
6672
6673 Ext.Element.prototype.getUpdateManager = Ext.Element.prototype.getUpdater;
6674
6675 Ext.Element.addMethods({
6676     
6677     getAnchorXY : function(anchor, local, s){
6678         
6679         
6680                 anchor = (anchor || "tl").toLowerCase();
6681         s = s || {};
6682         
6683         var me = this,        
6684                 vp = me.dom == document.body || me.dom == document,
6685                 w = s.width || vp ? Ext.lib.Dom.getViewWidth() : me.getWidth(),
6686                 h = s.height || vp ? Ext.lib.Dom.getViewHeight() : me.getHeight(),                              
6687                 xy,             
6688                 r = Math.round,
6689                 o = me.getXY(),
6690                 scroll = me.getScroll(),
6691                 extraX = vp ? scroll.left : !local ? o[0] : 0,
6692                 extraY = vp ? scroll.top : !local ? o[1] : 0,
6693                 hash = {
6694                         c  : [r(w * 0.5), r(h * 0.5)],
6695                         t  : [r(w * 0.5), 0],
6696                         l  : [0, r(h * 0.5)],
6697                         r  : [w, r(h * 0.5)],
6698                         b  : [r(w * 0.5), h],
6699                         tl : [0, 0],    
6700                         bl : [0, h],
6701                         br : [w, h],
6702                         tr : [w, 0]
6703                 };
6704         
6705         xy = hash[anchor];      
6706         return [xy[0] + extraX, xy[1] + extraY]; 
6707     },
6708
6709     
6710     anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){        
6711             var me = this,
6712             dom = me.dom,
6713             scroll = !Ext.isEmpty(monitorScroll),
6714             action = function(){
6715                 Ext.fly(dom).alignTo(el, alignment, offsets, animate);
6716                 Ext.callback(callback, Ext.fly(dom));
6717             },
6718             anchor = this.getAnchor();
6719             
6720         
6721         this.removeAnchor();
6722         Ext.apply(anchor, {
6723             fn: action,
6724             scroll: scroll
6725         });
6726
6727         Ext.EventManager.onWindowResize(action, null);
6728         
6729         if(scroll){
6730             Ext.EventManager.on(window, 'scroll', action, null,
6731                 {buffer: !isNaN(monitorScroll) ? monitorScroll : 50});
6732         }
6733         action.call(me); 
6734         return me;
6735     },
6736     
6737     
6738     removeAnchor : function(){
6739         var me = this,
6740             anchor = this.getAnchor();
6741             
6742         if(anchor && anchor.fn){
6743             Ext.EventManager.removeResizeListener(anchor.fn);
6744             if(anchor.scroll){
6745                 Ext.EventManager.un(window, 'scroll', anchor.fn);
6746             }
6747             delete anchor.fn;
6748         }
6749         return me;
6750     },
6751     
6752     
6753     getAnchor : function(){
6754         var data = Ext.Element.data,
6755             dom = this.dom;
6756             if (!dom) {
6757                 return;
6758             }
6759             var anchor = data(dom, '_anchor');
6760             
6761         if(!anchor){
6762             anchor = data(dom, '_anchor', {});
6763         }
6764         return anchor;
6765     },
6766
6767     
6768     getAlignToXY : function(el, p, o){      
6769         el = Ext.get(el);
6770         
6771         if(!el || !el.dom){
6772             throw "Element.alignToXY with an element that doesn't exist";
6773         }
6774         
6775         o = o || [0,0];
6776         p = (!p || p == "?" ? "tl-bl?" : (!(/-/).test(p) && p !== "" ? "tl-" + p : p || "tl-bl")).toLowerCase();       
6777                 
6778         var me = this,
6779                 d = me.dom,
6780                 a1,
6781                 a2,
6782                 x,
6783                 y,
6784                 
6785                 w,
6786                 h,
6787                 r,
6788                 dw = Ext.lib.Dom.getViewWidth() -10, 
6789                 dh = Ext.lib.Dom.getViewHeight()-10, 
6790                 p1y,
6791                 p1x,            
6792                 p2y,
6793                 p2x,
6794                 swapY,
6795                 swapX,
6796                 doc = document,
6797                 docElement = doc.documentElement,
6798                 docBody = doc.body,
6799                 scrollX = (docElement.scrollLeft || docBody.scrollLeft || 0)+5,
6800                 scrollY = (docElement.scrollTop || docBody.scrollTop || 0)+5,
6801                 c = false, 
6802                 p1 = "", 
6803                 p2 = "",
6804                 m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
6805         
6806         if(!m){
6807            throw "Element.alignTo with an invalid alignment " + p;
6808         }
6809         
6810         p1 = m[1]; 
6811         p2 = m[2]; 
6812         c = !!m[3];
6813
6814         
6815         
6816         a1 = me.getAnchorXY(p1, true);
6817         a2 = el.getAnchorXY(p2, false);
6818
6819         x = a2[0] - a1[0] + o[0];
6820         y = a2[1] - a1[1] + o[1];
6821
6822         if(c){    
6823                w = me.getWidth();
6824            h = me.getHeight();
6825            r = el.getRegion();       
6826            
6827            
6828            
6829            p1y = p1.charAt(0);
6830            p1x = p1.charAt(p1.length-1);
6831            p2y = p2.charAt(0);
6832            p2x = p2.charAt(p2.length-1);
6833            swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
6834            swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));          
6835            
6836
6837            if (x + w > dw + scrollX) {
6838                 x = swapX ? r.left-w : dw+scrollX-w;
6839            }
6840            if (x < scrollX) {
6841                x = swapX ? r.right : scrollX;
6842            }
6843            if (y + h > dh + scrollY) {
6844                 y = swapY ? r.top-h : dh+scrollY-h;
6845             }
6846            if (y < scrollY){
6847                y = swapY ? r.bottom : scrollY;
6848            }
6849         }
6850         return [x,y];
6851     },
6852
6853     
6854     alignTo : function(element, position, offsets, animate){
6855             var me = this;
6856         return me.setXY(me.getAlignToXY(element, position, offsets),
6857                                 me.preanim && !!animate ? me.preanim(arguments, 3) : false);
6858     },
6859     
6860     
6861     adjustForConstraints : function(xy, parent, offsets){
6862         return this.getConstrainToXY(parent || document, false, offsets, xy) ||  xy;
6863     },
6864
6865     
6866     getConstrainToXY : function(el, local, offsets, proposedXY){   
6867             var os = {top:0, left:0, bottom:0, right: 0};
6868
6869         return function(el, local, offsets, proposedXY){
6870             el = Ext.get(el);
6871             offsets = offsets ? Ext.applyIf(offsets, os) : os;
6872
6873             var vw, vh, vx = 0, vy = 0;
6874             if(el.dom == document.body || el.dom == document){
6875                 vw =Ext.lib.Dom.getViewWidth();
6876                 vh = Ext.lib.Dom.getViewHeight();
6877             }else{
6878                 vw = el.dom.clientWidth;
6879                 vh = el.dom.clientHeight;
6880                 if(!local){
6881                     var vxy = el.getXY();
6882                     vx = vxy[0];
6883                     vy = vxy[1];
6884                 }
6885             }
6886
6887             var s = el.getScroll();
6888
6889             vx += offsets.left + s.left;
6890             vy += offsets.top + s.top;
6891
6892             vw -= offsets.right;
6893             vh -= offsets.bottom;
6894
6895             var vr = vx + vw,
6896                 vb = vy + vh,
6897                 xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]),
6898                 x = xy[0], y = xy[1],
6899                 offset = this.getConstrainOffset(),
6900                 w = this.dom.offsetWidth + offset, 
6901                 h = this.dom.offsetHeight + offset;
6902
6903             
6904             var moved = false;
6905
6906             
6907             if((x + w) > vr){
6908                 x = vr - w;
6909                 moved = true;
6910             }
6911             if((y + h) > vb){
6912                 y = vb - h;
6913                 moved = true;
6914             }
6915             
6916             if(x < vx){
6917                 x = vx;
6918                 moved = true;
6919             }
6920             if(y < vy){
6921                 y = vy;
6922                 moved = true;
6923             }
6924             return moved ? [x, y] : false;
6925         };
6926     }(),
6927             
6928             
6929                 
6930
6931
6932
6933
6934
6935
6936
6937
6938
6939
6940
6941
6942
6943
6944
6945
6946
6947
6948
6949
6950
6951
6952
6953
6954
6955
6956
6957
6958
6959
6960
6961
6962
6963
6964
6965
6966
6967
6968
6969
6970
6971
6972
6973
6974
6975
6976
6977
6978
6979
6980
6981
6982
6983     
6984     getConstrainOffset : function(){
6985         return 0;
6986     },
6987     
6988     
6989     getCenterXY : function(){
6990         return this.getAlignToXY(document, 'c-c');
6991     },
6992
6993     
6994     center : function(centerIn){
6995         return this.alignTo(centerIn || document, 'c-c');        
6996     }    
6997 });
6998
6999 Ext.Element.addMethods({
7000     
7001     select : function(selector, unique){
7002         return Ext.Element.select(selector, unique, this.dom);
7003     }
7004 });
7005 Ext.apply(Ext.Element.prototype, function() {
7006         var GETDOM = Ext.getDom,
7007                 GET = Ext.get,
7008                 DH = Ext.DomHelper;
7009         
7010         return {        
7011                 
7012             insertSibling: function(el, where, returnDom){
7013                 var me = this,
7014                         rt,
7015                 isAfter = (where || 'before').toLowerCase() == 'after',
7016                 insertEl;
7017                         
7018                 if(Ext.isArray(el)){
7019                 insertEl = me;
7020                     Ext.each(el, function(e) {
7021                             rt = Ext.fly(insertEl, '_internal').insertSibling(e, where, returnDom);
7022                     if(isAfter){
7023                         insertEl = rt;
7024                     }
7025                     });
7026                     return rt;
7027                 }
7028                         
7029                 el = el || {};
7030                 
7031             if(el.nodeType || el.dom){
7032                 rt = me.dom.parentNode.insertBefore(GETDOM(el), isAfter ? me.dom.nextSibling : me.dom);
7033                 if (!returnDom) {
7034                     rt = GET(rt);
7035                 }
7036             }else{
7037                 if (isAfter && !me.dom.nextSibling) {
7038                     rt = DH.append(me.dom.parentNode, el, !returnDom);
7039                 } else {                    
7040                     rt = DH[isAfter ? 'insertAfter' : 'insertBefore'](me.dom, el, !returnDom);
7041                 }
7042             }
7043                 return rt;
7044             }
7045     };
7046 }());
7047
7048
7049 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>';
7050
7051 Ext.Element.addMethods(function(){
7052     var INTERNAL = "_internal",
7053         pxMatch = /(\d+\.?\d+)px/;
7054     return {
7055         
7056         applyStyles : function(style){
7057             Ext.DomHelper.applyStyles(this.dom, style);
7058             return this;
7059         },
7060
7061         
7062         getStyles : function(){
7063             var ret = {};
7064             Ext.each(arguments, function(v) {
7065                ret[v] = this.getStyle(v);
7066             },
7067             this);
7068             return ret;
7069         },
7070
7071         
7072         setOverflow : function(v){
7073             var dom = this.dom;
7074             if(v=='auto' && Ext.isMac && Ext.isGecko2){ 
7075                 dom.style.overflow = 'hidden';
7076                 (function(){dom.style.overflow = 'auto';}).defer(1);
7077             }else{
7078                 dom.style.overflow = v;
7079             }
7080         },
7081
7082        
7083         boxWrap : function(cls){
7084             cls = cls || 'x-box';
7085             var el = Ext.get(this.insertHtml("beforeBegin", "<div class='" + cls + "'>" + String.format(Ext.Element.boxMarkup, cls) + "</div>"));        
7086             Ext.DomQuery.selectNode('.' + cls + '-mc', el.dom).appendChild(this.dom);
7087             return el;
7088         },
7089
7090         
7091         setSize : function(width, height, animate){
7092             var me = this;
7093             if(typeof width == 'object'){ 
7094                 height = width.height;
7095                 width = width.width;
7096             }
7097             width = me.adjustWidth(width);
7098             height = me.adjustHeight(height);
7099             if(!animate || !me.anim){
7100                 me.dom.style.width = me.addUnits(width);
7101                 me.dom.style.height = me.addUnits(height);
7102             }else{
7103                 me.anim({width: {to: width}, height: {to: height}}, me.preanim(arguments, 2));
7104             }
7105             return me;
7106         },
7107
7108         
7109         getComputedHeight : function(){
7110             var me = this,
7111                 h = Math.max(me.dom.offsetHeight, me.dom.clientHeight);
7112             if(!h){
7113                 h = parseFloat(me.getStyle('height')) || 0;
7114                 if(!me.isBorderBox()){
7115                     h += me.getFrameWidth('tb');
7116                 }
7117             }
7118             return h;
7119         },
7120
7121         
7122         getComputedWidth : function(){
7123             var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
7124             if(!w){
7125                 w = parseFloat(this.getStyle('width')) || 0;
7126                 if(!this.isBorderBox()){
7127                     w += this.getFrameWidth('lr');
7128                 }
7129             }
7130             return w;
7131         },
7132
7133         
7134         getFrameWidth : function(sides, onlyContentBox){
7135             return onlyContentBox && this.isBorderBox() ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
7136         },
7137
7138         
7139         addClassOnOver : function(className){
7140             this.hover(
7141                 function(){
7142                     Ext.fly(this, INTERNAL).addClass(className);
7143                 },
7144                 function(){
7145                     Ext.fly(this, INTERNAL).removeClass(className);
7146                 }
7147             );
7148             return this;
7149         },
7150
7151         
7152         addClassOnFocus : function(className){
7153             this.on("focus", function(){
7154                 Ext.fly(this, INTERNAL).addClass(className);
7155             }, this.dom);
7156             this.on("blur", function(){
7157                 Ext.fly(this, INTERNAL).removeClass(className);
7158             }, this.dom);
7159             return this;
7160         },
7161
7162         
7163         addClassOnClick : function(className){
7164             var dom = this.dom;
7165             this.on("mousedown", function(){
7166                 Ext.fly(dom, INTERNAL).addClass(className);
7167                 var d = Ext.getDoc(),
7168                     fn = function(){
7169                         Ext.fly(dom, INTERNAL).removeClass(className);
7170                         d.removeListener("mouseup", fn);
7171                     };
7172                 d.on("mouseup", fn);
7173             });
7174             return this;
7175         },
7176
7177         
7178
7179         getViewSize : function(){
7180             var doc = document,
7181                 d = this.dom,
7182                 isDoc = (d == doc || d == doc.body);
7183
7184             
7185             if (isDoc) {
7186                 var extdom = Ext.lib.Dom;
7187                 return {
7188                     width : extdom.getViewWidth(),
7189                     height : extdom.getViewHeight()
7190                 };
7191
7192             
7193             } else {
7194                 return {
7195                     width : d.clientWidth,
7196                     height : d.clientHeight
7197                 };
7198             }
7199         },
7200
7201         
7202
7203         getStyleSize : function(){
7204             var me = this,
7205                 w, h,
7206                 doc = document,
7207                 d = this.dom,
7208                 isDoc = (d == doc || d == doc.body),
7209                 s = d.style;
7210
7211             
7212             if (isDoc) {
7213                 var extdom = Ext.lib.Dom;
7214                 return {
7215                     width : extdom.getViewWidth(),
7216                     height : extdom.getViewHeight()
7217                 };
7218             }
7219             
7220             if(s.width && s.width != 'auto'){
7221                 w = parseFloat(s.width);
7222                 if(me.isBorderBox()){
7223                    w -= me.getFrameWidth('lr');
7224                 }
7225             }
7226             
7227             if(s.height && s.height != 'auto'){
7228                 h = parseFloat(s.height);
7229                 if(me.isBorderBox()){
7230                    h -= me.getFrameWidth('tb');
7231                 }
7232             }
7233             
7234             return {width: w || me.getWidth(true), height: h || me.getHeight(true)};
7235         },
7236
7237         
7238         getSize : function(contentSize){
7239             return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
7240         },
7241
7242         
7243         repaint : function(){
7244             var dom = this.dom;
7245             this.addClass("x-repaint");
7246             setTimeout(function(){
7247                 Ext.fly(dom).removeClass("x-repaint");
7248             }, 1);
7249             return this;
7250         },
7251
7252         
7253         unselectable : function(){
7254             this.dom.unselectable = "on";
7255             return this.swallowEvent("selectstart", true).
7256                         applyStyles("-moz-user-select:none;-khtml-user-select:none;").
7257                         addClass("x-unselectable");
7258         },
7259
7260         
7261         getMargins : function(side){
7262             var me = this,
7263                 key,
7264                 hash = {t:"top", l:"left", r:"right", b: "bottom"},
7265                 o = {};
7266
7267             if (!side) {
7268                 for (key in me.margins){
7269                     o[hash[key]] = parseFloat(me.getStyle(me.margins[key])) || 0;
7270                 }
7271                 return o;
7272             } else {
7273                 return me.addStyles.call(me, side, me.margins);
7274             }
7275         }
7276     };
7277 }());
7278
7279 Ext.Element.addMethods({
7280     
7281     setBox : function(box, adjust, animate){
7282         var me = this,
7283                 w = box.width, 
7284                 h = box.height;
7285         if((adjust && !me.autoBoxAdjust) && !me.isBorderBox()){
7286            w -= (me.getBorderWidth("lr") + me.getPadding("lr"));
7287            h -= (me.getBorderWidth("tb") + me.getPadding("tb"));
7288         }
7289         me.setBounds(box.x, box.y, w, h, me.animTest.call(me, arguments, animate, 2));
7290         return me;
7291     },
7292
7293     
7294         getBox : function(contentBox, local) {      
7295             var me = this,
7296                 xy,
7297                 left,
7298                 top,
7299                 getBorderWidth = me.getBorderWidth,
7300                 getPadding = me.getPadding, 
7301                 l,
7302                 r,
7303                 t,
7304                 b;
7305         if(!local){
7306             xy = me.getXY();
7307         }else{
7308             left = parseInt(me.getStyle("left"), 10) || 0;
7309             top = parseInt(me.getStyle("top"), 10) || 0;
7310             xy = [left, top];
7311         }
7312         var el = me.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
7313         if(!contentBox){
7314             bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
7315         }else{
7316             l = getBorderWidth.call(me, "l") + getPadding.call(me, "l");
7317             r = getBorderWidth.call(me, "r") + getPadding.call(me, "r");
7318             t = getBorderWidth.call(me, "t") + getPadding.call(me, "t");
7319             b = getBorderWidth.call(me, "b") + getPadding.call(me, "b");
7320             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)};
7321         }
7322         bx.right = bx.x + bx.width;
7323         bx.bottom = bx.y + bx.height;
7324         return bx;
7325         },
7326         
7327     
7328      move : function(direction, distance, animate){
7329         var me = this,          
7330                 xy = me.getXY(),
7331                 x = xy[0],
7332                 y = xy[1],              
7333                 left = [x - distance, y],
7334                 right = [x + distance, y],
7335                 top = [x, y - distance],
7336                 bottom = [x, y + distance],
7337                 hash = {
7338                         l :     left,
7339                         left : left,
7340                         r : right,
7341                         right : right,
7342                         t : top,
7343                         top : top,
7344                         up : top,
7345                         b : bottom, 
7346                         bottom : bottom,
7347                         down : bottom                           
7348                 };
7349         
7350             direction = direction.toLowerCase();    
7351             me.moveTo(hash[direction][0], hash[direction][1], me.animTest.call(me, arguments, animate, 2));
7352     },
7353     
7354     
7355      setLeftTop : function(left, top){
7356             var me = this,
7357                 style = me.dom.style;
7358         style.left = me.addUnits(left);
7359         style.top = me.addUnits(top);
7360         return me;
7361     },
7362     
7363     
7364     getRegion : function(){
7365         return Ext.lib.Dom.getRegion(this.dom);
7366     },
7367     
7368     
7369     setBounds : function(x, y, width, height, animate){
7370             var me = this;
7371         if (!animate || !me.anim) {
7372             me.setSize(width, height);
7373             me.setLocation(x, y);
7374         } else {
7375             me.anim({points: {to: [x, y]}, 
7376                          width: {to: me.adjustWidth(width)}, 
7377                          height: {to: me.adjustHeight(height)}},
7378                      me.preanim(arguments, 4), 
7379                      'motion');
7380         }
7381         return me;
7382     },
7383
7384     
7385     setRegion : function(region, animate) {
7386         return this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.animTest.call(this, arguments, animate, 1));
7387     }
7388 });
7389 Ext.Element.addMethods({
7390     
7391     scrollTo : function(side, value, animate) {
7392         
7393         var top = /top/i.test(side),
7394             me = this,
7395             dom = me.dom,
7396             prop;
7397         if (!animate || !me.anim) {
7398             
7399             prop = 'scroll' + (top ? 'Top' : 'Left');
7400             dom[prop] = value;
7401         }
7402         else {
7403             
7404             prop = 'scroll' + (top ? 'Left' : 'Top');
7405             me.anim({scroll: {to: top ? [dom[prop], value] : [value, dom[prop]]}}, me.preanim(arguments, 2), 'scroll');
7406         }
7407         return me;
7408     },
7409     
7410     
7411     scrollIntoView : function(container, hscroll) {
7412         var c = Ext.getDom(container) || Ext.getBody().dom,
7413             el = this.dom,
7414             o = this.getOffsetsTo(c),
7415             l = o[0] + c.scrollLeft,
7416             t = o[1] + c.scrollTop,
7417             b = t + el.offsetHeight,
7418             r = l + el.offsetWidth,
7419             ch = c.clientHeight,
7420             ct = parseInt(c.scrollTop, 10),
7421             cl = parseInt(c.scrollLeft, 10),
7422             cb = ct + ch,
7423             cr = cl + c.clientWidth;
7424
7425         if (el.offsetHeight > ch || t < ct) {
7426             c.scrollTop = t;
7427         }
7428         else if (b > cb) {
7429             c.scrollTop = b-ch;
7430         }
7431         
7432         c.scrollTop = c.scrollTop;
7433
7434         if (hscroll !== false) {
7435             if (el.offsetWidth > c.clientWidth || l < cl) {
7436                 c.scrollLeft = l;
7437             }
7438             else if (r > cr) {
7439                 c.scrollLeft = r - c.clientWidth;
7440             }
7441             c.scrollLeft = c.scrollLeft;
7442         }
7443         return this;
7444     },
7445
7446     
7447     scrollChildIntoView : function(child, hscroll) {
7448         Ext.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
7449     },
7450     
7451     
7452      scroll : function(direction, distance, animate) {
7453         if (!this.isScrollable()) {
7454             return false;
7455         }
7456         var el = this.dom,
7457             l = el.scrollLeft, t = el.scrollTop,
7458             w = el.scrollWidth, h = el.scrollHeight,
7459             cw = el.clientWidth, ch = el.clientHeight,
7460             scrolled = false, v,
7461             hash = {
7462                 l: Math.min(l + distance, w-cw),
7463                 r: v = Math.max(l - distance, 0),
7464                 t: Math.max(t - distance, 0),
7465                 b: Math.min(t + distance, h-ch)
7466             };
7467             hash.d = hash.b;
7468             hash.u = hash.t;
7469         
7470         direction = direction.substr(0, 1);
7471         if ((v = hash[direction]) > -1) {
7472             scrolled = true;
7473             this.scrollTo(direction == 'l' || direction == 'r' ? 'left' : 'top', v, this.preanim(arguments, 2));
7474         }
7475         return scrolled;
7476     }
7477 });
7478 Ext.Element.addMethods(
7479     function() {
7480         var VISIBILITY      = "visibility",
7481             DISPLAY         = "display",
7482             HIDDEN          = "hidden",
7483             NONE            = "none",
7484             XMASKED         = "x-masked",
7485             XMASKEDRELATIVE = "x-masked-relative",
7486             data            = Ext.Element.data;
7487
7488         return {
7489             
7490             isVisible : function(deep) {
7491                 var vis = !this.isStyle(VISIBILITY, HIDDEN) && !this.isStyle(DISPLAY, NONE),
7492                     p   = this.dom.parentNode;
7493                 
7494                 if (deep !== true || !vis) {
7495                     return vis;
7496                 }
7497                 
7498                 while (p && !(/^body/i.test(p.tagName))) {
7499                     if (!Ext.fly(p, '_isVisible').isVisible()) {
7500                         return false;
7501                     }
7502                     p = p.parentNode;
7503                 }
7504                 return true;
7505             },
7506
7507             
7508             isDisplayed : function() {
7509                 return !this.isStyle(DISPLAY, NONE);
7510             },
7511
7512             
7513             enableDisplayMode : function(display) {
7514                 this.setVisibilityMode(Ext.Element.DISPLAY);
7515                 
7516                 if (!Ext.isEmpty(display)) {
7517                     data(this.dom, 'originalDisplay', display);
7518                 }
7519                 
7520                 return this;
7521             },
7522
7523             
7524             mask : function(msg, msgCls) {
7525                 var me  = this,
7526                     dom = me.dom,
7527                     dh  = Ext.DomHelper,
7528                     EXTELMASKMSG = "ext-el-mask-msg",
7529                     el,
7530                     mask;
7531
7532                 if (!(/^body/i.test(dom.tagName) && me.getStyle('position') == 'static')) {
7533                     me.addClass(XMASKEDRELATIVE);
7534                 }
7535                 if (el = data(dom, 'maskMsg')) {
7536                     el.remove();
7537                 }
7538                 if (el = data(dom, 'mask')) {
7539                     el.remove();
7540                 }
7541
7542                 mask = dh.append(dom, {cls : "ext-el-mask"}, true);
7543                 data(dom, 'mask', mask);
7544
7545                 me.addClass(XMASKED);
7546                 mask.setDisplayed(true);
7547                 
7548                 if (typeof msg == 'string') {
7549                     var mm = dh.append(dom, {cls : EXTELMASKMSG, cn:{tag:'div'}}, true);
7550                     data(dom, 'maskMsg', mm);
7551                     mm.dom.className = msgCls ? EXTELMASKMSG + " " + msgCls : EXTELMASKMSG;
7552                     mm.dom.firstChild.innerHTML = msg;
7553                     mm.setDisplayed(true);
7554                     mm.center(me);
7555                 }
7556                 
7557                 
7558                 if (Ext.isIE && !(Ext.isIE7 && Ext.isStrict) && me.getStyle('height') == 'auto') {
7559                     mask.setSize(undefined, me.getHeight());
7560                 }
7561                 
7562                 return mask;
7563             },
7564
7565             
7566             unmask : function() {
7567                 var me      = this,
7568                     dom     = me.dom,
7569                     mask    = data(dom, 'mask'),
7570                     maskMsg = data(dom, 'maskMsg');
7571
7572                 if (mask) {
7573                     if (maskMsg) {
7574                         maskMsg.remove();
7575                         data(dom, 'maskMsg', undefined);
7576                     }
7577                     
7578                     mask.remove();
7579                     data(dom, 'mask', undefined);
7580                     me.removeClass([XMASKED, XMASKEDRELATIVE]);
7581                 }
7582             },
7583
7584             
7585             isMasked : function() {
7586                 var m = data(this.dom, 'mask');
7587                 return m && m.isVisible();
7588             },
7589
7590             
7591             createShim : function() {
7592                 var el = document.createElement('iframe'),
7593                     shim;
7594                 
7595                 el.frameBorder = '0';
7596                 el.className = 'ext-shim';
7597                 el.src = Ext.SSL_SECURE_URL;
7598                 shim = Ext.get(this.dom.parentNode.insertBefore(el, this.dom));
7599                 shim.autoBoxAdjust = false;
7600                 return shim;
7601             }
7602         };
7603     }()
7604 );
7605 Ext.Element.addMethods({
7606     
7607     addKeyListener : function(key, fn, scope){
7608         var config;
7609         if(typeof key != 'object' || Ext.isArray(key)){
7610             config = {
7611                 key: key,
7612                 fn: fn,
7613                 scope: scope
7614             };
7615         }else{
7616             config = {
7617                 key : key.key,
7618                 shift : key.shift,
7619                 ctrl : key.ctrl,
7620                 alt : key.alt,
7621                 fn: fn,
7622                 scope: scope
7623             };
7624         }
7625         return new Ext.KeyMap(this, config);
7626     },
7627
7628     
7629     addKeyMap : function(config){
7630         return new Ext.KeyMap(this, config);
7631     }
7632 });
7633
7634
7635
7636 Ext.CompositeElementLite.importElementMethods();
7637 Ext.apply(Ext.CompositeElementLite.prototype, {
7638     addElements : function(els, root){
7639         if(!els){
7640             return this;
7641         }
7642         if(typeof els == "string"){
7643             els = Ext.Element.selectorFunction(els, root);
7644         }
7645         var yels = this.elements;
7646         Ext.each(els, function(e) {
7647             yels.push(Ext.get(e));
7648         });
7649         return this;
7650     },
7651
7652     
7653     first : function(){
7654         return this.item(0);
7655     },
7656
7657     
7658     last : function(){
7659         return this.item(this.getCount()-1);
7660     },
7661
7662     
7663     contains : function(el){
7664         return this.indexOf(el) != -1;
7665     },
7666
7667     
7668     removeElement : function(keys, removeDom){
7669         var me = this,
7670             els = this.elements,
7671             el;
7672         Ext.each(keys, function(val){
7673             if ((el = (els[val] || els[val = me.indexOf(val)]))) {
7674                 if(removeDom){
7675                     if(el.dom){
7676                         el.remove();
7677                     }else{
7678                         Ext.removeNode(el);
7679                     }
7680                 }
7681                 els.splice(val, 1);
7682             }
7683         });
7684         return this;
7685     }
7686 });
7687
7688 Ext.CompositeElement = Ext.extend(Ext.CompositeElementLite, {
7689     
7690     constructor : function(els, root){
7691         this.elements = [];
7692         this.add(els, root);
7693     },
7694     
7695     
7696     getElement : function(el){
7697         
7698         return el;
7699     },
7700     
7701     
7702     transformElement : function(el){
7703         return Ext.get(el);
7704     }
7705
7706     
7707
7708     
7709
7710     
7711 });
7712
7713
7714 Ext.Element.select = function(selector, unique, root){
7715     var els;
7716     if(typeof selector == "string"){
7717         els = Ext.Element.selectorFunction(selector, root);
7718     }else if(selector.length !== undefined){
7719         els = selector;
7720     }else{
7721         throw "Invalid selector";
7722     }
7723
7724     return (unique === true) ? new Ext.CompositeElement(els) : new Ext.CompositeElementLite(els);
7725 };
7726
7727
7728 Ext.select = Ext.Element.select;
7729 Ext.UpdateManager = Ext.Updater = Ext.extend(Ext.util.Observable,
7730 function() {
7731     var BEFOREUPDATE = "beforeupdate",
7732         UPDATE = "update",
7733         FAILURE = "failure";
7734
7735     
7736     function processSuccess(response){
7737         var me = this;
7738         me.transaction = null;
7739         if (response.argument.form && response.argument.reset) {
7740             try { 
7741                 response.argument.form.reset();
7742             } catch(e){}
7743         }
7744         if (me.loadScripts) {
7745             me.renderer.render(me.el, response, me,
7746                updateComplete.createDelegate(me, [response]));
7747         } else {
7748             me.renderer.render(me.el, response, me);
7749             updateComplete.call(me, response);
7750         }
7751     }
7752
7753     
7754     function updateComplete(response, type, success){
7755         this.fireEvent(type || UPDATE, this.el, response);
7756         if(Ext.isFunction(response.argument.callback)){
7757             response.argument.callback.call(response.argument.scope, this.el, Ext.isEmpty(success) ? true : false, response, response.argument.options);
7758         }
7759     }
7760
7761     
7762     function processFailure(response){
7763         updateComplete.call(this, response, FAILURE, !!(this.transaction = null));
7764     }
7765
7766     return {
7767         constructor: function(el, forceNew){
7768             var me = this;
7769             el = Ext.get(el);
7770             if(!forceNew && el.updateManager){
7771                 return el.updateManager;
7772             }
7773             
7774             me.el = el;
7775             
7776             me.defaultUrl = null;
7777
7778             me.addEvents(
7779                 
7780                 BEFOREUPDATE,
7781                 
7782                 UPDATE,
7783                 
7784                 FAILURE
7785             );
7786
7787             Ext.apply(me, Ext.Updater.defaults);
7788             
7789             
7790             
7791             
7792             
7793             
7794
7795             
7796             me.transaction = null;
7797             
7798             me.refreshDelegate = me.refresh.createDelegate(me);
7799             
7800             me.updateDelegate = me.update.createDelegate(me);
7801             
7802             me.formUpdateDelegate = (me.formUpdate || function(){}).createDelegate(me);
7803
7804             
7805             me.renderer = me.renderer || me.getDefaultRenderer();
7806
7807             Ext.Updater.superclass.constructor.call(me);
7808         },
7809
7810         
7811         setRenderer : function(renderer){
7812             this.renderer = renderer;
7813         },
7814
7815         
7816         getRenderer : function(){
7817            return this.renderer;
7818         },
7819
7820         
7821         getDefaultRenderer: function() {
7822             return new Ext.Updater.BasicRenderer();
7823         },
7824
7825         
7826         setDefaultUrl : function(defaultUrl){
7827             this.defaultUrl = defaultUrl;
7828         },
7829
7830         
7831         getEl : function(){
7832             return this.el;
7833         },
7834
7835         
7836         update : function(url, params, callback, discardUrl){
7837             var me = this,
7838                 cfg,
7839                 callerScope;
7840
7841             if(me.fireEvent(BEFOREUPDATE, me.el, url, params) !== false){
7842                 if(Ext.isObject(url)){ 
7843                     cfg = url;
7844                     url = cfg.url;
7845                     params = params || cfg.params;
7846                     callback = callback || cfg.callback;
7847                     discardUrl = discardUrl || cfg.discardUrl;
7848                     callerScope = cfg.scope;
7849                     if(!Ext.isEmpty(cfg.nocache)){me.disableCaching = cfg.nocache;};
7850                     if(!Ext.isEmpty(cfg.text)){me.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
7851                     if(!Ext.isEmpty(cfg.scripts)){me.loadScripts = cfg.scripts;};
7852                     if(!Ext.isEmpty(cfg.timeout)){me.timeout = cfg.timeout;};
7853                 }
7854                 me.showLoading();
7855
7856                 if(!discardUrl){
7857                     me.defaultUrl = url;
7858                 }
7859                 if(Ext.isFunction(url)){
7860                     url = url.call(me);
7861                 }
7862
7863                 var o = Ext.apply({}, {
7864                     url : url,
7865                     params: (Ext.isFunction(params) && callerScope) ? params.createDelegate(callerScope) : params,
7866                     success: processSuccess,
7867                     failure: processFailure,
7868                     scope: me,
7869                     callback: undefined,
7870                     timeout: (me.timeout*1000),
7871                     disableCaching: me.disableCaching,
7872                     argument: {
7873                         "options": cfg,
7874                         "url": url,
7875                         "form": null,
7876                         "callback": callback,
7877                         "scope": callerScope || window,
7878                         "params": params
7879                     }
7880                 }, cfg);
7881
7882                 me.transaction = Ext.Ajax.request(o);
7883             }
7884         },
7885
7886         
7887         formUpdate : function(form, url, reset, callback){
7888             var me = this;
7889             if(me.fireEvent(BEFOREUPDATE, me.el, form, url) !== false){
7890                 if(Ext.isFunction(url)){
7891                     url = url.call(me);
7892                 }
7893                 form = Ext.getDom(form);
7894                 me.transaction = Ext.Ajax.request({
7895                     form: form,
7896                     url:url,
7897                     success: processSuccess,
7898                     failure: processFailure,
7899                     scope: me,
7900                     timeout: (me.timeout*1000),
7901                     argument: {
7902                         "url": url,
7903                         "form": form,
7904                         "callback": callback,
7905                         "reset": reset
7906                     }
7907                 });
7908                 me.showLoading.defer(1, me);
7909             }
7910         },
7911
7912         
7913         startAutoRefresh : function(interval, url, params, callback, refreshNow){
7914             var me = this;
7915             if(refreshNow){
7916                 me.update(url || me.defaultUrl, params, callback, true);
7917             }
7918             if(me.autoRefreshProcId){
7919                 clearInterval(me.autoRefreshProcId);
7920             }
7921             me.autoRefreshProcId = setInterval(me.update.createDelegate(me, [url || me.defaultUrl, params, callback, true]), interval * 1000);
7922         },
7923
7924         
7925         stopAutoRefresh : function(){
7926             if(this.autoRefreshProcId){
7927                 clearInterval(this.autoRefreshProcId);
7928                 delete this.autoRefreshProcId;
7929             }
7930         },
7931
7932         
7933         isAutoRefreshing : function(){
7934            return !!this.autoRefreshProcId;
7935         },
7936
7937         
7938         showLoading : function(){
7939             if(this.showLoadIndicator){
7940                 this.el.dom.innerHTML = this.indicatorText;
7941             }
7942         },
7943
7944         
7945         abort : function(){
7946             if(this.transaction){
7947                 Ext.Ajax.abort(this.transaction);
7948             }
7949         },
7950
7951         
7952         isUpdating : function(){
7953             return this.transaction ? Ext.Ajax.isLoading(this.transaction) : false;
7954         },
7955
7956         
7957         refresh : function(callback){
7958             if(this.defaultUrl){
7959                 this.update(this.defaultUrl, null, callback, true);
7960             }
7961         }
7962     };
7963 }());
7964
7965
7966 Ext.Updater.defaults = {
7967    
7968     timeout : 30,
7969     
7970     disableCaching : false,
7971     
7972     showLoadIndicator : true,
7973     
7974     indicatorText : '<div class="loading-indicator">Loading...</div>',
7975      
7976     loadScripts : false,
7977     
7978     sslBlankUrl : Ext.SSL_SECURE_URL
7979 };
7980
7981
7982
7983 Ext.Updater.updateElement = function(el, url, params, options){
7984     var um = Ext.get(el).getUpdater();
7985     Ext.apply(um, options);
7986     um.update(url, params, options ? options.callback : null);
7987 };
7988
7989
7990 Ext.Updater.BasicRenderer = function(){};
7991
7992 Ext.Updater.BasicRenderer.prototype = {
7993     
7994      render : function(el, response, updateManager, callback){
7995         el.update(response.responseText, updateManager.loadScripts, callback);
7996     }
7997 };
7998
7999
8000
8001 (function() {
8002
8003
8004 Date.useStrict = false;
8005
8006
8007
8008
8009
8010 function xf(format) {
8011     var args = Array.prototype.slice.call(arguments, 1);
8012     return format.replace(/\{(\d+)\}/g, function(m, i) {
8013         return args[i];
8014     });
8015 }
8016
8017
8018
8019 Date.formatCodeToRegex = function(character, currentGroup) {
8020     
8021     var p = Date.parseCodes[character];
8022
8023     if (p) {
8024       p = typeof p == 'function'? p() : p;
8025       Date.parseCodes[character] = p; 
8026     }
8027
8028     return p ? Ext.applyIf({
8029       c: p.c ? xf(p.c, currentGroup || "{0}") : p.c
8030     }, p) : {
8031         g:0,
8032         c:null,
8033         s:Ext.escapeRe(character) 
8034     };
8035 };
8036
8037
8038 var $f = Date.formatCodeToRegex;
8039
8040 Ext.apply(Date, {
8041     
8042     parseFunctions: {
8043         "M$": function(input, strict) {
8044             
8045             
8046             var re = new RegExp('\\/Date\\(([-+])?(\\d+)(?:[+-]\\d{4})?\\)\\/');
8047             var r = (input || '').match(re);
8048             return r? new Date(((r[1] || '') + r[2]) * 1) : null;
8049         }
8050     },
8051     parseRegexes: [],
8052
8053     
8054     formatFunctions: {
8055         "M$": function() {
8056             
8057             return '\\/Date(' + this.getTime() + ')\\/';
8058         }
8059     },
8060
8061     y2kYear : 50,
8062
8063     
8064     MILLI : "ms",
8065
8066     
8067     SECOND : "s",
8068
8069     
8070     MINUTE : "mi",
8071
8072     
8073     HOUR : "h",
8074
8075     
8076     DAY : "d",
8077
8078     
8079     MONTH : "mo",
8080
8081     
8082     YEAR : "y",
8083
8084     
8085     defaults: {},
8086
8087     
8088     dayNames : [
8089         "Sunday",
8090         "Monday",
8091         "Tuesday",
8092         "Wednesday",
8093         "Thursday",
8094         "Friday",
8095         "Saturday"
8096     ],
8097
8098     
8099     monthNames : [
8100         "January",
8101         "February",
8102         "March",
8103         "April",
8104         "May",
8105         "June",
8106         "July",
8107         "August",
8108         "September",
8109         "October",
8110         "November",
8111         "December"
8112     ],
8113
8114     
8115     monthNumbers : {
8116         Jan:0,
8117         Feb:1,
8118         Mar:2,
8119         Apr:3,
8120         May:4,
8121         Jun:5,
8122         Jul:6,
8123         Aug:7,
8124         Sep:8,
8125         Oct:9,
8126         Nov:10,
8127         Dec:11
8128     },
8129
8130     
8131     getShortMonthName : function(month) {
8132         return Date.monthNames[month].substring(0, 3);
8133     },
8134
8135     
8136     getShortDayName : function(day) {
8137         return Date.dayNames[day].substring(0, 3);
8138     },
8139
8140     
8141     getMonthNumber : function(name) {
8142         
8143         return Date.monthNumbers[name.substring(0, 1).toUpperCase() + name.substring(1, 3).toLowerCase()];
8144     },
8145
8146     
8147     formatCodes : {
8148         d: "String.leftPad(this.getDate(), 2, '0')",
8149         D: "Date.getShortDayName(this.getDay())", 
8150         j: "this.getDate()",
8151         l: "Date.dayNames[this.getDay()]",
8152         N: "(this.getDay() ? this.getDay() : 7)",
8153         S: "this.getSuffix()",
8154         w: "this.getDay()",
8155         z: "this.getDayOfYear()",
8156         W: "String.leftPad(this.getWeekOfYear(), 2, '0')",
8157         F: "Date.monthNames[this.getMonth()]",
8158         m: "String.leftPad(this.getMonth() + 1, 2, '0')",
8159         M: "Date.getShortMonthName(this.getMonth())", 
8160         n: "(this.getMonth() + 1)",
8161         t: "this.getDaysInMonth()",
8162         L: "(this.isLeapYear() ? 1 : 0)",
8163         o: "(this.getFullYear() + (this.getWeekOfYear() == 1 && this.getMonth() > 0 ? +1 : (this.getWeekOfYear() >= 52 && this.getMonth() < 11 ? -1 : 0)))",
8164         Y: "String.leftPad(this.getFullYear(), 4, '0')",
8165         y: "('' + this.getFullYear()).substring(2, 4)",
8166         a: "(this.getHours() < 12 ? 'am' : 'pm')",
8167         A: "(this.getHours() < 12 ? 'AM' : 'PM')",
8168         g: "((this.getHours() % 12) ? this.getHours() % 12 : 12)",
8169         G: "this.getHours()",
8170         h: "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0')",
8171         H: "String.leftPad(this.getHours(), 2, '0')",
8172         i: "String.leftPad(this.getMinutes(), 2, '0')",
8173         s: "String.leftPad(this.getSeconds(), 2, '0')",
8174         u: "String.leftPad(this.getMilliseconds(), 3, '0')",
8175         O: "this.getGMTOffset()",
8176         P: "this.getGMTOffset(true)",
8177         T: "this.getTimezone()",
8178         Z: "(this.getTimezoneOffset() * -60)",
8179
8180         c: function() { 
8181             for (var c = "Y-m-dTH:i:sP", code = [], i = 0, l = c.length; i < l; ++i) {
8182                 var e = c.charAt(i);
8183                 code.push(e == "T" ? "'T'" : Date.getFormatCode(e)); 
8184             }
8185             return code.join(" + ");
8186         },
8187         
8188
8189         U: "Math.round(this.getTime() / 1000)"
8190     },
8191
8192     
8193     isValid : function(y, m, d, h, i, s, ms) {
8194         
8195         h = h || 0;
8196         i = i || 0;
8197         s = s || 0;
8198         ms = ms || 0;
8199
8200         
8201         var dt = new Date(y < 100 ? 100 : y, m - 1, d, h, i, s, ms).add(Date.YEAR, y < 100 ? y - 100 : 0);
8202
8203         return y == dt.getFullYear() &&
8204             m == dt.getMonth() + 1 &&
8205             d == dt.getDate() &&
8206             h == dt.getHours() &&
8207             i == dt.getMinutes() &&
8208             s == dt.getSeconds() &&
8209             ms == dt.getMilliseconds();
8210     },
8211
8212     
8213     parseDate : function(input, format, strict) {
8214         var p = Date.parseFunctions;
8215         if (p[format] == null) {
8216             Date.createParser(format);
8217         }
8218         return p[format](input, Ext.isDefined(strict) ? strict : Date.useStrict);
8219     },
8220
8221     
8222     getFormatCode : function(character) {
8223         var f = Date.formatCodes[character];
8224
8225         if (f) {
8226           f = typeof f == 'function'? f() : f;
8227           Date.formatCodes[character] = f; 
8228         }
8229
8230         
8231         return f || ("'" + String.escape(character) + "'");
8232     },
8233
8234     
8235     createFormat : function(format) {
8236         var code = [],
8237             special = false,
8238             ch = '';
8239
8240         for (var i = 0; i < format.length; ++i) {
8241             ch = format.charAt(i);
8242             if (!special && ch == "\\") {
8243                 special = true;
8244             } else if (special) {
8245                 special = false;
8246                 code.push("'" + String.escape(ch) + "'");
8247             } else {
8248                 code.push(Date.getFormatCode(ch));
8249             }
8250         }
8251         Date.formatFunctions[format] = new Function("return " + code.join('+'));
8252     },
8253
8254     
8255     createParser : function() {
8256         var code = [
8257             "var dt, y, m, d, h, i, s, ms, o, z, zz, u, v,",
8258                 "def = Date.defaults,",
8259                 "results = String(input).match(Date.parseRegexes[{0}]);", 
8260
8261             "if(results){",
8262                 "{1}",
8263
8264                 "if(u != null){", 
8265                     "v = new Date(u * 1000);", 
8266                 "}else{",
8267                     
8268                     
8269                     
8270                     "dt = (new Date()).clearTime();",
8271
8272                     
8273                     "y = Ext.num(y, Ext.num(def.y, dt.getFullYear()));",
8274                     "m = Ext.num(m, Ext.num(def.m - 1, dt.getMonth()));",
8275                     "d = Ext.num(d, Ext.num(def.d, dt.getDate()));",
8276
8277                     
8278                     "h  = Ext.num(h, Ext.num(def.h, dt.getHours()));",
8279                     "i  = Ext.num(i, Ext.num(def.i, dt.getMinutes()));",
8280                     "s  = Ext.num(s, Ext.num(def.s, dt.getSeconds()));",
8281                     "ms = Ext.num(ms, Ext.num(def.ms, dt.getMilliseconds()));",
8282
8283                     "if(z >= 0 && y >= 0){",
8284                         
8285                         
8286
8287                         
8288                         
8289                         "v = new Date(y < 100 ? 100 : y, 0, 1, h, i, s, ms).add(Date.YEAR, y < 100 ? y - 100 : 0);",
8290
8291                         
8292                         "v = !strict? v : (strict === true && (z <= 364 || (v.isLeapYear() && z <= 365))? v.add(Date.DAY, z) : null);",
8293                     "}else if(strict === true && !Date.isValid(y, m + 1, d, h, i, s, ms)){", 
8294                         "v = null;", 
8295                     "}else{",
8296                         
8297                         
8298                         "v = new Date(y < 100 ? 100 : y, m, d, h, i, s, ms).add(Date.YEAR, y < 100 ? y - 100 : 0);",
8299                     "}",
8300                 "}",
8301             "}",
8302
8303             "if(v){",
8304                 
8305                 "if(zz != null){",
8306                     
8307                     "v = v.add(Date.SECOND, -v.getTimezoneOffset() * 60 - zz);",
8308                 "}else if(o){",
8309                     
8310                     "v = v.add(Date.MINUTE, -v.getTimezoneOffset() + (sn == '+'? -1 : 1) * (hr * 60 + mn));",
8311                 "}",
8312             "}",
8313
8314             "return v;"
8315         ].join('\n');
8316
8317         return function(format) {
8318             var regexNum = Date.parseRegexes.length,
8319                 currentGroup = 1,
8320                 calc = [],
8321                 regex = [],
8322                 special = false,
8323                 ch = "";
8324
8325             for (var i = 0; i < format.length; ++i) {
8326                 ch = format.charAt(i);
8327                 if (!special && ch == "\\") {
8328                     special = true;
8329                 } else if (special) {
8330                     special = false;
8331                     regex.push(String.escape(ch));
8332                 } else {
8333                     var obj = $f(ch, currentGroup);
8334                     currentGroup += obj.g;
8335                     regex.push(obj.s);
8336                     if (obj.g && obj.c) {
8337                         calc.push(obj.c);
8338                     }
8339                 }
8340             }
8341
8342             Date.parseRegexes[regexNum] = new RegExp("^" + regex.join('') + "$", 'i');
8343             Date.parseFunctions[format] = new Function("input", "strict", xf(code, regexNum, calc.join('')));
8344         };
8345     }(),
8346
8347     
8348     parseCodes : {
8349         
8350         d: {
8351             g:1,
8352             c:"d = parseInt(results[{0}], 10);\n",
8353             s:"(\\d{2})" 
8354         },
8355         j: {
8356             g:1,
8357             c:"d = parseInt(results[{0}], 10);\n",
8358             s:"(\\d{1,2})" 
8359         },
8360         D: function() {
8361             for (var a = [], i = 0; i < 7; a.push(Date.getShortDayName(i)), ++i); 
8362             return {
8363                 g:0,
8364                 c:null,
8365                 s:"(?:" + a.join("|") +")"
8366             };
8367         },
8368         l: function() {
8369             return {
8370                 g:0,
8371                 c:null,
8372                 s:"(?:" + Date.dayNames.join("|") + ")"
8373             };
8374         },
8375         N: {
8376             g:0,
8377             c:null,
8378             s:"[1-7]" 
8379         },
8380         S: {
8381             g:0,
8382             c:null,
8383             s:"(?:st|nd|rd|th)"
8384         },
8385         w: {
8386             g:0,
8387             c:null,
8388             s:"[0-6]" 
8389         },
8390         z: {
8391             g:1,
8392             c:"z = parseInt(results[{0}], 10);\n",
8393             s:"(\\d{1,3})" 
8394         },
8395         W: {
8396             g:0,
8397             c:null,
8398             s:"(?:\\d{2})" 
8399         },
8400         F: function() {
8401             return {
8402                 g:1,
8403                 c:"m = parseInt(Date.getMonthNumber(results[{0}]), 10);\n", 
8404                 s:"(" + Date.monthNames.join("|") + ")"
8405             };
8406         },
8407         M: function() {
8408             for (var a = [], i = 0; i < 12; a.push(Date.getShortMonthName(i)), ++i); 
8409             return Ext.applyIf({
8410                 s:"(" + a.join("|") + ")"
8411             }, $f("F"));
8412         },
8413         m: {
8414             g:1,
8415             c:"m = parseInt(results[{0}], 10) - 1;\n",
8416             s:"(\\d{2})" 
8417         },
8418         n: {
8419             g:1,
8420             c:"m = parseInt(results[{0}], 10) - 1;\n",
8421             s:"(\\d{1,2})" 
8422         },
8423         t: {
8424             g:0,
8425             c:null,
8426             s:"(?:\\d{2})" 
8427         },
8428         L: {
8429             g:0,
8430             c:null,
8431             s:"(?:1|0)"
8432         },
8433         o: function() {
8434             return $f("Y");
8435         },
8436         Y: {
8437             g:1,
8438             c:"y = parseInt(results[{0}], 10);\n",
8439             s:"(\\d{4})" 
8440         },
8441         y: {
8442             g:1,
8443             c:"var ty = parseInt(results[{0}], 10);\n"
8444                 + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n", 
8445             s:"(\\d{1,2})"
8446         },
8447         
8448         a: {
8449             g:1,
8450             c:"if (/(am)/i.test(results[{0}])) {\n"
8451                 + "if (!h || h == 12) { h = 0; }\n"
8452                 + "} else { if (!h || h < 12) { h = (h || 0) + 12; }}",
8453             s:"(am|pm|AM|PM)"
8454         },
8455         A: {
8456             g:1,
8457             c:"if (/(am)/i.test(results[{0}])) {\n"
8458                 + "if (!h || h == 12) { h = 0; }\n"
8459                 + "} else { if (!h || h < 12) { h = (h || 0) + 12; }}",
8460             s:"(AM|PM|am|pm)"
8461         },
8462         g: function() {
8463             return $f("G");
8464         },
8465         G: {
8466             g:1,
8467             c:"h = parseInt(results[{0}], 10);\n",
8468             s:"(\\d{1,2})" 
8469         },
8470         h: function() {
8471             return $f("H");
8472         },
8473         H: {
8474             g:1,
8475             c:"h = parseInt(results[{0}], 10);\n",
8476             s:"(\\d{2})" 
8477         },
8478         i: {
8479             g:1,
8480             c:"i = parseInt(results[{0}], 10);\n",
8481             s:"(\\d{2})" 
8482         },
8483         s: {
8484             g:1,
8485             c:"s = parseInt(results[{0}], 10);\n",
8486             s:"(\\d{2})" 
8487         },
8488         u: {
8489             g:1,
8490             c:"ms = results[{0}]; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n",
8491             s:"(\\d+)" 
8492         },
8493         O: {
8494             g:1,
8495             c:[
8496                 "o = results[{0}];",
8497                 "var sn = o.substring(0,1),", 
8498                     "hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60),", 
8499                     "mn = o.substring(3,5) % 60;", 
8500                 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n" 
8501             ].join("\n"),
8502             s: "([+\-]\\d{4})" 
8503         },
8504         P: {
8505             g:1,
8506             c:[
8507                 "o = results[{0}];",
8508                 "var sn = o.substring(0,1),", 
8509                     "hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60),", 
8510                     "mn = o.substring(4,6) % 60;", 
8511                 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n" 
8512             ].join("\n"),
8513             s: "([+\-]\\d{2}:\\d{2})" 
8514         },
8515         T: {
8516             g:0,
8517             c:null,
8518             s:"[A-Z]{1,4}" 
8519         },
8520         Z: {
8521             g:1,
8522             c:"zz = results[{0}] * 1;\n" 
8523                   + "zz = (-43200 <= zz && zz <= 50400)? zz : null;\n",
8524             s:"([+\-]?\\d{1,5})" 
8525         },
8526         c: function() {
8527             var calc = [],
8528                 arr = [
8529                     $f("Y", 1), 
8530                     $f("m", 2), 
8531                     $f("d", 3), 
8532                     $f("h", 4), 
8533                     $f("i", 5), 
8534                     $f("s", 6), 
8535                     {c:"ms = results[7] || '0'; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n"}, 
8536                     {c:[ 
8537                         "if(results[8]) {", 
8538                             "if(results[8] == 'Z'){",
8539                                 "zz = 0;", 
8540                             "}else if (results[8].indexOf(':') > -1){",
8541                                 $f("P", 8).c, 
8542                             "}else{",
8543                                 $f("O", 8).c, 
8544                             "}",
8545                         "}"
8546                     ].join('\n')}
8547                 ];
8548
8549             for (var i = 0, l = arr.length; i < l; ++i) {
8550                 calc.push(arr[i].c);
8551             }
8552
8553             return {
8554                 g:1,
8555                 c:calc.join(""),
8556                 s:[
8557                     arr[0].s, 
8558                     "(?:", "-", arr[1].s, 
8559                         "(?:", "-", arr[2].s, 
8560                             "(?:",
8561                                 "(?:T| )?", 
8562                                 arr[3].s, ":", arr[4].s,  
8563                                 "(?::", arr[5].s, ")?", 
8564                                 "(?:(?:\\.|,)(\\d+))?", 
8565                                 "(Z|(?:[-+]\\d{2}(?::)?\\d{2}))?", 
8566                             ")?",
8567                         ")?",
8568                     ")?"
8569                 ].join("")
8570             };
8571         },
8572         U: {
8573             g:1,
8574             c:"u = parseInt(results[{0}], 10);\n",
8575             s:"(-?\\d+)" 
8576         }
8577     }
8578 });
8579
8580 }());
8581
8582 Ext.apply(Date.prototype, {
8583     
8584     dateFormat : function(format) {
8585         if (Date.formatFunctions[format] == null) {
8586             Date.createFormat(format);
8587         }
8588         return Date.formatFunctions[format].call(this);
8589     },
8590
8591     
8592     getTimezone : function() {
8593         
8594         
8595         
8596         
8597         
8598         
8599         
8600         
8601         
8602         
8603         
8604         
8605         return this.toString().replace(/^.* (?:\((.*)\)|([A-Z]{1,4})(?:[\-+][0-9]{4})?(?: -?\d+)?)$/, "$1$2").replace(/[^A-Z]/g, "");
8606     },
8607
8608     
8609     getGMTOffset : function(colon) {
8610         return (this.getTimezoneOffset() > 0 ? "-" : "+")
8611             + String.leftPad(Math.floor(Math.abs(this.getTimezoneOffset()) / 60), 2, "0")
8612             + (colon ? ":" : "")
8613             + String.leftPad(Math.abs(this.getTimezoneOffset() % 60), 2, "0");
8614     },
8615
8616     
8617     getDayOfYear: function() {
8618         var num = 0,
8619             d = this.clone(),
8620             m = this.getMonth(),
8621             i;
8622
8623         for (i = 0, d.setDate(1), d.setMonth(0); i < m; d.setMonth(++i)) {
8624             num += d.getDaysInMonth();
8625         }
8626         return num + this.getDate() - 1;
8627     },
8628
8629     
8630     getWeekOfYear : function() {
8631         
8632         var ms1d = 864e5, 
8633             ms7d = 7 * ms1d; 
8634
8635         return function() { 
8636             var DC3 = Date.UTC(this.getFullYear(), this.getMonth(), this.getDate() + 3) / ms1d, 
8637                 AWN = Math.floor(DC3 / 7), 
8638                 Wyr = new Date(AWN * ms7d).getUTCFullYear();
8639
8640             return AWN - Math.floor(Date.UTC(Wyr, 0, 7) / ms7d) + 1;
8641         };
8642     }(),
8643
8644     
8645     isLeapYear : function() {
8646         var year = this.getFullYear();
8647         return !!((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
8648     },
8649
8650     
8651     getFirstDayOfMonth : function() {
8652         var day = (this.getDay() - (this.getDate() - 1)) % 7;
8653         return (day < 0) ? (day + 7) : day;
8654     },
8655
8656     
8657     getLastDayOfMonth : function() {
8658         return this.getLastDateOfMonth().getDay();
8659     },
8660
8661
8662     
8663     getFirstDateOfMonth : function() {
8664         return new Date(this.getFullYear(), this.getMonth(), 1);
8665     },
8666
8667     
8668     getLastDateOfMonth : function() {
8669         return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
8670     },
8671
8672     
8673     getDaysInMonth: function() {
8674         var daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
8675
8676         return function() { 
8677             var m = this.getMonth();
8678
8679             return m == 1 && this.isLeapYear() ? 29 : daysInMonth[m];
8680         };
8681     }(),
8682
8683     
8684     getSuffix : function() {
8685         switch (this.getDate()) {
8686             case 1:
8687             case 21:
8688             case 31:
8689                 return "st";
8690             case 2:
8691             case 22:
8692                 return "nd";
8693             case 3:
8694             case 23:
8695                 return "rd";
8696             default:
8697                 return "th";
8698         }
8699     },
8700
8701     
8702     clone : function() {
8703         return new Date(this.getTime());
8704     },
8705
8706     
8707     isDST : function() {
8708         
8709         
8710         return new Date(this.getFullYear(), 0, 1).getTimezoneOffset() != this.getTimezoneOffset();
8711     },
8712
8713     
8714     clearTime : function(clone) {
8715         if (clone) {
8716             return this.clone().clearTime();
8717         }
8718
8719         
8720         var d = this.getDate();
8721
8722         
8723         this.setHours(0);
8724         this.setMinutes(0);
8725         this.setSeconds(0);
8726         this.setMilliseconds(0);
8727
8728         if (this.getDate() != d) { 
8729             
8730             
8731
8732             
8733             for (var hr = 1, c = this.add(Date.HOUR, hr); c.getDate() != d; hr++, c = this.add(Date.HOUR, hr));
8734
8735             this.setDate(d);
8736             this.setHours(c.getHours());
8737         }
8738
8739         return this;
8740     },
8741
8742     
8743     add : function(interval, value) {
8744         var d = this.clone();
8745         if (!interval || value === 0) return d;
8746
8747         switch(interval.toLowerCase()) {
8748             case Date.MILLI:
8749                 d.setMilliseconds(this.getMilliseconds() + value);
8750                 break;
8751             case Date.SECOND:
8752                 d.setSeconds(this.getSeconds() + value);
8753                 break;
8754             case Date.MINUTE:
8755                 d.setMinutes(this.getMinutes() + value);
8756                 break;
8757             case Date.HOUR:
8758                 d.setHours(this.getHours() + value);
8759                 break;
8760             case Date.DAY:
8761                 d.setDate(this.getDate() + value);
8762                 break;
8763             case Date.MONTH:
8764                 var day = this.getDate();
8765                 if (day > 28) {
8766                     day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
8767                 }
8768                 d.setDate(day);
8769                 d.setMonth(this.getMonth() + value);
8770                 break;
8771             case Date.YEAR:
8772                 d.setFullYear(this.getFullYear() + value);
8773                 break;
8774         }
8775         return d;
8776     },
8777
8778     
8779     between : function(start, end) {
8780         var t = this.getTime();
8781         return start.getTime() <= t && t <= end.getTime();
8782     }
8783 });
8784
8785
8786
8787 Date.prototype.format = Date.prototype.dateFormat;
8788
8789
8790
8791 if (Ext.isSafari && (navigator.userAgent.match(/WebKit\/(\d+)/)[1] || NaN) < 420) {
8792     Ext.apply(Date.prototype, {
8793         _xMonth : Date.prototype.setMonth,
8794         _xDate  : Date.prototype.setDate,
8795
8796         
8797         
8798         setMonth : function(num) {
8799             if (num <= -1) {
8800                 var n = Math.ceil(-num),
8801                     back_year = Math.ceil(n / 12),
8802                     month = (n % 12) ? 12 - n % 12 : 0;
8803
8804                 this.setFullYear(this.getFullYear() - back_year);
8805
8806                 return this._xMonth(month);
8807             } else {
8808                 return this._xMonth(num);
8809             }
8810         },
8811
8812         
8813         
8814         
8815         setDate : function(d) {
8816             
8817             
8818             return this.setTime(this.getTime() - (this.getDate() - d) * 864e5);
8819         }
8820     });
8821 }
8822
8823
8824
8825
8826
8827 Ext.util.MixedCollection = function(allowFunctions, keyFn){
8828     this.items = [];
8829     this.map = {};
8830     this.keys = [];
8831     this.length = 0;
8832     this.addEvents(
8833         
8834         'clear',
8835         
8836         'add',
8837         
8838         'replace',
8839         
8840         'remove',
8841         'sort'
8842     );
8843     this.allowFunctions = allowFunctions === true;
8844     if(keyFn){
8845         this.getKey = keyFn;
8846     }
8847     Ext.util.MixedCollection.superclass.constructor.call(this);
8848 };
8849
8850 Ext.extend(Ext.util.MixedCollection, Ext.util.Observable, {
8851
8852     
8853     allowFunctions : false,
8854
8855     
8856     add : function(key, o){
8857         if(arguments.length == 1){
8858             o = arguments[0];
8859             key = this.getKey(o);
8860         }
8861         if(typeof key != 'undefined' && key !== null){
8862             var old = this.map[key];
8863             if(typeof old != 'undefined'){
8864                 return this.replace(key, o);
8865             }
8866             this.map[key] = o;
8867         }
8868         this.length++;
8869         this.items.push(o);
8870         this.keys.push(key);
8871         this.fireEvent('add', this.length-1, o, key);
8872         return o;
8873     },
8874
8875     
8876     getKey : function(o){
8877          return o.id;
8878     },
8879
8880     
8881     replace : function(key, o){
8882         if(arguments.length == 1){
8883             o = arguments[0];
8884             key = this.getKey(o);
8885         }
8886         var old = this.map[key];
8887         if(typeof key == 'undefined' || key === null || typeof old == 'undefined'){
8888              return this.add(key, o);
8889         }
8890         var index = this.indexOfKey(key);
8891         this.items[index] = o;
8892         this.map[key] = o;
8893         this.fireEvent('replace', key, old, o);
8894         return o;
8895     },
8896
8897     
8898     addAll : function(objs){
8899         if(arguments.length > 1 || Ext.isArray(objs)){
8900             var args = arguments.length > 1 ? arguments : objs;
8901             for(var i = 0, len = args.length; i < len; i++){
8902                 this.add(args[i]);
8903             }
8904         }else{
8905             for(var key in objs){
8906                 if(this.allowFunctions || typeof objs[key] != 'function'){
8907                     this.add(key, objs[key]);
8908                 }
8909             }
8910         }
8911     },
8912
8913     
8914     each : function(fn, scope){
8915         var items = [].concat(this.items); 
8916         for(var i = 0, len = items.length; i < len; i++){
8917             if(fn.call(scope || items[i], items[i], i, len) === false){
8918                 break;
8919             }
8920         }
8921     },
8922
8923     
8924     eachKey : function(fn, scope){
8925         for(var i = 0, len = this.keys.length; i < len; i++){
8926             fn.call(scope || window, this.keys[i], this.items[i], i, len);
8927         }
8928     },
8929
8930     
8931     find : function(fn, scope){
8932         for(var i = 0, len = this.items.length; i < len; i++){
8933             if(fn.call(scope || window, this.items[i], this.keys[i])){
8934                 return this.items[i];
8935             }
8936         }
8937         return null;
8938     },
8939
8940     
8941     insert : function(index, key, o){
8942         if(arguments.length == 2){
8943             o = arguments[1];
8944             key = this.getKey(o);
8945         }
8946         if(this.containsKey(key)){
8947             this.suspendEvents();
8948             this.removeKey(key);
8949             this.resumeEvents();
8950         }
8951         if(index >= this.length){
8952             return this.add(key, o);
8953         }
8954         this.length++;
8955         this.items.splice(index, 0, o);
8956         if(typeof key != 'undefined' && key !== null){
8957             this.map[key] = o;
8958         }
8959         this.keys.splice(index, 0, key);
8960         this.fireEvent('add', index, o, key);
8961         return o;
8962     },
8963
8964     
8965     remove : function(o){
8966         return this.removeAt(this.indexOf(o));
8967     },
8968
8969     
8970     removeAt : function(index){
8971         if(index < this.length && index >= 0){
8972             this.length--;
8973             var o = this.items[index];
8974             this.items.splice(index, 1);
8975             var key = this.keys[index];
8976             if(typeof key != 'undefined'){
8977                 delete this.map[key];
8978             }
8979             this.keys.splice(index, 1);
8980             this.fireEvent('remove', o, key);
8981             return o;
8982         }
8983         return false;
8984     },
8985
8986     
8987     removeKey : function(key){
8988         return this.removeAt(this.indexOfKey(key));
8989     },
8990
8991     
8992     getCount : function(){
8993         return this.length;
8994     },
8995
8996     
8997     indexOf : function(o){
8998         return this.items.indexOf(o);
8999     },
9000
9001     
9002     indexOfKey : function(key){
9003         return this.keys.indexOf(key);
9004     },
9005
9006     
9007     item : function(key){
9008         var mk = this.map[key],
9009             item = mk !== undefined ? mk : (typeof key == 'number') ? this.items[key] : undefined;
9010         return typeof item != 'function' || this.allowFunctions ? item : null; 
9011     },
9012
9013     
9014     itemAt : function(index){
9015         return this.items[index];
9016     },
9017
9018     
9019     key : function(key){
9020         return this.map[key];
9021     },
9022
9023     
9024     contains : function(o){
9025         return this.indexOf(o) != -1;
9026     },
9027
9028     
9029     containsKey : function(key){
9030         return typeof this.map[key] != 'undefined';
9031     },
9032
9033     
9034     clear : function(){
9035         this.length = 0;
9036         this.items = [];
9037         this.keys = [];
9038         this.map = {};
9039         this.fireEvent('clear');
9040     },
9041
9042     
9043     first : function(){
9044         return this.items[0];
9045     },
9046
9047     
9048     last : function(){
9049         return this.items[this.length-1];
9050     },
9051
9052     
9053     _sort : function(property, dir, fn){
9054         var i, len,
9055             dsc   = String(dir).toUpperCase() == 'DESC' ? -1 : 1,
9056
9057             
9058             c     = [],
9059             keys  = this.keys,
9060             items = this.items;
9061
9062         
9063         fn = fn || function(a, b) {
9064             return a - b;
9065         };
9066
9067         
9068         for(i = 0, len = items.length; i < len; i++){
9069             c[c.length] = {
9070                 key  : keys[i],
9071                 value: items[i],
9072                 index: i
9073             };
9074         }
9075
9076         
9077         c.sort(function(a, b){
9078             var v = fn(a[property], b[property]) * dsc;
9079             if(v === 0){
9080                 v = (a.index < b.index ? -1 : 1);
9081             }
9082             return v;
9083         });
9084
9085         
9086         for(i = 0, len = c.length; i < len; i++){
9087             items[i] = c[i].value;
9088             keys[i]  = c[i].key;
9089         }
9090
9091         this.fireEvent('sort', this);
9092     },
9093
9094     
9095     sort : function(dir, fn){
9096         this._sort('value', dir, fn);
9097     },
9098
9099     
9100     reorder: function(mapping) {
9101         this.suspendEvents();
9102
9103         var items = this.items,
9104             index = 0,
9105             length = items.length,
9106             order = [],
9107             remaining = [],
9108             oldIndex;
9109
9110         
9111         for (oldIndex in mapping) {
9112             order[mapping[oldIndex]] = items[oldIndex];
9113         }
9114
9115         for (index = 0; index < length; index++) {
9116             if (mapping[index] == undefined) {
9117                 remaining.push(items[index]);
9118             }
9119         }
9120
9121         for (index = 0; index < length; index++) {
9122             if (order[index] == undefined) {
9123                 order[index] = remaining.shift();
9124             }
9125         }
9126
9127         this.clear();
9128         this.addAll(order);
9129
9130         this.resumeEvents();
9131         this.fireEvent('sort', this);
9132     },
9133
9134     
9135     keySort : function(dir, fn){
9136         this._sort('key', dir, fn || function(a, b){
9137             var v1 = String(a).toUpperCase(), v2 = String(b).toUpperCase();
9138             return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
9139         });
9140     },
9141
9142     
9143     getRange : function(start, end){
9144         var items = this.items;
9145         if(items.length < 1){
9146             return [];
9147         }
9148         start = start || 0;
9149         end = Math.min(typeof end == 'undefined' ? this.length-1 : end, this.length-1);
9150         var i, r = [];
9151         if(start <= end){
9152             for(i = start; i <= end; i++) {
9153                 r[r.length] = items[i];
9154             }
9155         }else{
9156             for(i = start; i >= end; i--) {
9157                 r[r.length] = items[i];
9158             }
9159         }
9160         return r;
9161     },
9162
9163     
9164     filter : function(property, value, anyMatch, caseSensitive){
9165         if(Ext.isEmpty(value, false)){
9166             return this.clone();
9167         }
9168         value = this.createValueMatcher(value, anyMatch, caseSensitive);
9169         return this.filterBy(function(o){
9170             return o && value.test(o[property]);
9171         });
9172     },
9173
9174     
9175     filterBy : function(fn, scope){
9176         var r = new Ext.util.MixedCollection();
9177         r.getKey = this.getKey;
9178         var k = this.keys, it = this.items;
9179         for(var i = 0, len = it.length; i < len; i++){
9180             if(fn.call(scope||this, it[i], k[i])){
9181                 r.add(k[i], it[i]);
9182             }
9183         }
9184         return r;
9185     },
9186
9187     
9188     findIndex : function(property, value, start, anyMatch, caseSensitive){
9189         if(Ext.isEmpty(value, false)){
9190             return -1;
9191         }
9192         value = this.createValueMatcher(value, anyMatch, caseSensitive);
9193         return this.findIndexBy(function(o){
9194             return o && value.test(o[property]);
9195         }, null, start);
9196     },
9197
9198     
9199     findIndexBy : function(fn, scope, start){
9200         var k = this.keys, it = this.items;
9201         for(var i = (start||0), len = it.length; i < len; i++){
9202             if(fn.call(scope||this, it[i], k[i])){
9203                 return i;
9204             }
9205         }
9206         return -1;
9207     },
9208
9209     
9210     createValueMatcher : function(value, anyMatch, caseSensitive, exactMatch) {
9211         if (!value.exec) { 
9212             var er = Ext.escapeRe;
9213             value = String(value);
9214
9215             if (anyMatch === true) {
9216                 value = er(value);
9217             } else {
9218                 value = '^' + er(value);
9219                 if (exactMatch === true) {
9220                     value += '$';
9221                 }
9222             }
9223             value = new RegExp(value, caseSensitive ? '' : 'i');
9224          }
9225          return value;
9226     },
9227
9228     
9229     clone : function(){
9230         var r = new Ext.util.MixedCollection();
9231         var k = this.keys, it = this.items;
9232         for(var i = 0, len = it.length; i < len; i++){
9233             r.add(k[i], it[i]);
9234         }
9235         r.getKey = this.getKey;
9236         return r;
9237     }
9238 });
9239
9240 Ext.util.MixedCollection.prototype.get = Ext.util.MixedCollection.prototype.item;
9241
9242 Ext.AbstractManager = Ext.extend(Object, {
9243     typeName: 'type',
9244     
9245     constructor: function(config) {
9246         Ext.apply(this, config || {});
9247         
9248         
9249         this.all = new Ext.util.MixedCollection();
9250         
9251         this.types = {};
9252     },
9253     
9254     
9255     get : function(id){
9256         return this.all.get(id);
9257     },
9258     
9259     
9260     register: function(item) {
9261         this.all.add(item);
9262     },
9263     
9264     
9265     unregister: function(item) {
9266         this.all.remove(item);        
9267     },
9268     
9269     
9270     registerType : function(type, cls){
9271         this.types[type] = cls;
9272         cls[this.typeName] = type;
9273     },
9274     
9275     
9276     isRegistered : function(type){
9277         return this.types[type] !== undefined;    
9278     },
9279     
9280     
9281     create: function(config, defaultType) {
9282         var type        = config[this.typeName] || config.type || defaultType,
9283             Constructor = this.types[type];
9284         
9285         if (Constructor == undefined) {
9286             throw new Error(String.format("The '{0}' type has not been registered with this manager", type));
9287         }
9288         
9289         return new Constructor(config);
9290     },
9291     
9292     
9293     onAvailable : function(id, fn, scope){
9294         var all = this.all;
9295         
9296         all.on("add", function(index, o){
9297             if (o.id == id) {
9298                 fn.call(scope || o, o);
9299                 all.un("add", fn, scope);
9300             }
9301         });
9302     }
9303 });
9304 Ext.util.Format = function() {
9305     var trimRe         = /^\s+|\s+$/g,
9306         stripTagsRE    = /<\/?[^>]+>/gi,
9307         stripScriptsRe = /(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig,
9308         nl2brRe        = /\r?\n/g;
9309
9310     return {
9311         
9312         ellipsis : function(value, len, word) {
9313             if (value && value.length > len) {
9314                 if (word) {
9315                     var vs    = value.substr(0, len - 2),
9316                         index = Math.max(vs.lastIndexOf(' '), vs.lastIndexOf('.'), vs.lastIndexOf('!'), vs.lastIndexOf('?'));
9317                     if (index == -1 || index < (len - 15)) {
9318                         return value.substr(0, len - 3) + "...";
9319                     } else {
9320                         return vs.substr(0, index) + "...";
9321                     }
9322                 } else {
9323                     return value.substr(0, len - 3) + "...";
9324                 }
9325             }
9326             return value;
9327         },
9328
9329         
9330         undef : function(value) {
9331             return value !== undefined ? value : "";
9332         },
9333
9334         
9335         defaultValue : function(value, defaultValue) {
9336             return value !== undefined && value !== '' ? value : defaultValue;
9337         },
9338
9339         
9340         htmlEncode : function(value) {
9341             return !value ? value : String(value).replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/</g, "&lt;").replace(/"/g, "&quot;");
9342         },
9343
9344         
9345         htmlDecode : function(value) {
9346             return !value ? value : String(value).replace(/&gt;/g, ">").replace(/&lt;/g, "<").replace(/&quot;/g, '"').replace(/&amp;/g, "&");
9347         },
9348
9349         
9350         trim : function(value) {
9351             return String(value).replace(trimRe, "");
9352         },
9353
9354         
9355         substr : function(value, start, length) {
9356             return String(value).substr(start, length);
9357         },
9358
9359         
9360         lowercase : function(value) {
9361             return String(value).toLowerCase();
9362         },
9363
9364         
9365         uppercase : function(value) {
9366             return String(value).toUpperCase();
9367         },
9368
9369         
9370         capitalize : function(value) {
9371             return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
9372         },
9373
9374         
9375         call : function(value, fn) {
9376             if (arguments.length > 2) {
9377                 var args = Array.prototype.slice.call(arguments, 2);
9378                 args.unshift(value);
9379                 return eval(fn).apply(window, args);
9380             } else {
9381                 return eval(fn).call(window, value);
9382             }
9383         },
9384
9385         
9386         usMoney : function(v) {
9387             v = (Math.round((v-0)*100))/100;
9388             v = (v == Math.floor(v)) ? v + ".00" : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
9389             v = String(v);
9390             var ps = v.split('.'),
9391                 whole = ps[0],
9392                 sub = ps[1] ? '.'+ ps[1] : '.00',
9393                 r = /(\d+)(\d{3})/;
9394             while (r.test(whole)) {
9395                 whole = whole.replace(r, '$1' + ',' + '$2');
9396             }
9397             v = whole + sub;
9398             if (v.charAt(0) == '-') {
9399                 return '-$' + v.substr(1);
9400             }
9401             return "$" +  v;
9402         },
9403
9404         
9405         date : function(v, format) {
9406             if (!v) {
9407                 return "";
9408             }
9409             if (!Ext.isDate(v)) {
9410                 v = new Date(Date.parse(v));
9411             }
9412             return v.dateFormat(format || "m/d/Y");
9413         },
9414
9415         
9416         dateRenderer : function(format) {
9417             return function(v) {
9418                 return Ext.util.Format.date(v, format);
9419             };
9420         },
9421
9422         
9423         stripTags : function(v) {
9424             return !v ? v : String(v).replace(stripTagsRE, "");
9425         },
9426
9427         
9428         stripScripts : function(v) {
9429             return !v ? v : String(v).replace(stripScriptsRe, "");
9430         },
9431
9432         
9433         fileSize : function(size) {
9434             if (size < 1024) {
9435                 return size + " bytes";
9436             } else if (size < 1048576) {
9437                 return (Math.round(((size*10) / 1024))/10) + " KB";
9438             } else {
9439                 return (Math.round(((size*10) / 1048576))/10) + " MB";
9440             }
9441         },
9442
9443         
9444         math : function(){
9445             var fns = {};
9446             
9447             return function(v, a){
9448                 if (!fns[a]) {
9449                     fns[a] = new Function('v', 'return v ' + a + ';');
9450                 }
9451                 return fns[a](v);
9452             };
9453         }(),
9454
9455         
9456         round : function(value, precision) {
9457             var result = Number(value);
9458             if (typeof precision == 'number') {
9459                 precision = Math.pow(10, precision);
9460                 result = Math.round(value * precision) / precision;
9461             }
9462             return result;
9463         },
9464
9465         
9466         number: function(v, format) {
9467             if (!format) {
9468                 return v;
9469             }
9470             v = Ext.num(v, NaN);
9471             if (isNaN(v)) {
9472                 return '';
9473             }
9474             var comma = ',',
9475                 dec   = '.',
9476                 i18n  = false,
9477                 neg   = v < 0;
9478
9479             v = Math.abs(v);
9480             if (format.substr(format.length - 2) == '/i') {
9481                 format = format.substr(0, format.length - 2);
9482                 i18n   = true;
9483                 comma  = '.';
9484                 dec    = ',';
9485             }
9486
9487             var hasComma = format.indexOf(comma) != -1,
9488                 psplit   = (i18n ? format.replace(/[^\d\,]/g, '') : format.replace(/[^\d\.]/g, '')).split(dec);
9489
9490             if (1 < psplit.length) {
9491                 v = v.toFixed(psplit[1].length);
9492             } else if(2 < psplit.length) {
9493                 throw ('NumberFormatException: invalid format, formats should have no more than 1 period: ' + format);
9494             } else {
9495                 v = v.toFixed(0);
9496             }
9497
9498             var fnum = v.toString();
9499
9500             psplit = fnum.split('.');
9501
9502             if (hasComma) {
9503                 var cnum = psplit[0], 
9504                     parr = [], 
9505                     j    = cnum.length, 
9506                     m    = Math.floor(j / 3),
9507                     n    = cnum.length % 3 || 3,
9508                     i;
9509
9510                 for (i = 0; i < j; i += n) {
9511                     if (i != 0) {
9512                         n = 3;
9513                     }
9514                     
9515                     parr[parr.length] = cnum.substr(i, n);
9516                     m -= 1;
9517                 }
9518                 fnum = parr.join(comma);
9519                 if (psplit[1]) {
9520                     fnum += dec + psplit[1];
9521                 }
9522             } else {
9523                 if (psplit[1]) {
9524                     fnum = psplit[0] + dec + psplit[1];
9525                 }
9526             }
9527
9528             return (neg ? '-' : '') + format.replace(/[\d,?\.?]+/, fnum);
9529         },
9530
9531         
9532         numberRenderer : function(format) {
9533             return function(v) {
9534                 return Ext.util.Format.number(v, format);
9535             };
9536         },
9537
9538         
9539         plural : function(v, s, p) {
9540             return v +' ' + (v == 1 ? s : (p ? p : s+'s'));
9541         },
9542
9543         
9544         nl2br : function(v) {
9545             return Ext.isEmpty(v) ? '' : v.replace(nl2brRe, '<br/>');
9546         }
9547     };
9548 }();
9549
9550 Ext.XTemplate = function(){
9551     Ext.XTemplate.superclass.constructor.apply(this, arguments);
9552
9553     var me = this,
9554         s = me.html,
9555         re = /<tpl\b[^>]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/,
9556         nameRe = /^<tpl\b[^>]*?for="(.*?)"/,
9557         ifRe = /^<tpl\b[^>]*?if="(.*?)"/,
9558         execRe = /^<tpl\b[^>]*?exec="(.*?)"/,
9559         m,
9560         id = 0,
9561         tpls = [],
9562         VALUES = 'values',
9563         PARENT = 'parent',
9564         XINDEX = 'xindex',
9565         XCOUNT = 'xcount',
9566         RETURN = 'return ',
9567         WITHVALUES = 'with(values){ ';
9568
9569     s = ['<tpl>', s, '</tpl>'].join('');
9570
9571     while((m = s.match(re))){
9572         var m2 = m[0].match(nameRe),
9573             m3 = m[0].match(ifRe),
9574             m4 = m[0].match(execRe),
9575             exp = null,
9576             fn = null,
9577             exec = null,
9578             name = m2 && m2[1] ? m2[1] : '';
9579
9580        if (m3) {
9581            exp = m3 && m3[1] ? m3[1] : null;
9582            if(exp){
9583                fn = new Function(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES + RETURN +(Ext.util.Format.htmlDecode(exp))+'; }');
9584            }
9585        }
9586        if (m4) {
9587            exp = m4 && m4[1] ? m4[1] : null;
9588            if(exp){
9589                exec = new Function(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES +(Ext.util.Format.htmlDecode(exp))+'; }');
9590            }
9591        }
9592        if(name){
9593            switch(name){
9594                case '.': name = new Function(VALUES, PARENT, WITHVALUES + RETURN + VALUES + '; }'); break;
9595                case '..': name = new Function(VALUES, PARENT, WITHVALUES + RETURN + PARENT + '; }'); break;
9596                default: name = new Function(VALUES, PARENT, WITHVALUES + RETURN + name + '; }');
9597            }
9598        }
9599        tpls.push({
9600             id: id,
9601             target: name,
9602             exec: exec,
9603             test: fn,
9604             body: m[1]||''
9605         });
9606        s = s.replace(m[0], '{xtpl'+ id + '}');
9607        ++id;
9608     }
9609     for(var i = tpls.length-1; i >= 0; --i){
9610         me.compileTpl(tpls[i]);
9611     }
9612     me.master = tpls[tpls.length-1];
9613     me.tpls = tpls;
9614 };
9615 Ext.extend(Ext.XTemplate, Ext.Template, {
9616     
9617     re : /\{([\w-\.\#]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?(\s?[\+\-\*\\]\s?[\d\.\+\-\*\\\(\)]+)?\}/g,
9618     
9619     codeRe : /\{\[((?:\\\]|.|\n)*?)\]\}/g,
9620
9621     
9622     applySubTemplate : function(id, values, parent, xindex, xcount){
9623         var me = this,
9624             len,
9625             t = me.tpls[id],
9626             vs,
9627             buf = [];
9628         if ((t.test && !t.test.call(me, values, parent, xindex, xcount)) ||
9629             (t.exec && t.exec.call(me, values, parent, xindex, xcount))) {
9630             return '';
9631         }
9632         vs = t.target ? t.target.call(me, values, parent) : values;
9633         len = vs.length;
9634         parent = t.target ? values : parent;
9635         if(t.target && Ext.isArray(vs)){
9636             for(var i = 0, len = vs.length; i < len; i++){
9637                 buf[buf.length] = t.compiled.call(me, vs[i], parent, i+1, len);
9638             }
9639             return buf.join('');
9640         }
9641         return t.compiled.call(me, vs, parent, xindex, xcount);
9642     },
9643
9644     
9645     compileTpl : function(tpl){
9646         var fm = Ext.util.Format,
9647             useF = this.disableFormats !== true,
9648             sep = Ext.isGecko ? "+" : ",",
9649             body;
9650
9651         function fn(m, name, format, args, math){
9652             if(name.substr(0, 4) == 'xtpl'){
9653                 return "'"+ sep +'this.applySubTemplate('+name.substr(4)+', values, parent, xindex, xcount)'+sep+"'";
9654             }
9655             var v;
9656             if(name === '.'){
9657                 v = 'values';
9658             }else if(name === '#'){
9659                 v = 'xindex';
9660             }else if(name.indexOf('.') != -1){
9661                 v = name;
9662             }else{
9663                 v = "values['" + name + "']";
9664             }
9665             if(math){
9666                 v = '(' + v + math + ')';
9667             }
9668             if (format && useF) {
9669                 args = args ? ',' + args : "";
9670                 if(format.substr(0, 5) != "this."){
9671                     format = "fm." + format + '(';
9672                 }else{
9673                     format = 'this.call("'+ format.substr(5) + '", ';
9674                     args = ", values";
9675                 }
9676             } else {
9677                 args= ''; format = "("+v+" === undefined ? '' : ";
9678             }
9679             return "'"+ sep + format + v + args + ")"+sep+"'";
9680         }
9681
9682         function codeFn(m, code){
9683             
9684             return "'" + sep + '(' + code.replace(/\\'/g, "'") + ')' + sep + "'";
9685         }
9686
9687         
9688         if(Ext.isGecko){
9689             body = "tpl.compiled = function(values, parent, xindex, xcount){ return '" +
9690                    tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn).replace(this.codeRe, codeFn) +
9691                     "';};";
9692         }else{
9693             body = ["tpl.compiled = function(values, parent, xindex, xcount){ return ['"];
9694             body.push(tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn).replace(this.codeRe, codeFn));
9695             body.push("'].join('');};");
9696             body = body.join('');
9697         }
9698         eval(body);
9699         return this;
9700     },
9701
9702     
9703     applyTemplate : function(values){
9704         return this.master.compiled.call(this, values, {}, 1, 1);
9705     },
9706
9707     
9708     compile : function(){return this;}
9709
9710     
9711     
9712     
9713
9714 });
9715
9716 Ext.XTemplate.prototype.apply = Ext.XTemplate.prototype.applyTemplate;
9717
9718
9719 Ext.XTemplate.from = function(el){
9720     el = Ext.getDom(el);
9721     return new Ext.XTemplate(el.value || el.innerHTML);
9722 };
9723
9724 Ext.util.CSS = function(){
9725         var rules = null;
9726         var doc = document;
9727
9728     var camelRe = /(-[a-z])/gi;
9729     var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
9730
9731    return {
9732    
9733    createStyleSheet : function(cssText, id){
9734        var ss;
9735        var head = doc.getElementsByTagName("head")[0];
9736        var rules = doc.createElement("style");
9737        rules.setAttribute("type", "text/css");
9738        if(id){
9739            rules.setAttribute("id", id);
9740        }
9741        if(Ext.isIE){
9742            head.appendChild(rules);
9743            ss = rules.styleSheet;
9744            ss.cssText = cssText;
9745        }else{
9746            try{
9747                 rules.appendChild(doc.createTextNode(cssText));
9748            }catch(e){
9749                rules.cssText = cssText;
9750            }
9751            head.appendChild(rules);
9752            ss = rules.styleSheet ? rules.styleSheet : (rules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
9753        }
9754        this.cacheStyleSheet(ss);
9755        return ss;
9756    },
9757
9758    
9759    removeStyleSheet : function(id){
9760        var existing = doc.getElementById(id);
9761        if(existing){
9762            existing.parentNode.removeChild(existing);
9763        }
9764    },
9765
9766    
9767    swapStyleSheet : function(id, url){
9768        this.removeStyleSheet(id);
9769        var ss = doc.createElement("link");
9770        ss.setAttribute("rel", "stylesheet");
9771        ss.setAttribute("type", "text/css");
9772        ss.setAttribute("id", id);
9773        ss.setAttribute("href", url);
9774        doc.getElementsByTagName("head")[0].appendChild(ss);
9775    },
9776    
9777    
9778    refreshCache : function(){
9779        return this.getRules(true);
9780    },
9781
9782    
9783    cacheStyleSheet : function(ss){
9784        if(!rules){
9785            rules = {};
9786        }
9787        try{
9788            var ssRules = ss.cssRules || ss.rules;
9789            for(var j = ssRules.length-1; j >= 0; --j){
9790                rules[ssRules[j].selectorText.toLowerCase()] = ssRules[j];
9791            }
9792        }catch(e){}
9793    },
9794    
9795    
9796    getRules : function(refreshCache){
9797                 if(rules === null || refreshCache){
9798                         rules = {};
9799                         var ds = doc.styleSheets;
9800                         for(var i =0, len = ds.length; i < len; i++){
9801                             try{
9802                         this.cacheStyleSheet(ds[i]);
9803                     }catch(e){} 
9804                 }
9805                 }
9806                 return rules;
9807         },
9808         
9809         
9810    getRule : function(selector, refreshCache){
9811                 var rs = this.getRules(refreshCache);
9812                 if(!Ext.isArray(selector)){
9813                     return rs[selector.toLowerCase()];
9814                 }
9815                 for(var i = 0; i < selector.length; i++){
9816                         if(rs[selector[i]]){
9817                                 return rs[selector[i].toLowerCase()];
9818                         }
9819                 }
9820                 return null;
9821         },
9822         
9823         
9824         
9825    updateRule : function(selector, property, value){
9826                 if(!Ext.isArray(selector)){
9827                         var rule = this.getRule(selector);
9828                         if(rule){
9829                                 rule.style[property.replace(camelRe, camelFn)] = value;
9830                                 return true;
9831                         }
9832                 }else{
9833                         for(var i = 0; i < selector.length; i++){
9834                                 if(this.updateRule(selector[i], property, value)){
9835                                         return true;
9836                                 }
9837                         }
9838                 }
9839                 return false;
9840         }
9841    };   
9842 }();
9843 Ext.util.ClickRepeater = Ext.extend(Ext.util.Observable, {
9844     
9845     constructor : function(el, config){
9846         this.el = Ext.get(el);
9847         this.el.unselectable();
9848
9849         Ext.apply(this, config);
9850
9851         this.addEvents(
9852         
9853         "mousedown",
9854         
9855         "click",
9856         
9857         "mouseup"
9858         );
9859
9860         if(!this.disabled){
9861             this.disabled = true;
9862             this.enable();
9863         }
9864
9865         
9866         if(this.handler){
9867             this.on("click", this.handler,  this.scope || this);
9868         }
9869
9870         Ext.util.ClickRepeater.superclass.constructor.call(this);        
9871     },
9872     
9873     interval : 20,
9874     delay: 250,
9875     preventDefault : true,
9876     stopDefault : false,
9877     timer : 0,
9878
9879     
9880     enable: function(){
9881         if(this.disabled){
9882             this.el.on('mousedown', this.handleMouseDown, this);
9883             if (Ext.isIE){
9884                 this.el.on('dblclick', this.handleDblClick, this);
9885             }
9886             if(this.preventDefault || this.stopDefault){
9887                 this.el.on('click', this.eventOptions, this);
9888             }
9889         }
9890         this.disabled = false;
9891     },
9892
9893     
9894     disable: function( force){
9895         if(force || !this.disabled){
9896             clearTimeout(this.timer);
9897             if(this.pressClass){
9898                 this.el.removeClass(this.pressClass);
9899             }
9900             Ext.getDoc().un('mouseup', this.handleMouseUp, this);
9901             this.el.removeAllListeners();
9902         }
9903         this.disabled = true;
9904     },
9905
9906     
9907     setDisabled: function(disabled){
9908         this[disabled ? 'disable' : 'enable']();
9909     },
9910
9911     eventOptions: function(e){
9912         if(this.preventDefault){
9913             e.preventDefault();
9914         }
9915         if(this.stopDefault){
9916             e.stopEvent();
9917         }
9918     },
9919
9920     
9921     destroy : function() {
9922         this.disable(true);
9923         Ext.destroy(this.el);
9924         this.purgeListeners();
9925     },
9926
9927     handleDblClick : function(e){
9928         clearTimeout(this.timer);
9929         this.el.blur();
9930
9931         this.fireEvent("mousedown", this, e);
9932         this.fireEvent("click", this, e);
9933     },
9934
9935     
9936     handleMouseDown : function(e){
9937         clearTimeout(this.timer);
9938         this.el.blur();
9939         if(this.pressClass){
9940             this.el.addClass(this.pressClass);
9941         }
9942         this.mousedownTime = new Date();
9943
9944         Ext.getDoc().on("mouseup", this.handleMouseUp, this);
9945         this.el.on("mouseout", this.handleMouseOut, this);
9946
9947         this.fireEvent("mousedown", this, e);
9948         this.fireEvent("click", this, e);
9949
9950         
9951         if (this.accelerate) {
9952             this.delay = 400;
9953         }
9954         this.timer = this.click.defer(this.delay || this.interval, this, [e]);
9955     },
9956
9957     
9958     click : function(e){
9959         this.fireEvent("click", this, e);
9960         this.timer = this.click.defer(this.accelerate ?
9961             this.easeOutExpo(this.mousedownTime.getElapsed(),
9962                 400,
9963                 -390,
9964                 12000) :
9965             this.interval, this, [e]);
9966     },
9967
9968     easeOutExpo : function (t, b, c, d) {
9969         return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
9970     },
9971
9972     
9973     handleMouseOut : function(){
9974         clearTimeout(this.timer);
9975         if(this.pressClass){
9976             this.el.removeClass(this.pressClass);
9977         }
9978         this.el.on("mouseover", this.handleMouseReturn, this);
9979     },
9980
9981     
9982     handleMouseReturn : function(){
9983         this.el.un("mouseover", this.handleMouseReturn, this);
9984         if(this.pressClass){
9985             this.el.addClass(this.pressClass);
9986         }
9987         this.click();
9988     },
9989
9990     
9991     handleMouseUp : function(e){
9992         clearTimeout(this.timer);
9993         this.el.un("mouseover", this.handleMouseReturn, this);
9994         this.el.un("mouseout", this.handleMouseOut, this);
9995         Ext.getDoc().un("mouseup", this.handleMouseUp, this);
9996         this.el.removeClass(this.pressClass);
9997         this.fireEvent("mouseup", this, e);
9998     }
9999 });
10000 Ext.KeyNav = function(el, config){
10001     this.el = Ext.get(el);
10002     Ext.apply(this, config);
10003     if(!this.disabled){
10004         this.disabled = true;
10005         this.enable();
10006     }
10007 };
10008
10009 Ext.KeyNav.prototype = {
10010     
10011     disabled : false,
10012     
10013     defaultEventAction: "stopEvent",
10014     
10015     forceKeyDown : false,
10016
10017     
10018     relay : function(e){
10019         var k = e.getKey(),
10020             h = this.keyToHandler[k];
10021         if(h && this[h]){
10022             if(this.doRelay(e, this[h], h) !== true){
10023                 e[this.defaultEventAction]();
10024             }
10025         }
10026     },
10027
10028     
10029     doRelay : function(e, h, hname){
10030         return h.call(this.scope || this, e, hname);
10031     },
10032
10033     
10034     enter : false,
10035     left : false,
10036     right : false,
10037     up : false,
10038     down : false,
10039     tab : false,
10040     esc : false,
10041     pageUp : false,
10042     pageDown : false,
10043     del : false,
10044     home : false,
10045     end : false,
10046
10047     
10048     keyToHandler : {
10049         37 : "left",
10050         39 : "right",
10051         38 : "up",
10052         40 : "down",
10053         33 : "pageUp",
10054         34 : "pageDown",
10055         46 : "del",
10056         36 : "home",
10057         35 : "end",
10058         13 : "enter",
10059         27 : "esc",
10060         9  : "tab"
10061     },
10062     
10063     stopKeyUp: function(e) {
10064         var k = e.getKey();
10065
10066         if (k >= 37 && k <= 40) {
10067             
10068             
10069             e.stopEvent();
10070         }
10071     },
10072     
10073     
10074     destroy: function(){
10075         this.disable();    
10076     },
10077
10078         
10079         enable: function() {
10080         if (this.disabled) {
10081             if (Ext.isSafari2) {
10082                 
10083                 this.el.on('keyup', this.stopKeyUp, this);
10084             }
10085
10086             this.el.on(this.isKeydown()? 'keydown' : 'keypress', this.relay, this);
10087             this.disabled = false;
10088         }
10089     },
10090
10091         
10092         disable: function() {
10093         if (!this.disabled) {
10094             if (Ext.isSafari2) {
10095                 
10096                 this.el.un('keyup', this.stopKeyUp, this);
10097             }
10098
10099             this.el.un(this.isKeydown()? 'keydown' : 'keypress', this.relay, this);
10100             this.disabled = true;
10101         }
10102     },
10103     
10104     
10105     setDisabled : function(disabled){
10106         this[disabled ? "disable" : "enable"]();
10107     },
10108     
10109     
10110     isKeydown: function(){
10111         return this.forceKeyDown || Ext.EventManager.useKeydown;
10112     }
10113 };
10114
10115 Ext.KeyMap = function(el, config, eventName){
10116     this.el  = Ext.get(el);
10117     this.eventName = eventName || "keydown";
10118     this.bindings = [];
10119     if(config){
10120         this.addBinding(config);
10121     }
10122     this.enable();
10123 };
10124
10125 Ext.KeyMap.prototype = {
10126     
10127     stopEvent : false,
10128
10129     
10130         addBinding : function(config){
10131         if(Ext.isArray(config)){
10132             Ext.each(config, function(c){
10133                 this.addBinding(c);
10134             }, this);
10135             return;
10136         }
10137         var keyCode = config.key,
10138             fn = config.fn || config.handler,
10139             scope = config.scope;
10140
10141         if (config.stopEvent) {
10142             this.stopEvent = config.stopEvent;    
10143         }       
10144
10145         if(typeof keyCode == "string"){
10146             var ks = [];
10147             var keyString = keyCode.toUpperCase();
10148             for(var j = 0, len = keyString.length; j < len; j++){
10149                 ks.push(keyString.charCodeAt(j));
10150             }
10151             keyCode = ks;
10152         }
10153         var keyArray = Ext.isArray(keyCode);
10154         
10155         var handler = function(e){
10156             if(this.checkModifiers(config, e)){
10157                 var k = e.getKey();
10158                 if(keyArray){
10159                     for(var i = 0, len = keyCode.length; i < len; i++){
10160                         if(keyCode[i] == k){
10161                           if(this.stopEvent){
10162                               e.stopEvent();
10163                           }
10164                           fn.call(scope || window, k, e);
10165                           return;
10166                         }
10167                     }
10168                 }else{
10169                     if(k == keyCode){
10170                         if(this.stopEvent){
10171                            e.stopEvent();
10172                         }
10173                         fn.call(scope || window, k, e);
10174                     }
10175                 }
10176             }
10177         };
10178         this.bindings.push(handler);
10179         },
10180     
10181     
10182     checkModifiers: function(config, e){
10183         var val, key, keys = ['shift', 'ctrl', 'alt'];
10184         for (var i = 0, len = keys.length; i < len; ++i){
10185             key = keys[i];
10186             val = config[key];
10187             if(!(val === undefined || (val === e[key + 'Key']))){
10188                 return false;
10189             }
10190         }
10191         return true;
10192     },
10193
10194     
10195     on : function(key, fn, scope){
10196         var keyCode, shift, ctrl, alt;
10197         if(typeof key == "object" && !Ext.isArray(key)){
10198             keyCode = key.key;
10199             shift = key.shift;
10200             ctrl = key.ctrl;
10201             alt = key.alt;
10202         }else{
10203             keyCode = key;
10204         }
10205         this.addBinding({
10206             key: keyCode,
10207             shift: shift,
10208             ctrl: ctrl,
10209             alt: alt,
10210             fn: fn,
10211             scope: scope
10212         });
10213     },
10214
10215     
10216     handleKeyDown : function(e){
10217             if(this.enabled){ 
10218             var b = this.bindings;
10219             for(var i = 0, len = b.length; i < len; i++){
10220                 b[i].call(this, e);
10221             }
10222             }
10223         },
10224
10225         
10226         isEnabled : function(){
10227             return this.enabled;
10228         },
10229
10230         
10231         enable: function(){
10232                 if(!this.enabled){
10233                     this.el.on(this.eventName, this.handleKeyDown, this);
10234                     this.enabled = true;
10235                 }
10236         },
10237
10238         
10239         disable: function(){
10240                 if(this.enabled){
10241                     this.el.removeListener(this.eventName, this.handleKeyDown, this);
10242                     this.enabled = false;
10243                 }
10244         },
10245     
10246     
10247     setDisabled : function(disabled){
10248         this[disabled ? "disable" : "enable"]();
10249     }
10250 };
10251 Ext.util.TextMetrics = function(){
10252     var shared;
10253     return {
10254         
10255         measure : function(el, text, fixedWidth){
10256             if(!shared){
10257                 shared = Ext.util.TextMetrics.Instance(el, fixedWidth);
10258             }
10259             shared.bind(el);
10260             shared.setFixedWidth(fixedWidth || 'auto');
10261             return shared.getSize(text);
10262         },
10263
10264         
10265         createInstance : function(el, fixedWidth){
10266             return Ext.util.TextMetrics.Instance(el, fixedWidth);
10267         }
10268     };
10269 }();
10270
10271 Ext.util.TextMetrics.Instance = function(bindTo, fixedWidth){
10272     var ml = new Ext.Element(document.createElement('div'));
10273     document.body.appendChild(ml.dom);
10274     ml.position('absolute');
10275     ml.setLeftTop(-1000, -1000);
10276     ml.hide();
10277
10278     if(fixedWidth){
10279         ml.setWidth(fixedWidth);
10280     }
10281
10282     var instance = {
10283         
10284         getSize : function(text){
10285             ml.update(text);
10286             var s = ml.getSize();
10287             ml.update('');
10288             return s;
10289         },
10290
10291         
10292         bind : function(el){
10293             ml.setStyle(
10294                 Ext.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height', 'text-transform', 'letter-spacing')
10295             );
10296         },
10297
10298         
10299         setFixedWidth : function(width){
10300             ml.setWidth(width);
10301         },
10302
10303         
10304         getWidth : function(text){
10305             ml.dom.style.width = 'auto';
10306             return this.getSize(text).width;
10307         },
10308
10309         
10310         getHeight : function(text){
10311             return this.getSize(text).height;
10312         }
10313     };
10314
10315     instance.bind(bindTo);
10316
10317     return instance;
10318 };
10319
10320 Ext.Element.addMethods({
10321     
10322     getTextWidth : function(text, min, max){
10323         return (Ext.util.TextMetrics.measure(this.dom, Ext.value(text, this.dom.innerHTML, true)).width).constrain(min || 0, max || 1000000);
10324     }
10325 });
10326
10327 Ext.util.Cookies = {
10328     
10329     set : function(name, value){
10330         var argv = arguments;
10331         var argc = arguments.length;
10332         var expires = (argc > 2) ? argv[2] : null;
10333         var path = (argc > 3) ? argv[3] : '/';
10334         var domain = (argc > 4) ? argv[4] : null;
10335         var secure = (argc > 5) ? argv[5] : false;
10336         document.cookie = name + "=" + escape(value) + ((expires === null) ? "" : ("; expires=" + expires.toGMTString())) + ((path === null) ? "" : ("; path=" + path)) + ((domain === null) ? "" : ("; domain=" + domain)) + ((secure === true) ? "; secure" : "");
10337     },
10338
10339     
10340     get : function(name){
10341         var arg = name + "=";
10342         var alen = arg.length;
10343         var clen = document.cookie.length;
10344         var i = 0;
10345         var j = 0;
10346         while(i < clen){
10347             j = i + alen;
10348             if(document.cookie.substring(i, j) == arg){
10349                 return Ext.util.Cookies.getCookieVal(j);
10350             }
10351             i = document.cookie.indexOf(" ", i) + 1;
10352             if(i === 0){
10353                 break;
10354             }
10355         }
10356         return null;
10357     },
10358
10359     
10360     clear : function(name){
10361         if(Ext.util.Cookies.get(name)){
10362             document.cookie = name + "=" + "; expires=Thu, 01-Jan-70 00:00:01 GMT";
10363         }
10364     },
10365     
10366     getCookieVal : function(offset){
10367         var endstr = document.cookie.indexOf(";", offset);
10368         if(endstr == -1){
10369             endstr = document.cookie.length;
10370         }
10371         return unescape(document.cookie.substring(offset, endstr));
10372     }
10373 };
10374 Ext.handleError = function(e) {
10375     throw e;
10376 };
10377
10378
10379 Ext.Error = function(message) {
10380     
10381     this.message = (this.lang[message]) ? this.lang[message] : message;
10382 };
10383
10384 Ext.Error.prototype = new Error();
10385 Ext.apply(Ext.Error.prototype, {
10386     
10387     lang: {},
10388
10389     name: 'Ext.Error',
10390     
10391     getName : function() {
10392         return this.name;
10393     },
10394     
10395     getMessage : function() {
10396         return this.message;
10397     },
10398     
10399     toJson : function() {
10400         return Ext.encode(this);
10401     }
10402 });
10403
10404 Ext.ComponentMgr = function(){
10405     var all = new Ext.util.MixedCollection();
10406     var types = {};
10407     var ptypes = {};
10408
10409     return {
10410         
10411         register : function(c){
10412             all.add(c);
10413         },
10414
10415         
10416         unregister : function(c){
10417             all.remove(c);
10418         },
10419
10420         
10421         get : function(id){
10422             return all.get(id);
10423         },
10424
10425         
10426         onAvailable : function(id, fn, scope){
10427             all.on("add", function(index, o){
10428                 if(o.id == id){
10429                     fn.call(scope || o, o);
10430                     all.un("add", fn, scope);
10431                 }
10432             });
10433         },
10434
10435         
10436         all : all,
10437         
10438         
10439         types : types,
10440         
10441         
10442         ptypes: ptypes,
10443         
10444         
10445         isRegistered : function(xtype){
10446             return types[xtype] !== undefined;    
10447         },
10448         
10449         
10450         isPluginRegistered : function(ptype){
10451             return ptypes[ptype] !== undefined;    
10452         },        
10453
10454         
10455         registerType : function(xtype, cls){
10456             types[xtype] = cls;
10457             cls.xtype = xtype;
10458         },
10459
10460         
10461         create : function(config, defaultType){
10462             return config.render ? config : new types[config.xtype || defaultType](config);
10463         },
10464
10465         
10466         registerPlugin : function(ptype, cls){
10467             ptypes[ptype] = cls;
10468             cls.ptype = ptype;
10469         },
10470
10471         
10472         createPlugin : function(config, defaultType){
10473             var PluginCls = ptypes[config.ptype || defaultType];
10474             if (PluginCls.init) {
10475                 return PluginCls;                
10476             } else {
10477                 return new PluginCls(config);
10478             }            
10479         }
10480     };
10481 }();
10482
10483
10484 Ext.reg = Ext.ComponentMgr.registerType; 
10485
10486 Ext.preg = Ext.ComponentMgr.registerPlugin;
10487
10488 Ext.create = Ext.ComponentMgr.create;
10489 Ext.Component = function(config){
10490     config = config || {};
10491     if(config.initialConfig){
10492         if(config.isAction){           
10493             this.baseAction = config;
10494         }
10495         config = config.initialConfig; 
10496     }else if(config.tagName || config.dom || Ext.isString(config)){ 
10497         config = {applyTo: config, id: config.id || config};
10498     }
10499
10500     
10501     this.initialConfig = config;
10502
10503     Ext.apply(this, config);
10504     this.addEvents(
10505         
10506         'added',
10507         
10508         'disable',
10509         
10510         'enable',
10511         
10512         'beforeshow',
10513         
10514         'show',
10515         
10516         'beforehide',
10517         
10518         'hide',
10519         
10520         'removed',
10521         
10522         'beforerender',
10523         
10524         'render',
10525         
10526         'afterrender',
10527         
10528         'beforedestroy',
10529         
10530         'destroy',
10531         
10532         'beforestaterestore',
10533         
10534         'staterestore',
10535         
10536         'beforestatesave',
10537         
10538         'statesave'
10539     );
10540     this.getId();
10541     Ext.ComponentMgr.register(this);
10542     Ext.Component.superclass.constructor.call(this);
10543
10544     if(this.baseAction){
10545         this.baseAction.addComponent(this);
10546     }
10547
10548     this.initComponent();
10549
10550     if(this.plugins){
10551         if(Ext.isArray(this.plugins)){
10552             for(var i = 0, len = this.plugins.length; i < len; i++){
10553                 this.plugins[i] = this.initPlugin(this.plugins[i]);
10554             }
10555         }else{
10556             this.plugins = this.initPlugin(this.plugins);
10557         }
10558     }
10559
10560     if(this.stateful !== false){
10561         this.initState();
10562     }
10563
10564     if(this.applyTo){
10565         this.applyToMarkup(this.applyTo);
10566         delete this.applyTo;
10567     }else if(this.renderTo){
10568         this.render(this.renderTo);
10569         delete this.renderTo;
10570     }
10571 };
10572
10573
10574 Ext.Component.AUTO_ID = 1000;
10575
10576 Ext.extend(Ext.Component, Ext.util.Observable, {
10577     
10578     
10579     
10580     
10581     
10582     
10583     
10584
10585     
10586     
10587     
10588     
10589     
10590     
10591     
10592     
10593     
10594     disabled : false,
10595     
10596     hidden : false,
10597     
10598     
10599     
10600     
10601     
10602     
10603     
10604     autoEl : 'div',
10605
10606     
10607     disabledClass : 'x-item-disabled',
10608     
10609     allowDomMove : true,
10610     
10611     autoShow : false,
10612     
10613     hideMode : 'display',
10614     
10615     hideParent : false,
10616     
10617     
10618     
10619     
10620     
10621     rendered : false,
10622
10623     
10624     
10625
10626     
10627
10628     
10629     tplWriteMode : 'overwrite',
10630
10631     
10632     
10633     
10634     bubbleEvents: [],
10635
10636
10637     
10638     ctype : 'Ext.Component',
10639
10640     
10641     actionMode : 'el',
10642
10643     
10644     getActionEl : function(){
10645         return this[this.actionMode];
10646     },
10647
10648     initPlugin : function(p){
10649         if(p.ptype && !Ext.isFunction(p.init)){
10650             p = Ext.ComponentMgr.createPlugin(p);
10651         }else if(Ext.isString(p)){
10652             p = Ext.ComponentMgr.createPlugin({
10653                 ptype: p
10654             });
10655         }
10656         p.init(this);
10657         return p;
10658     },
10659
10660     
10661     initComponent : function(){
10662         
10663         if(this.listeners){
10664             this.on(this.listeners);
10665             delete this.listeners;
10666         }
10667         this.enableBubble(this.bubbleEvents);
10668     },
10669
10670     
10671     render : function(container, position){
10672         if(!this.rendered && this.fireEvent('beforerender', this) !== false){
10673             if(!container && this.el){
10674                 this.el = Ext.get(this.el);
10675                 container = this.el.dom.parentNode;
10676                 this.allowDomMove = false;
10677             }
10678             this.container = Ext.get(container);
10679             if(this.ctCls){
10680                 this.container.addClass(this.ctCls);
10681             }
10682             this.rendered = true;
10683             if(position !== undefined){
10684                 if(Ext.isNumber(position)){
10685                     position = this.container.dom.childNodes[position];
10686                 }else{
10687                     position = Ext.getDom(position);
10688                 }
10689             }
10690             this.onRender(this.container, position || null);
10691             if(this.autoShow){
10692                 this.el.removeClass(['x-hidden','x-hide-' + this.hideMode]);
10693             }
10694             if(this.cls){
10695                 this.el.addClass(this.cls);
10696                 delete this.cls;
10697             }
10698             if(this.style){
10699                 this.el.applyStyles(this.style);
10700                 delete this.style;
10701             }
10702             if(this.overCls){
10703                 this.el.addClassOnOver(this.overCls);
10704             }
10705             this.fireEvent('render', this);
10706
10707
10708             
10709             
10710             var contentTarget = this.getContentTarget();
10711             if (this.html){
10712                 contentTarget.update(Ext.DomHelper.markup(this.html));
10713                 delete this.html;
10714             }
10715             if (this.contentEl){
10716                 var ce = Ext.getDom(this.contentEl);
10717                 Ext.fly(ce).removeClass(['x-hidden', 'x-hide-display']);
10718                 contentTarget.appendChild(ce);
10719             }
10720             if (this.tpl) {
10721                 if (!this.tpl.compile) {
10722                     this.tpl = new Ext.XTemplate(this.tpl);
10723                 }
10724                 if (this.data) {
10725                     this.tpl[this.tplWriteMode](contentTarget, this.data);
10726                     delete this.data;
10727                 }
10728             }
10729             this.afterRender(this.container);
10730
10731
10732             if(this.hidden){
10733                 
10734                 this.doHide();
10735             }
10736             if(this.disabled){
10737                 
10738                 this.disable(true);
10739             }
10740
10741             if(this.stateful !== false){
10742                 this.initStateEvents();
10743             }
10744             this.fireEvent('afterrender', this);
10745         }
10746         return this;
10747     },
10748
10749
10750     
10751     update: function(htmlOrData, loadScripts, cb) {
10752         var contentTarget = this.getContentTarget();
10753         if (this.tpl && typeof htmlOrData !== "string") {
10754             this.tpl[this.tplWriteMode](contentTarget, htmlOrData || {});
10755         } else {
10756             var html = Ext.isObject(htmlOrData) ? Ext.DomHelper.markup(htmlOrData) : htmlOrData;
10757             contentTarget.update(html, loadScripts, cb);
10758         }
10759     },
10760
10761
10762     
10763     onAdded : function(container, pos) {
10764         this.ownerCt = container;
10765         this.initRef();
10766         this.fireEvent('added', this, container, pos);
10767     },
10768
10769     
10770     onRemoved : function() {
10771         this.removeRef();
10772         this.fireEvent('removed', this, this.ownerCt);
10773         delete this.ownerCt;
10774     },
10775
10776     
10777     initRef : function() {
10778         
10779         if(this.ref && !this.refOwner){
10780             var levels = this.ref.split('/'),
10781                 last = levels.length,
10782                 i = 0,
10783                 t = this;
10784
10785             while(t && i < last){
10786                 t = t.ownerCt;
10787                 ++i;
10788             }
10789             if(t){
10790                 t[this.refName = levels[--i]] = this;
10791                 
10792                 this.refOwner = t;
10793             }
10794         }
10795     },
10796
10797     removeRef : function() {
10798         if (this.refOwner && this.refName) {
10799             delete this.refOwner[this.refName];
10800             delete this.refOwner;
10801         }
10802     },
10803
10804     
10805     initState : function(){
10806         if(Ext.state.Manager){
10807             var id = this.getStateId();
10808             if(id){
10809                 var state = Ext.state.Manager.get(id);
10810                 if(state){
10811                     if(this.fireEvent('beforestaterestore', this, state) !== false){
10812                         this.applyState(Ext.apply({}, state));
10813                         this.fireEvent('staterestore', this, state);
10814                     }
10815                 }
10816             }
10817         }
10818     },
10819
10820     
10821     getStateId : function(){
10822         return this.stateId || ((/^(ext-comp-|ext-gen)/).test(String(this.id)) ? null : this.id);
10823     },
10824
10825     
10826     initStateEvents : function(){
10827         if(this.stateEvents){
10828             for(var i = 0, e; e = this.stateEvents[i]; i++){
10829                 this.on(e, this.saveState, this, {delay:100});
10830             }
10831         }
10832     },
10833
10834     
10835     applyState : function(state){
10836         if(state){
10837             Ext.apply(this, state);
10838         }
10839     },
10840
10841     
10842     getState : function(){
10843         return null;
10844     },
10845
10846     
10847     saveState : function(){
10848         if(Ext.state.Manager && this.stateful !== false){
10849             var id = this.getStateId();
10850             if(id){
10851                 var state = this.getState();
10852                 if(this.fireEvent('beforestatesave', this, state) !== false){
10853                     Ext.state.Manager.set(id, state);
10854                     this.fireEvent('statesave', this, state);
10855                 }
10856             }
10857         }
10858     },
10859
10860     
10861     applyToMarkup : function(el){
10862         this.allowDomMove = false;
10863         this.el = Ext.get(el);
10864         this.render(this.el.dom.parentNode);
10865     },
10866
10867     
10868     addClass : function(cls){
10869         if(this.el){
10870             this.el.addClass(cls);
10871         }else{
10872             this.cls = this.cls ? this.cls + ' ' + cls : cls;
10873         }
10874         return this;
10875     },
10876
10877     
10878     removeClass : function(cls){
10879         if(this.el){
10880             this.el.removeClass(cls);
10881         }else if(this.cls){
10882             this.cls = this.cls.split(' ').remove(cls).join(' ');
10883         }
10884         return this;
10885     },
10886
10887     
10888     
10889     onRender : function(ct, position){
10890         if(!this.el && this.autoEl){
10891             if(Ext.isString(this.autoEl)){
10892                 this.el = document.createElement(this.autoEl);
10893             }else{
10894                 var div = document.createElement('div');
10895                 Ext.DomHelper.overwrite(div, this.autoEl);
10896                 this.el = div.firstChild;
10897             }
10898             if (!this.el.id) {
10899                 this.el.id = this.getId();
10900             }
10901         }
10902         if(this.el){
10903             this.el = Ext.get(this.el);
10904             if(this.allowDomMove !== false){
10905                 ct.dom.insertBefore(this.el.dom, position);
10906                 if (div) {
10907                     Ext.removeNode(div);
10908                     div = null;
10909                 }
10910             }
10911         }
10912     },
10913
10914     
10915     getAutoCreate : function(){
10916         var cfg = Ext.isObject(this.autoCreate) ?
10917                       this.autoCreate : Ext.apply({}, this.defaultAutoCreate);
10918         if(this.id && !cfg.id){
10919             cfg.id = this.id;
10920         }
10921         return cfg;
10922     },
10923
10924     
10925     afterRender : Ext.emptyFn,
10926
10927     
10928     destroy : function(){
10929         if(!this.isDestroyed){
10930             if(this.fireEvent('beforedestroy', this) !== false){
10931                 this.destroying = true;
10932                 this.beforeDestroy();
10933                 if(this.ownerCt && this.ownerCt.remove){
10934                     this.ownerCt.remove(this, false);
10935                 }
10936                 if(this.rendered){
10937                     this.el.remove();
10938                     if(this.actionMode == 'container' || this.removeMode == 'container'){
10939                         this.container.remove();
10940                     }
10941                 }
10942                 
10943                 if(this.focusTask && this.focusTask.cancel){
10944                     this.focusTask.cancel();
10945                 }
10946                 this.onDestroy();
10947                 Ext.ComponentMgr.unregister(this);
10948                 this.fireEvent('destroy', this);
10949                 this.purgeListeners();
10950                 this.destroying = false;
10951                 this.isDestroyed = true;
10952             }
10953         }
10954     },
10955
10956     deleteMembers : function(){
10957         var args = arguments;
10958         for(var i = 0, len = args.length; i < len; ++i){
10959             delete this[args[i]];
10960         }
10961     },
10962
10963     
10964     beforeDestroy : Ext.emptyFn,
10965
10966     
10967     onDestroy  : Ext.emptyFn,
10968
10969     
10970     getEl : function(){
10971         return this.el;
10972     },
10973
10974     
10975     getContentTarget : function(){
10976         return this.el;
10977     },
10978
10979     
10980     getId : function(){
10981         return this.id || (this.id = 'ext-comp-' + (++Ext.Component.AUTO_ID));
10982     },
10983
10984     
10985     getItemId : function(){
10986         return this.itemId || this.getId();
10987     },
10988
10989     
10990     focus : function(selectText, delay){
10991         if(delay){
10992             this.focusTask = new Ext.util.DelayedTask(this.focus, this, [selectText, false]);
10993             this.focusTask.delay(Ext.isNumber(delay) ? delay : 10);
10994             return this;
10995         }
10996         if(this.rendered && !this.isDestroyed){
10997             this.el.focus();
10998             if(selectText === true){
10999                 this.el.dom.select();
11000             }
11001         }
11002         return this;
11003     },
11004
11005     
11006     blur : function(){
11007         if(this.rendered){
11008             this.el.blur();
11009         }
11010         return this;
11011     },
11012
11013     
11014     disable : function( silent){
11015         if(this.rendered){
11016             this.onDisable();
11017         }
11018         this.disabled = true;
11019         if(silent !== true){
11020             this.fireEvent('disable', this);
11021         }
11022         return this;
11023     },
11024
11025     
11026     onDisable : function(){
11027         this.getActionEl().addClass(this.disabledClass);
11028         this.el.dom.disabled = true;
11029     },
11030
11031     
11032     enable : function(){
11033         if(this.rendered){
11034             this.onEnable();
11035         }
11036         this.disabled = false;
11037         this.fireEvent('enable', this);
11038         return this;
11039     },
11040
11041     
11042     onEnable : function(){
11043         this.getActionEl().removeClass(this.disabledClass);
11044         this.el.dom.disabled = false;
11045     },
11046
11047     
11048     setDisabled : function(disabled){
11049         return this[disabled ? 'disable' : 'enable']();
11050     },
11051
11052     
11053     show : function(){
11054         if(this.fireEvent('beforeshow', this) !== false){
11055             this.hidden = false;
11056             if(this.autoRender){
11057                 this.render(Ext.isBoolean(this.autoRender) ? Ext.getBody() : this.autoRender);
11058             }
11059             if(this.rendered){
11060                 this.onShow();
11061             }
11062             this.fireEvent('show', this);
11063         }
11064         return this;
11065     },
11066
11067     
11068     onShow : function(){
11069         this.getVisibilityEl().removeClass('x-hide-' + this.hideMode);
11070     },
11071
11072     
11073     hide : function(){
11074         if(this.fireEvent('beforehide', this) !== false){
11075             this.doHide();
11076             this.fireEvent('hide', this);
11077         }
11078         return this;
11079     },
11080
11081     
11082     doHide: function(){
11083         this.hidden = true;
11084         if(this.rendered){
11085             this.onHide();
11086         }
11087     },
11088
11089     
11090     onHide : function(){
11091         this.getVisibilityEl().addClass('x-hide-' + this.hideMode);
11092     },
11093
11094     
11095     getVisibilityEl : function(){
11096         return this.hideParent ? this.container : this.getActionEl();
11097     },
11098
11099     
11100     setVisible : function(visible){
11101         return this[visible ? 'show' : 'hide']();
11102     },
11103
11104     
11105     isVisible : function(){
11106         return this.rendered && this.getVisibilityEl().isVisible();
11107     },
11108
11109     
11110     cloneConfig : function(overrides){
11111         overrides = overrides || {};
11112         var id = overrides.id || Ext.id();
11113         var cfg = Ext.applyIf(overrides, this.initialConfig);
11114         cfg.id = id; 
11115         return new this.constructor(cfg);
11116     },
11117
11118     
11119     getXType : function(){
11120         return this.constructor.xtype;
11121     },
11122
11123     
11124     isXType : function(xtype, shallow){
11125         
11126         if (Ext.isFunction(xtype)){
11127             xtype = xtype.xtype; 
11128         }else if (Ext.isObject(xtype)){
11129             xtype = xtype.constructor.xtype; 
11130         }
11131
11132         return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1 : this.constructor.xtype == xtype;
11133     },
11134
11135     
11136     getXTypes : function(){
11137         var tc = this.constructor;
11138         if(!tc.xtypes){
11139             var c = [], sc = this;
11140             while(sc && sc.constructor.xtype){
11141                 c.unshift(sc.constructor.xtype);
11142                 sc = sc.constructor.superclass;
11143             }
11144             tc.xtypeChain = c;
11145             tc.xtypes = c.join('/');
11146         }
11147         return tc.xtypes;
11148     },
11149
11150     
11151     findParentBy : function(fn) {
11152         for (var p = this.ownerCt; (p != null) && !fn(p, this); p = p.ownerCt);
11153         return p || null;
11154     },
11155
11156     
11157     findParentByType : function(xtype, shallow){
11158         return this.findParentBy(function(c){
11159             return c.isXType(xtype, shallow);
11160         });
11161     },
11162     
11163     
11164     bubble : function(fn, scope, args){
11165         var p = this;
11166         while(p){
11167             if(fn.apply(scope || p, args || [p]) === false){
11168                 break;
11169             }
11170             p = p.ownerCt;
11171         }
11172         return this;
11173     },
11174
11175     
11176     getPositionEl : function(){
11177         return this.positionEl || this.el;
11178     },
11179
11180     
11181     purgeListeners : function(){
11182         Ext.Component.superclass.purgeListeners.call(this);
11183         if(this.mons){
11184             this.on('beforedestroy', this.clearMons, this, {single: true});
11185         }
11186     },
11187
11188     
11189     clearMons : function(){
11190         Ext.each(this.mons, function(m){
11191             m.item.un(m.ename, m.fn, m.scope);
11192         }, this);
11193         this.mons = [];
11194     },
11195
11196     
11197     createMons: function(){
11198         if(!this.mons){
11199             this.mons = [];
11200             this.on('beforedestroy', this.clearMons, this, {single: true});
11201         }
11202     },
11203
11204     
11205     mon : function(item, ename, fn, scope, opt){
11206         this.createMons();
11207         if(Ext.isObject(ename)){
11208             var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
11209
11210             var o = ename;
11211             for(var e in o){
11212                 if(propRe.test(e)){
11213                     continue;
11214                 }
11215                 if(Ext.isFunction(o[e])){
11216                     
11217                     this.mons.push({
11218                         item: item, ename: e, fn: o[e], scope: o.scope
11219                     });
11220                     item.on(e, o[e], o.scope, o);
11221                 }else{
11222                     
11223                     this.mons.push({
11224                         item: item, ename: e, fn: o[e], scope: o.scope
11225                     });
11226                     item.on(e, o[e]);
11227                 }
11228             }
11229             return;
11230         }
11231
11232         this.mons.push({
11233             item: item, ename: ename, fn: fn, scope: scope
11234         });
11235         item.on(ename, fn, scope, opt);
11236     },
11237
11238     
11239     mun : function(item, ename, fn, scope){
11240         var found, mon;
11241         this.createMons();
11242         for(var i = 0, len = this.mons.length; i < len; ++i){
11243             mon = this.mons[i];
11244             if(item === mon.item && ename == mon.ename && fn === mon.fn && scope === mon.scope){
11245                 this.mons.splice(i, 1);
11246                 item.un(ename, fn, scope);
11247                 found = true;
11248                 break;
11249             }
11250         }
11251         return found;
11252     },
11253
11254     
11255     nextSibling : function(){
11256         if(this.ownerCt){
11257             var index = this.ownerCt.items.indexOf(this);
11258             if(index != -1 && index+1 < this.ownerCt.items.getCount()){
11259                 return this.ownerCt.items.itemAt(index+1);
11260             }
11261         }
11262         return null;
11263     },
11264
11265     
11266     previousSibling : function(){
11267         if(this.ownerCt){
11268             var index = this.ownerCt.items.indexOf(this);
11269             if(index > 0){
11270                 return this.ownerCt.items.itemAt(index-1);
11271             }
11272         }
11273         return null;
11274     },
11275
11276     
11277     getBubbleTarget : function(){
11278         return this.ownerCt;
11279     }
11280 });
11281
11282 Ext.reg('component', Ext.Component);
11283
11284 Ext.Action = Ext.extend(Object, {
11285     
11286     
11287     
11288     
11289     
11290     
11291     
11292
11293     constructor : function(config){
11294         this.initialConfig = config;
11295         this.itemId = config.itemId = (config.itemId || config.id || Ext.id());
11296         this.items = [];
11297     },
11298     
11299     
11300     isAction : true,
11301
11302     
11303     setText : function(text){
11304         this.initialConfig.text = text;
11305         this.callEach('setText', [text]);
11306     },
11307
11308     
11309     getText : function(){
11310         return this.initialConfig.text;
11311     },
11312
11313     
11314     setIconClass : function(cls){
11315         this.initialConfig.iconCls = cls;
11316         this.callEach('setIconClass', [cls]);
11317     },
11318
11319     
11320     getIconClass : function(){
11321         return this.initialConfig.iconCls;
11322     },
11323
11324     
11325     setDisabled : function(v){
11326         this.initialConfig.disabled = v;
11327         this.callEach('setDisabled', [v]);
11328     },
11329
11330     
11331     enable : function(){
11332         this.setDisabled(false);
11333     },
11334
11335     
11336     disable : function(){
11337         this.setDisabled(true);
11338     },
11339
11340     
11341     isDisabled : function(){
11342         return this.initialConfig.disabled;
11343     },
11344
11345     
11346     setHidden : function(v){
11347         this.initialConfig.hidden = v;
11348         this.callEach('setVisible', [!v]);
11349     },
11350
11351     
11352     show : function(){
11353         this.setHidden(false);
11354     },
11355
11356     
11357     hide : function(){
11358         this.setHidden(true);
11359     },
11360
11361     
11362     isHidden : function(){
11363         return this.initialConfig.hidden;
11364     },
11365
11366     
11367     setHandler : function(fn, scope){
11368         this.initialConfig.handler = fn;
11369         this.initialConfig.scope = scope;
11370         this.callEach('setHandler', [fn, scope]);
11371     },
11372
11373     
11374     each : function(fn, scope){
11375         Ext.each(this.items, fn, scope);
11376     },
11377
11378     
11379     callEach : function(fnName, args){
11380         var cs = this.items;
11381         for(var i = 0, len = cs.length; i < len; i++){
11382             cs[i][fnName].apply(cs[i], args);
11383         }
11384     },
11385
11386     
11387     addComponent : function(comp){
11388         this.items.push(comp);
11389         comp.on('destroy', this.removeComponent, this);
11390     },
11391
11392     
11393     removeComponent : function(comp){
11394         this.items.remove(comp);
11395     },
11396
11397     
11398     execute : function(){
11399         this.initialConfig.handler.apply(this.initialConfig.scope || window, arguments);
11400     }
11401 });
11402
11403 (function(){
11404 Ext.Layer = function(config, existingEl){
11405     config = config || {};
11406     var dh = Ext.DomHelper,
11407         cp = config.parentEl, pel = cp ? Ext.getDom(cp) : document.body;
11408         
11409     if (existingEl) {
11410         this.dom = Ext.getDom(existingEl);
11411     }
11412     if(!this.dom){
11413         var o = config.dh || {tag: 'div', cls: 'x-layer'};
11414         this.dom = dh.append(pel, o);
11415     }
11416     if(config.cls){
11417         this.addClass(config.cls);
11418     }
11419     this.constrain = config.constrain !== false;
11420     this.setVisibilityMode(Ext.Element.VISIBILITY);
11421     if(config.id){
11422         this.id = this.dom.id = config.id;
11423     }else{
11424         this.id = Ext.id(this.dom);
11425     }
11426     this.zindex = config.zindex || this.getZIndex();
11427     this.position('absolute', this.zindex);
11428     if(config.shadow){
11429         this.shadowOffset = config.shadowOffset || 4;
11430         this.shadow = new Ext.Shadow({
11431             offset : this.shadowOffset,
11432             mode : config.shadow
11433         });
11434     }else{
11435         this.shadowOffset = 0;
11436     }
11437     this.useShim = config.shim !== false && Ext.useShims;
11438     this.useDisplay = config.useDisplay;
11439     this.hide();
11440 };
11441
11442 var supr = Ext.Element.prototype;
11443
11444
11445 var shims = [];
11446
11447 Ext.extend(Ext.Layer, Ext.Element, {
11448
11449     getZIndex : function(){
11450         return this.zindex || parseInt((this.getShim() || this).getStyle('z-index'), 10) || 11000;
11451     },
11452
11453     getShim : function(){
11454         if(!this.useShim){
11455             return null;
11456         }
11457         if(this.shim){
11458             return this.shim;
11459         }
11460         var shim = shims.shift();
11461         if(!shim){
11462             shim = this.createShim();
11463             shim.enableDisplayMode('block');
11464             shim.dom.style.display = 'none';
11465             shim.dom.style.visibility = 'visible';
11466         }
11467         var pn = this.dom.parentNode;
11468         if(shim.dom.parentNode != pn){
11469             pn.insertBefore(shim.dom, this.dom);
11470         }
11471         shim.setStyle('z-index', this.getZIndex()-2);
11472         this.shim = shim;
11473         return shim;
11474     },
11475
11476     hideShim : function(){
11477         if(this.shim){
11478             this.shim.setDisplayed(false);
11479             shims.push(this.shim);
11480             delete this.shim;
11481         }
11482     },
11483
11484     disableShadow : function(){
11485         if(this.shadow){
11486             this.shadowDisabled = true;
11487             this.shadow.hide();
11488             this.lastShadowOffset = this.shadowOffset;
11489             this.shadowOffset = 0;
11490         }
11491     },
11492
11493     enableShadow : function(show){
11494         if(this.shadow){
11495             this.shadowDisabled = false;
11496             this.shadowOffset = this.lastShadowOffset;
11497             delete this.lastShadowOffset;
11498             if(show){
11499                 this.sync(true);
11500             }
11501         }
11502     },
11503
11504     
11505     
11506     
11507     sync : function(doShow){
11508         var shadow = this.shadow;
11509         if(!this.updating && this.isVisible() && (shadow || this.useShim)){
11510             var shim = this.getShim(),
11511                 w = this.getWidth(),
11512                 h = this.getHeight(),
11513                 l = this.getLeft(true),
11514                 t = this.getTop(true);
11515
11516             if(shadow && !this.shadowDisabled){
11517                 if(doShow && !shadow.isVisible()){
11518                     shadow.show(this);
11519                 }else{
11520                     shadow.realign(l, t, w, h);
11521                 }
11522                 if(shim){
11523                     if(doShow){
11524                        shim.show();
11525                     }
11526                     
11527                     var shadowAdj = shadow.el.getXY(), shimStyle = shim.dom.style,
11528                         shadowSize = shadow.el.getSize();
11529                     shimStyle.left = (shadowAdj[0])+'px';
11530                     shimStyle.top = (shadowAdj[1])+'px';
11531                     shimStyle.width = (shadowSize.width)+'px';
11532                     shimStyle.height = (shadowSize.height)+'px';
11533                 }
11534             }else if(shim){
11535                 if(doShow){
11536                    shim.show();
11537                 }
11538                 shim.setSize(w, h);
11539                 shim.setLeftTop(l, t);
11540             }
11541         }
11542     },
11543
11544     
11545     destroy : function(){
11546         this.hideShim();
11547         if(this.shadow){
11548             this.shadow.hide();
11549         }
11550         this.removeAllListeners();
11551         Ext.removeNode(this.dom);
11552         delete this.dom;
11553     },
11554
11555     remove : function(){
11556         this.destroy();
11557     },
11558
11559     
11560     beginUpdate : function(){
11561         this.updating = true;
11562     },
11563
11564     
11565     endUpdate : function(){
11566         this.updating = false;
11567         this.sync(true);
11568     },
11569
11570     
11571     hideUnders : function(negOffset){
11572         if(this.shadow){
11573             this.shadow.hide();
11574         }
11575         this.hideShim();
11576     },
11577
11578     
11579     constrainXY : function(){
11580         if(this.constrain){
11581             var vw = Ext.lib.Dom.getViewWidth(),
11582                 vh = Ext.lib.Dom.getViewHeight();
11583             var s = Ext.getDoc().getScroll();
11584
11585             var xy = this.getXY();
11586             var x = xy[0], y = xy[1];
11587             var so = this.shadowOffset;
11588             var w = this.dom.offsetWidth+so, h = this.dom.offsetHeight+so;
11589             
11590             var moved = false;
11591             
11592             if((x + w) > vw+s.left){
11593                 x = vw - w - so;
11594                 moved = true;
11595             }
11596             if((y + h) > vh+s.top){
11597                 y = vh - h - so;
11598                 moved = true;
11599             }
11600             
11601             if(x < s.left){
11602                 x = s.left;
11603                 moved = true;
11604             }
11605             if(y < s.top){
11606                 y = s.top;
11607                 moved = true;
11608             }
11609             if(moved){
11610                 if(this.avoidY){
11611                     var ay = this.avoidY;
11612                     if(y <= ay && (y+h) >= ay){
11613                         y = ay-h-5;
11614                     }
11615                 }
11616                 xy = [x, y];
11617                 this.storeXY(xy);
11618                 supr.setXY.call(this, xy);
11619                 this.sync();
11620             }
11621         }
11622         return this;
11623     },
11624     
11625     getConstrainOffset : function(){
11626         return this.shadowOffset;    
11627     },
11628
11629     isVisible : function(){
11630         return this.visible;
11631     },
11632
11633     
11634     showAction : function(){
11635         this.visible = true; 
11636         if(this.useDisplay === true){
11637             this.setDisplayed('');
11638         }else if(this.lastXY){
11639             supr.setXY.call(this, this.lastXY);
11640         }else if(this.lastLT){
11641             supr.setLeftTop.call(this, this.lastLT[0], this.lastLT[1]);
11642         }
11643     },
11644
11645     
11646     hideAction : function(){
11647         this.visible = false;
11648         if(this.useDisplay === true){
11649             this.setDisplayed(false);
11650         }else{
11651             this.setLeftTop(-10000,-10000);
11652         }
11653     },
11654
11655     
11656     setVisible : function(v, a, d, c, e){
11657         if(v){
11658             this.showAction();
11659         }
11660         if(a && v){
11661             var cb = function(){
11662                 this.sync(true);
11663                 if(c){
11664                     c();
11665                 }
11666             }.createDelegate(this);
11667             supr.setVisible.call(this, true, true, d, cb, e);
11668         }else{
11669             if(!v){
11670                 this.hideUnders(true);
11671             }
11672             var cb = c;
11673             if(a){
11674                 cb = function(){
11675                     this.hideAction();
11676                     if(c){
11677                         c();
11678                     }
11679                 }.createDelegate(this);
11680             }
11681             supr.setVisible.call(this, v, a, d, cb, e);
11682             if(v){
11683                 this.sync(true);
11684             }else if(!a){
11685                 this.hideAction();
11686             }
11687         }
11688         return this;
11689     },
11690
11691     storeXY : function(xy){
11692         delete this.lastLT;
11693         this.lastXY = xy;
11694     },
11695
11696     storeLeftTop : function(left, top){
11697         delete this.lastXY;
11698         this.lastLT = [left, top];
11699     },
11700
11701     
11702     beforeFx : function(){
11703         this.beforeAction();
11704         return Ext.Layer.superclass.beforeFx.apply(this, arguments);
11705     },
11706
11707     
11708     afterFx : function(){
11709         Ext.Layer.superclass.afterFx.apply(this, arguments);
11710         this.sync(this.isVisible());
11711     },
11712
11713     
11714     beforeAction : function(){
11715         if(!this.updating && this.shadow){
11716             this.shadow.hide();
11717         }
11718     },
11719
11720     
11721     setLeft : function(left){
11722         this.storeLeftTop(left, this.getTop(true));
11723         supr.setLeft.apply(this, arguments);
11724         this.sync();
11725         return this;
11726     },
11727
11728     setTop : function(top){
11729         this.storeLeftTop(this.getLeft(true), top);
11730         supr.setTop.apply(this, arguments);
11731         this.sync();
11732         return this;
11733     },
11734
11735     setLeftTop : function(left, top){
11736         this.storeLeftTop(left, top);
11737         supr.setLeftTop.apply(this, arguments);
11738         this.sync();
11739         return this;
11740     },
11741
11742     setXY : function(xy, a, d, c, e){
11743         this.fixDisplay();
11744         this.beforeAction();
11745         this.storeXY(xy);
11746         var cb = this.createCB(c);
11747         supr.setXY.call(this, xy, a, d, cb, e);
11748         if(!a){
11749             cb();
11750         }
11751         return this;
11752     },
11753
11754     
11755     createCB : function(c){
11756         var el = this;
11757         return function(){
11758             el.constrainXY();
11759             el.sync(true);
11760             if(c){
11761                 c();
11762             }
11763         };
11764     },
11765
11766     
11767     setX : function(x, a, d, c, e){
11768         this.setXY([x, this.getY()], a, d, c, e);
11769         return this;
11770     },
11771
11772     
11773     setY : function(y, a, d, c, e){
11774         this.setXY([this.getX(), y], a, d, c, e);
11775         return this;
11776     },
11777
11778     
11779     setSize : function(w, h, a, d, c, e){
11780         this.beforeAction();
11781         var cb = this.createCB(c);
11782         supr.setSize.call(this, w, h, a, d, cb, e);
11783         if(!a){
11784             cb();
11785         }
11786         return this;
11787     },
11788
11789     
11790     setWidth : function(w, a, d, c, e){
11791         this.beforeAction();
11792         var cb = this.createCB(c);
11793         supr.setWidth.call(this, w, a, d, cb, e);
11794         if(!a){
11795             cb();
11796         }
11797         return this;
11798     },
11799
11800     
11801     setHeight : function(h, a, d, c, e){
11802         this.beforeAction();
11803         var cb = this.createCB(c);
11804         supr.setHeight.call(this, h, a, d, cb, e);
11805         if(!a){
11806             cb();
11807         }
11808         return this;
11809     },
11810
11811     
11812     setBounds : function(x, y, w, h, a, d, c, e){
11813         this.beforeAction();
11814         var cb = this.createCB(c);
11815         if(!a){
11816             this.storeXY([x, y]);
11817             supr.setXY.call(this, [x, y]);
11818             supr.setSize.call(this, w, h, a, d, cb, e);
11819             cb();
11820         }else{
11821             supr.setBounds.call(this, x, y, w, h, a, d, cb, e);
11822         }
11823         return this;
11824     },
11825
11826     
11827     setZIndex : function(zindex){
11828         this.zindex = zindex;
11829         this.setStyle('z-index', zindex + 2);
11830         if(this.shadow){
11831             this.shadow.setZIndex(zindex + 1);
11832         }
11833         if(this.shim){
11834             this.shim.setStyle('z-index', zindex);
11835         }
11836         return this;
11837     }
11838 });
11839 })();
11840
11841 Ext.Shadow = function(config) {
11842     Ext.apply(this, config);
11843     if (typeof this.mode != "string") {
11844         this.mode = this.defaultMode;
11845     }
11846     var o = this.offset,
11847         a = {
11848             h: 0
11849         },
11850         rad = Math.floor(this.offset / 2);
11851     switch (this.mode.toLowerCase()) {
11852         
11853         case "drop":
11854             a.w = 0;
11855             a.l = a.t = o;
11856             a.t -= 1;
11857             if (Ext.isIE) {
11858                 a.l -= this.offset + rad;
11859                 a.t -= this.offset + rad;
11860                 a.w -= rad;
11861                 a.h -= rad;
11862                 a.t += 1;
11863             }
11864         break;
11865         case "sides":
11866             a.w = (o * 2);
11867             a.l = -o;
11868             a.t = o - 1;
11869             if (Ext.isIE) {
11870                 a.l -= (this.offset - rad);
11871                 a.t -= this.offset + rad;
11872                 a.l += 1;
11873                 a.w -= (this.offset - rad) * 2;
11874                 a.w -= rad + 1;
11875                 a.h -= 1;
11876             }
11877         break;
11878         case "frame":
11879             a.w = a.h = (o * 2);
11880             a.l = a.t = -o;
11881             a.t += 1;
11882             a.h -= 2;
11883             if (Ext.isIE) {
11884                 a.l -= (this.offset - rad);
11885                 a.t -= (this.offset - rad);
11886                 a.l += 1;
11887                 a.w -= (this.offset + rad + 1);
11888                 a.h -= (this.offset + rad);
11889                 a.h += 1;
11890             }
11891         break;
11892     };
11893
11894     this.adjusts = a;
11895 };
11896
11897 Ext.Shadow.prototype = {
11898     
11899     
11900     offset: 4,
11901
11902     
11903     defaultMode: "drop",
11904
11905     
11906     show: function(target) {
11907         target = Ext.get(target);
11908         if (!this.el) {
11909             this.el = Ext.Shadow.Pool.pull();
11910             if (this.el.dom.nextSibling != target.dom) {
11911                 this.el.insertBefore(target);
11912             }
11913         }
11914         this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10) - 1);
11915         if (Ext.isIE) {
11916             this.el.dom.style.filter = "progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius=" + (this.offset) + ")";
11917         }
11918         this.realign(
11919         target.getLeft(true),
11920         target.getTop(true),
11921         target.getWidth(),
11922         target.getHeight()
11923         );
11924         this.el.dom.style.display = "block";
11925     },
11926
11927     
11928     isVisible: function() {
11929         return this.el ? true: false;
11930     },
11931
11932     
11933     realign: function(l, t, w, h) {
11934         if (!this.el) {
11935             return;
11936         }
11937         var a = this.adjusts,
11938             d = this.el.dom,
11939             s = d.style,
11940             iea = 0,
11941             sw = (w + a.w),
11942             sh = (h + a.h),
11943             sws = sw + "px",
11944             shs = sh + "px",
11945             cn,
11946             sww;
11947         s.left = (l + a.l) + "px";
11948         s.top = (t + a.t) + "px";
11949         if (s.width != sws || s.height != shs) {
11950             s.width = sws;
11951             s.height = shs;
11952             if (!Ext.isIE) {
11953                 cn = d.childNodes;
11954                 sww = Math.max(0, (sw - 12)) + "px";
11955                 cn[0].childNodes[1].style.width = sww;
11956                 cn[1].childNodes[1].style.width = sww;
11957                 cn[2].childNodes[1].style.width = sww;
11958                 cn[1].style.height = Math.max(0, (sh - 12)) + "px";
11959             }
11960         }
11961     },
11962
11963     
11964     hide: function() {
11965         if (this.el) {
11966             this.el.dom.style.display = "none";
11967             Ext.Shadow.Pool.push(this.el);
11968             delete this.el;
11969         }
11970     },
11971
11972     
11973     setZIndex: function(z) {
11974         this.zIndex = z;
11975         if (this.el) {
11976             this.el.setStyle("z-index", z);
11977         }
11978     }
11979 };
11980
11981
11982 Ext.Shadow.Pool = function() {
11983     var p = [],
11984         markup = Ext.isIE ?
11985             '<div class="x-ie-shadow"></div>':
11986             '<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>';
11987     return {
11988         pull: function() {
11989             var sh = p.shift();
11990             if (!sh) {
11991                 sh = Ext.get(Ext.DomHelper.insertHtml("beforeBegin", document.body.firstChild, markup));
11992                 sh.autoBoxAdjust = false;
11993             }
11994             return sh;
11995         },
11996
11997         push: function(sh) {
11998             p.push(sh);
11999         }
12000     };
12001 }();
12002 Ext.BoxComponent = Ext.extend(Ext.Component, {
12003
12004     
12005     
12006     
12007     
12008     
12009     
12010     
12011     
12012     
12013     
12014     
12015     
12016     
12017     
12018     
12019     
12020     
12021     
12022     
12023     
12024     
12025     
12026     
12027
12028     
12029
12030     
12031     initComponent : function(){
12032         Ext.BoxComponent.superclass.initComponent.call(this);
12033         this.addEvents(
12034             
12035             'resize',
12036             
12037             'move'
12038         );
12039     },
12040
12041     
12042     boxReady : false,
12043     
12044     deferHeight: false,
12045
12046     
12047     setSize : function(w, h){
12048
12049         
12050         if(typeof w == 'object'){
12051             h = w.height;
12052             w = w.width;
12053         }
12054         if (Ext.isDefined(w) && Ext.isDefined(this.boxMinWidth) && (w < this.boxMinWidth)) {
12055             w = this.boxMinWidth;
12056         }
12057         if (Ext.isDefined(h) && Ext.isDefined(this.boxMinHeight) && (h < this.boxMinHeight)) {
12058             h = this.boxMinHeight;
12059         }
12060         if (Ext.isDefined(w) && Ext.isDefined(this.boxMaxWidth) && (w > this.boxMaxWidth)) {
12061             w = this.boxMaxWidth;
12062         }
12063         if (Ext.isDefined(h) && Ext.isDefined(this.boxMaxHeight) && (h > this.boxMaxHeight)) {
12064             h = this.boxMaxHeight;
12065         }
12066         
12067         if(!this.boxReady){
12068             this.width  = w;
12069             this.height = h;
12070             return this;
12071         }
12072
12073         
12074         if(this.cacheSizes !== false && this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
12075             return this;
12076         }
12077         this.lastSize = {width: w, height: h};
12078         var adj = this.adjustSize(w, h),
12079             aw = adj.width,
12080             ah = adj.height,
12081             rz;
12082         if(aw !== undefined || ah !== undefined){ 
12083             rz = this.getResizeEl();
12084             if(!this.deferHeight && aw !== undefined && ah !== undefined){
12085                 rz.setSize(aw, ah);
12086             }else if(!this.deferHeight && ah !== undefined){
12087                 rz.setHeight(ah);
12088             }else if(aw !== undefined){
12089                 rz.setWidth(aw);
12090             }
12091             this.onResize(aw, ah, w, h);
12092             this.fireEvent('resize', this, aw, ah, w, h);
12093         }
12094         return this;
12095     },
12096
12097     
12098     setWidth : function(width){
12099         return this.setSize(width);
12100     },
12101
12102     
12103     setHeight : function(height){
12104         return this.setSize(undefined, height);
12105     },
12106
12107     
12108     getSize : function(){
12109         return this.getResizeEl().getSize();
12110     },
12111
12112     
12113     getWidth : function(){
12114         return this.getResizeEl().getWidth();
12115     },
12116
12117     
12118     getHeight : function(){
12119         return this.getResizeEl().getHeight();
12120     },
12121
12122     
12123     getOuterSize : function(){
12124         var el = this.getResizeEl();
12125         return {width: el.getWidth() + el.getMargins('lr'),
12126                 height: el.getHeight() + el.getMargins('tb')};
12127     },
12128
12129     
12130     getPosition : function(local){
12131         var el = this.getPositionEl();
12132         if(local === true){
12133             return [el.getLeft(true), el.getTop(true)];
12134         }
12135         return this.xy || el.getXY();
12136     },
12137
12138     
12139     getBox : function(local){
12140         var pos = this.getPosition(local);
12141         var s = this.getSize();
12142         s.x = pos[0];
12143         s.y = pos[1];
12144         return s;
12145     },
12146
12147     
12148     updateBox : function(box){
12149         this.setSize(box.width, box.height);
12150         this.setPagePosition(box.x, box.y);
12151         return this;
12152     },
12153
12154     
12155     getResizeEl : function(){
12156         return this.resizeEl || this.el;
12157     },
12158
12159     
12160     setAutoScroll : function(scroll){
12161         if(this.rendered){
12162             this.getContentTarget().setOverflow(scroll ? 'auto' : '');
12163         }
12164         this.autoScroll = scroll;
12165         return this;
12166     },
12167
12168     
12169     setPosition : function(x, y){
12170         if(x && typeof x[1] == 'number'){
12171             y = x[1];
12172             x = x[0];
12173         }
12174         this.x = x;
12175         this.y = y;
12176         if(!this.boxReady){
12177             return this;
12178         }
12179         var adj = this.adjustPosition(x, y);
12180         var ax = adj.x, ay = adj.y;
12181
12182         var el = this.getPositionEl();
12183         if(ax !== undefined || ay !== undefined){
12184             if(ax !== undefined && ay !== undefined){
12185                 el.setLeftTop(ax, ay);
12186             }else if(ax !== undefined){
12187                 el.setLeft(ax);
12188             }else if(ay !== undefined){
12189                 el.setTop(ay);
12190             }
12191             this.onPosition(ax, ay);
12192             this.fireEvent('move', this, ax, ay);
12193         }
12194         return this;
12195     },
12196
12197     
12198     setPagePosition : function(x, y){
12199         if(x && typeof x[1] == 'number'){
12200             y = x[1];
12201             x = x[0];
12202         }
12203         this.pageX = x;
12204         this.pageY = y;
12205         if(!this.boxReady){
12206             return;
12207         }
12208         if(x === undefined || y === undefined){ 
12209             return;
12210         }
12211         var p = this.getPositionEl().translatePoints(x, y);
12212         this.setPosition(p.left, p.top);
12213         return this;
12214     },
12215
12216     
12217     afterRender : function(){
12218         Ext.BoxComponent.superclass.afterRender.call(this);
12219         if(this.resizeEl){
12220             this.resizeEl = Ext.get(this.resizeEl);
12221         }
12222         if(this.positionEl){
12223             this.positionEl = Ext.get(this.positionEl);
12224         }
12225         this.boxReady = true;
12226         Ext.isDefined(this.autoScroll) && this.setAutoScroll(this.autoScroll);
12227         this.setSize(this.width, this.height);
12228         if(this.x || this.y){
12229             this.setPosition(this.x, this.y);
12230         }else if(this.pageX || this.pageY){
12231             this.setPagePosition(this.pageX, this.pageY);
12232         }
12233     },
12234
12235     
12236     syncSize : function(){
12237         delete this.lastSize;
12238         this.setSize(this.autoWidth ? undefined : this.getResizeEl().getWidth(), this.autoHeight ? undefined : this.getResizeEl().getHeight());
12239         return this;
12240     },
12241
12242     
12243     onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
12244     },
12245
12246     
12247     onPosition : function(x, y){
12248
12249     },
12250
12251     
12252     adjustSize : function(w, h){
12253         if(this.autoWidth){
12254             w = 'auto';
12255         }
12256         if(this.autoHeight){
12257             h = 'auto';
12258         }
12259         return {width : w, height: h};
12260     },
12261
12262     
12263     adjustPosition : function(x, y){
12264         return {x : x, y: y};
12265     }
12266 });
12267 Ext.reg('box', Ext.BoxComponent);
12268
12269
12270
12271 Ext.Spacer = Ext.extend(Ext.BoxComponent, {
12272     autoEl:'div'
12273 });
12274 Ext.reg('spacer', Ext.Spacer);
12275 Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy){
12276
12277     
12278     this.el = Ext.get(dragElement, true);
12279     this.el.dom.unselectable = "on";
12280     
12281     this.resizingEl = Ext.get(resizingElement, true);
12282
12283     
12284     this.orientation = orientation || Ext.SplitBar.HORIZONTAL;
12285
12286     
12287     
12288     this.minSize = 0;
12289
12290     
12291     this.maxSize = 2000;
12292
12293     
12294     this.animate = false;
12295
12296     
12297     this.useShim = false;
12298
12299     
12300     this.shim = null;
12301
12302     if(!existingProxy){
12303         
12304         this.proxy = Ext.SplitBar.createProxy(this.orientation);
12305     }else{
12306         this.proxy = Ext.get(existingProxy).dom;
12307     }
12308     
12309     this.dd = new Ext.dd.DDProxy(this.el.dom.id, "XSplitBars", {dragElId : this.proxy.id});
12310
12311     
12312     this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);
12313
12314     
12315     this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);
12316
12317     
12318     this.dragSpecs = {};
12319
12320     
12321     this.adapter = new Ext.SplitBar.BasicLayoutAdapter();
12322     this.adapter.init(this);
12323
12324     if(this.orientation == Ext.SplitBar.HORIZONTAL){
12325         
12326         this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? Ext.SplitBar.LEFT : Ext.SplitBar.RIGHT);
12327         this.el.addClass("x-splitbar-h");
12328     }else{
12329         
12330         this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? Ext.SplitBar.TOP : Ext.SplitBar.BOTTOM);
12331         this.el.addClass("x-splitbar-v");
12332     }
12333
12334     this.addEvents(
12335         
12336         "resize",
12337         
12338         "moved",
12339         
12340         "beforeresize",
12341
12342         "beforeapply"
12343     );
12344
12345     Ext.SplitBar.superclass.constructor.call(this);
12346 };
12347
12348 Ext.extend(Ext.SplitBar, Ext.util.Observable, {
12349     onStartProxyDrag : function(x, y){
12350         this.fireEvent("beforeresize", this);
12351         this.overlay =  Ext.DomHelper.append(document.body,  {cls: "x-drag-overlay", html: "&#160;"}, true);
12352         this.overlay.unselectable();
12353         this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
12354         this.overlay.show();
12355         Ext.get(this.proxy).setDisplayed("block");
12356         var size = this.adapter.getElementSize(this);
12357         this.activeMinSize = this.getMinimumSize();
12358         this.activeMaxSize = this.getMaximumSize();
12359         var c1 = size - this.activeMinSize;
12360         var c2 = Math.max(this.activeMaxSize - size, 0);
12361         if(this.orientation == Ext.SplitBar.HORIZONTAL){
12362             this.dd.resetConstraints();
12363             this.dd.setXConstraint(
12364                 this.placement == Ext.SplitBar.LEFT ? c1 : c2,
12365                 this.placement == Ext.SplitBar.LEFT ? c2 : c1,
12366                 this.tickSize
12367             );
12368             this.dd.setYConstraint(0, 0);
12369         }else{
12370             this.dd.resetConstraints();
12371             this.dd.setXConstraint(0, 0);
12372             this.dd.setYConstraint(
12373                 this.placement == Ext.SplitBar.TOP ? c1 : c2,
12374                 this.placement == Ext.SplitBar.TOP ? c2 : c1,
12375                 this.tickSize
12376             );
12377          }
12378         this.dragSpecs.startSize = size;
12379         this.dragSpecs.startPoint = [x, y];
12380         Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);
12381     },
12382
12383     
12384     onEndProxyDrag : function(e){
12385         Ext.get(this.proxy).setDisplayed(false);
12386         var endPoint = Ext.lib.Event.getXY(e);
12387         if(this.overlay){
12388             Ext.destroy(this.overlay);
12389             delete this.overlay;
12390         }
12391         var newSize;
12392         if(this.orientation == Ext.SplitBar.HORIZONTAL){
12393             newSize = this.dragSpecs.startSize +
12394                 (this.placement == Ext.SplitBar.LEFT ?
12395                     endPoint[0] - this.dragSpecs.startPoint[0] :
12396                     this.dragSpecs.startPoint[0] - endPoint[0]
12397                 );
12398         }else{
12399             newSize = this.dragSpecs.startSize +
12400                 (this.placement == Ext.SplitBar.TOP ?
12401                     endPoint[1] - this.dragSpecs.startPoint[1] :
12402                     this.dragSpecs.startPoint[1] - endPoint[1]
12403                 );
12404         }
12405         newSize = Math.min(Math.max(newSize, this.activeMinSize), this.activeMaxSize);
12406         if(newSize != this.dragSpecs.startSize){
12407             if(this.fireEvent('beforeapply', this, newSize) !== false){
12408                 this.adapter.setElementSize(this, newSize);
12409                 this.fireEvent("moved", this, newSize);
12410                 this.fireEvent("resize", this, newSize);
12411             }
12412         }
12413     },
12414
12415     
12416     getAdapter : function(){
12417         return this.adapter;
12418     },
12419
12420     
12421     setAdapter : function(adapter){
12422         this.adapter = adapter;
12423         this.adapter.init(this);
12424     },
12425
12426     
12427     getMinimumSize : function(){
12428         return this.minSize;
12429     },
12430
12431     
12432     setMinimumSize : function(minSize){
12433         this.minSize = minSize;
12434     },
12435
12436     
12437     getMaximumSize : function(){
12438         return this.maxSize;
12439     },
12440
12441     
12442     setMaximumSize : function(maxSize){
12443         this.maxSize = maxSize;
12444     },
12445
12446     
12447     setCurrentSize : function(size){
12448         var oldAnimate = this.animate;
12449         this.animate = false;
12450         this.adapter.setElementSize(this, size);
12451         this.animate = oldAnimate;
12452     },
12453
12454     
12455     destroy : function(removeEl){
12456         Ext.destroy(this.shim, Ext.get(this.proxy));
12457         this.dd.unreg();
12458         if(removeEl){
12459             this.el.remove();
12460         }
12461         this.purgeListeners();
12462     }
12463 });
12464
12465
12466 Ext.SplitBar.createProxy = function(dir){
12467     var proxy = new Ext.Element(document.createElement("div"));
12468     document.body.appendChild(proxy.dom);
12469     proxy.unselectable();
12470     var cls = 'x-splitbar-proxy';
12471     proxy.addClass(cls + ' ' + (dir == Ext.SplitBar.HORIZONTAL ? cls +'-h' : cls + '-v'));
12472     return proxy.dom;
12473 };
12474
12475
12476 Ext.SplitBar.BasicLayoutAdapter = function(){
12477 };
12478
12479 Ext.SplitBar.BasicLayoutAdapter.prototype = {
12480     
12481     init : function(s){
12482
12483     },
12484     
12485      getElementSize : function(s){
12486         if(s.orientation == Ext.SplitBar.HORIZONTAL){
12487             return s.resizingEl.getWidth();
12488         }else{
12489             return s.resizingEl.getHeight();
12490         }
12491     },
12492
12493     
12494     setElementSize : function(s, newSize, onComplete){
12495         if(s.orientation == Ext.SplitBar.HORIZONTAL){
12496             if(!s.animate){
12497                 s.resizingEl.setWidth(newSize);
12498                 if(onComplete){
12499                     onComplete(s, newSize);
12500                 }
12501             }else{
12502                 s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');
12503             }
12504         }else{
12505
12506             if(!s.animate){
12507                 s.resizingEl.setHeight(newSize);
12508                 if(onComplete){
12509                     onComplete(s, newSize);
12510                 }
12511             }else{
12512                 s.resizingEl.setHeight(newSize, true, .1, onComplete, 'easeOut');
12513             }
12514         }
12515     }
12516 };
12517
12518
12519 Ext.SplitBar.AbsoluteLayoutAdapter = function(container){
12520     this.basic = new Ext.SplitBar.BasicLayoutAdapter();
12521     this.container = Ext.get(container);
12522 };
12523
12524 Ext.SplitBar.AbsoluteLayoutAdapter.prototype = {
12525     init : function(s){
12526         this.basic.init(s);
12527     },
12528
12529     getElementSize : function(s){
12530         return this.basic.getElementSize(s);
12531     },
12532
12533     setElementSize : function(s, newSize, onComplete){
12534         this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));
12535     },
12536
12537     moveSplitter : function(s){
12538         var yes = Ext.SplitBar;
12539         switch(s.placement){
12540             case yes.LEFT:
12541                 s.el.setX(s.resizingEl.getRight());
12542                 break;
12543             case yes.RIGHT:
12544                 s.el.setStyle("right", (this.container.getWidth() - s.resizingEl.getLeft()) + "px");
12545                 break;
12546             case yes.TOP:
12547                 s.el.setY(s.resizingEl.getBottom());
12548                 break;
12549             case yes.BOTTOM:
12550                 s.el.setY(s.resizingEl.getTop() - s.el.getHeight());
12551                 break;
12552         }
12553     }
12554 };
12555
12556
12557 Ext.SplitBar.VERTICAL = 1;
12558
12559
12560 Ext.SplitBar.HORIZONTAL = 2;
12561
12562
12563 Ext.SplitBar.LEFT = 1;
12564
12565
12566 Ext.SplitBar.RIGHT = 2;
12567
12568
12569 Ext.SplitBar.TOP = 3;
12570
12571
12572 Ext.SplitBar.BOTTOM = 4;
12573
12574 Ext.Container = Ext.extend(Ext.BoxComponent, {
12575     
12576     
12577     
12578     
12579     bufferResize: 50,
12580
12581     
12582     
12583     
12584
12585
12586     
12587     autoDestroy : true,
12588
12589     
12590     forceLayout: false,
12591
12592     
12593     
12594     defaultType : 'panel',
12595
12596     
12597     resizeEvent: 'resize',
12598
12599     
12600     bubbleEvents: ['add', 'remove'],
12601
12602     
12603     initComponent : function(){
12604         Ext.Container.superclass.initComponent.call(this);
12605
12606         this.addEvents(
12607             
12608             'afterlayout',
12609             
12610             'beforeadd',
12611             
12612             'beforeremove',
12613             
12614             'add',
12615             
12616             'remove'
12617         );
12618
12619         
12620         var items = this.items;
12621         if(items){
12622             delete this.items;
12623             this.add(items);
12624         }
12625     },
12626
12627     
12628     initItems : function(){
12629         if(!this.items){
12630             this.items = new Ext.util.MixedCollection(false, this.getComponentId);
12631             this.getLayout(); 
12632         }
12633     },
12634
12635     
12636     setLayout : function(layout){
12637         if(this.layout && this.layout != layout){
12638             this.layout.setContainer(null);
12639         }
12640         this.layout = layout;
12641         this.initItems();
12642         layout.setContainer(this);
12643     },
12644
12645     afterRender: function(){
12646         
12647         
12648         Ext.Container.superclass.afterRender.call(this);
12649         if(!this.layout){
12650             this.layout = 'auto';
12651         }
12652         if(Ext.isObject(this.layout) && !this.layout.layout){
12653             this.layoutConfig = this.layout;
12654             this.layout = this.layoutConfig.type;
12655         }
12656         if(Ext.isString(this.layout)){
12657             this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig);
12658         }
12659         this.setLayout(this.layout);
12660
12661         
12662         if(this.activeItem !== undefined && this.layout.setActiveItem){
12663             var item = this.activeItem;
12664             delete this.activeItem;
12665             this.layout.setActiveItem(item);
12666         }
12667
12668         
12669         if(!this.ownerCt){
12670             this.doLayout(false, true);
12671         }
12672
12673         
12674         
12675         if(this.monitorResize === true){
12676             Ext.EventManager.onWindowResize(this.doLayout, this, [false]);
12677         }
12678     },
12679
12680     
12681     getLayoutTarget : function(){
12682         return this.el;
12683     },
12684
12685     
12686     getComponentId : function(comp){
12687         return comp.getItemId();
12688     },
12689
12690     
12691     add : function(comp){
12692         this.initItems();
12693         var args = arguments.length > 1;
12694         if(args || Ext.isArray(comp)){
12695             var result = [];
12696             Ext.each(args ? arguments : comp, function(c){
12697                 result.push(this.add(c));
12698             }, this);
12699             return result;
12700         }
12701         var c = this.lookupComponent(this.applyDefaults(comp));
12702         var index = this.items.length;
12703         if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
12704             this.items.add(c);
12705             
12706             c.onAdded(this, index);
12707             this.onAdd(c);
12708             this.fireEvent('add', this, c, index);
12709         }
12710         return c;
12711     },
12712
12713     onAdd : function(c){
12714         
12715     },
12716
12717     
12718     onAdded : function(container, pos) {
12719         
12720         this.ownerCt = container;
12721         this.initRef();
12722         
12723         this.cascade(function(c){
12724             c.initRef();
12725         });
12726         this.fireEvent('added', this, container, pos);
12727     },
12728
12729     
12730     insert : function(index, comp) {
12731         var args   = arguments,
12732             length = args.length,
12733             result = [],
12734             i, c;
12735         
12736         this.initItems();
12737         
12738         if (length > 2) {
12739             for (i = length - 1; i >= 1; --i) {
12740                 result.push(this.insert(index, args[i]));
12741             }
12742             return result;
12743         }
12744         
12745         c = this.lookupComponent(this.applyDefaults(comp));
12746         index = Math.min(index, this.items.length);
12747         
12748         if (this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false) {
12749             if (c.ownerCt == this) {
12750                 this.items.remove(c);
12751             }
12752             this.items.insert(index, c);
12753             c.onAdded(this, index);
12754             this.onAdd(c);
12755             this.fireEvent('add', this, c, index);
12756         }
12757         
12758         return c;
12759     },
12760
12761     
12762     applyDefaults : function(c){
12763         var d = this.defaults;
12764         if(d){
12765             if(Ext.isFunction(d)){
12766                 d = d.call(this, c);
12767             }
12768             if(Ext.isString(c)){
12769                 c = Ext.ComponentMgr.get(c);
12770                 Ext.apply(c, d);
12771             }else if(!c.events){
12772                 Ext.applyIf(c, d);
12773             }else{
12774                 Ext.apply(c, d);
12775             }
12776         }
12777         return c;
12778     },
12779
12780     
12781     onBeforeAdd : function(item){
12782         if(item.ownerCt){
12783             item.ownerCt.remove(item, false);
12784         }
12785         if(this.hideBorders === true){
12786             item.border = (item.border === true);
12787         }
12788     },
12789
12790     
12791     remove : function(comp, autoDestroy){
12792         this.initItems();
12793         var c = this.getComponent(comp);
12794         if(c && this.fireEvent('beforeremove', this, c) !== false){
12795             this.doRemove(c, autoDestroy);
12796             this.fireEvent('remove', this, c);
12797         }
12798         return c;
12799     },
12800
12801     onRemove: function(c){
12802         
12803     },
12804
12805     
12806     doRemove: function(c, autoDestroy){
12807         var l = this.layout,
12808             hasLayout = l && this.rendered;
12809
12810         if(hasLayout){
12811             l.onRemove(c);
12812         }
12813         this.items.remove(c);
12814         c.onRemoved();
12815         this.onRemove(c);
12816         if(autoDestroy === true || (autoDestroy !== false && this.autoDestroy)){
12817             c.destroy();
12818         }
12819         if(hasLayout){
12820             l.afterRemove(c);
12821         }
12822     },
12823
12824     
12825     removeAll: function(autoDestroy){
12826         this.initItems();
12827         var item, rem = [], items = [];
12828         this.items.each(function(i){
12829             rem.push(i);
12830         });
12831         for (var i = 0, len = rem.length; i < len; ++i){
12832             item = rem[i];
12833             this.remove(item, autoDestroy);
12834             if(item.ownerCt !== this){
12835                 items.push(item);
12836             }
12837         }
12838         return items;
12839     },
12840
12841     
12842     getComponent : function(comp){
12843         if(Ext.isObject(comp)){
12844             comp = comp.getItemId();
12845         }
12846         return this.items.get(comp);
12847     },
12848
12849     
12850     lookupComponent : function(comp){
12851         if(Ext.isString(comp)){
12852             return Ext.ComponentMgr.get(comp);
12853         }else if(!comp.events){
12854             return this.createComponent(comp);
12855         }
12856         return comp;
12857     },
12858
12859     
12860     createComponent : function(config, defaultType){
12861         if (config.render) {
12862             return config;
12863         }
12864         
12865         
12866         var c = Ext.create(Ext.apply({
12867             ownerCt: this
12868         }, config), defaultType || this.defaultType);
12869         delete c.initialConfig.ownerCt;
12870         delete c.ownerCt;
12871         return c;
12872     },
12873
12874     
12875     canLayout : function() {
12876         var el = this.getVisibilityEl();
12877         return el && el.dom && !el.isStyle("display", "none");
12878     },
12879
12880     
12881
12882     doLayout : function(shallow, force){
12883         var rendered = this.rendered,
12884             forceLayout = force || this.forceLayout;
12885
12886         if(this.collapsed || !this.canLayout()){
12887             this.deferLayout = this.deferLayout || !shallow;
12888             if(!forceLayout){
12889                 return;
12890             }
12891             shallow = shallow && !this.deferLayout;
12892         } else {
12893             delete this.deferLayout;
12894         }
12895         if(rendered && this.layout){
12896             this.layout.layout();
12897         }
12898         if(shallow !== true && this.items){
12899             var cs = this.items.items;
12900             for(var i = 0, len = cs.length; i < len; i++){
12901                 var c = cs[i];
12902                 if(c.doLayout){
12903                     c.doLayout(false, forceLayout);
12904                 }
12905             }
12906         }
12907         if(rendered){
12908             this.onLayout(shallow, forceLayout);
12909         }
12910         
12911         this.hasLayout = true;
12912         delete this.forceLayout;
12913     },
12914
12915     onLayout : Ext.emptyFn,
12916
12917     
12918     shouldBufferLayout: function(){
12919         
12920         var hl = this.hasLayout;
12921         if(this.ownerCt){
12922             
12923             return hl ? !this.hasLayoutPending() : false;
12924         }
12925         
12926         return hl;
12927     },
12928
12929     
12930     hasLayoutPending: function(){
12931         
12932         var pending = false;
12933         this.ownerCt.bubble(function(c){
12934             if(c.layoutPending){
12935                 pending = true;
12936                 return false;
12937             }
12938         });
12939         return pending;
12940     },
12941
12942     onShow : function(){
12943         
12944         Ext.Container.superclass.onShow.call(this);
12945         
12946         if(Ext.isDefined(this.deferLayout)){
12947             delete this.deferLayout;
12948             this.doLayout(true);
12949         }
12950     },
12951
12952     
12953     getLayout : function(){
12954         if(!this.layout){
12955             var layout = new Ext.layout.AutoLayout(this.layoutConfig);
12956             this.setLayout(layout);
12957         }
12958         return this.layout;
12959     },
12960
12961     
12962     beforeDestroy : function(){
12963         var c;
12964         if(this.items){
12965             while(c = this.items.first()){
12966                 this.doRemove(c, true);
12967             }
12968         }
12969         if(this.monitorResize){
12970             Ext.EventManager.removeResizeListener(this.doLayout, this);
12971         }
12972         Ext.destroy(this.layout);
12973         Ext.Container.superclass.beforeDestroy.call(this);
12974     },
12975
12976     
12977     cascade : function(fn, scope, args){
12978         if(fn.apply(scope || this, args || [this]) !== false){
12979             if(this.items){
12980                 var cs = this.items.items;
12981                 for(var i = 0, len = cs.length; i < len; i++){
12982                     if(cs[i].cascade){
12983                         cs[i].cascade(fn, scope, args);
12984                     }else{
12985                         fn.apply(scope || cs[i], args || [cs[i]]);
12986                     }
12987                 }
12988             }
12989         }
12990         return this;
12991     },
12992
12993     
12994     findById : function(id){
12995         var m = null, 
12996             ct = this;
12997         this.cascade(function(c){
12998             if(ct != c && c.id === id){
12999                 m = c;
13000                 return false;
13001             }
13002         });
13003         return m;
13004     },
13005
13006     
13007     findByType : function(xtype, shallow){
13008         return this.findBy(function(c){
13009             return c.isXType(xtype, shallow);
13010         });
13011     },
13012
13013     
13014     find : function(prop, value){
13015         return this.findBy(function(c){
13016             return c[prop] === value;
13017         });
13018     },
13019
13020     
13021     findBy : function(fn, scope){
13022         var m = [], ct = this;
13023         this.cascade(function(c){
13024             if(ct != c && fn.call(scope || c, c, ct) === true){
13025                 m.push(c);
13026             }
13027         });
13028         return m;
13029     },
13030
13031     
13032     get : function(key){
13033         return this.getComponent(key);
13034     }
13035 });
13036
13037 Ext.Container.LAYOUTS = {};
13038 Ext.reg('container', Ext.Container);
13039
13040 Ext.layout.ContainerLayout = Ext.extend(Object, {
13041     
13042     
13043
13044     
13045
13046     
13047     monitorResize:false,
13048     
13049     activeItem : null,
13050
13051     constructor : function(config){
13052         this.id = Ext.id(null, 'ext-layout-');
13053         Ext.apply(this, config);
13054     },
13055
13056     type: 'container',
13057
13058     
13059     IEMeasureHack : function(target, viewFlag) {
13060         var tChildren = target.dom.childNodes, tLen = tChildren.length, c, d = [], e, i, ret;
13061         for (i = 0 ; i < tLen ; i++) {
13062             c = tChildren[i];
13063             e = Ext.get(c);
13064             if (e) {
13065                 d[i] = e.getStyle('display');
13066                 e.setStyle({display: 'none'});
13067             }
13068         }
13069         ret = target ? target.getViewSize(viewFlag) : {};
13070         for (i = 0 ; i < tLen ; i++) {
13071             c = tChildren[i];
13072             e = Ext.get(c);
13073             if (e) {
13074                 e.setStyle({display: d[i]});
13075             }
13076         }
13077         return ret;
13078     },
13079
13080     
13081     getLayoutTargetSize : Ext.EmptyFn,
13082
13083     
13084     layout : function(){
13085         var ct = this.container, target = ct.getLayoutTarget();
13086         if(!(this.hasLayout || Ext.isEmpty(this.targetCls))){
13087             target.addClass(this.targetCls);
13088         }
13089         this.onLayout(ct, target);
13090         ct.fireEvent('afterlayout', ct, this);
13091     },
13092
13093     
13094     onLayout : function(ct, target){
13095         this.renderAll(ct, target);
13096     },
13097
13098     
13099     isValidParent : function(c, target){
13100         return target && c.getPositionEl().dom.parentNode == (target.dom || target);
13101     },
13102
13103     
13104     renderAll : function(ct, target){
13105         var items = ct.items.items, i, c, len = items.length;
13106         for(i = 0; i < len; i++) {
13107             c = items[i];
13108             if(c && (!c.rendered || !this.isValidParent(c, target))){
13109                 this.renderItem(c, i, target);
13110             }
13111         }
13112     },
13113
13114     
13115     renderItem : function(c, position, target){
13116         if (c) {
13117             if (!c.rendered) {
13118                 c.render(target, position);
13119                 this.configureItem(c);
13120             } else if (!this.isValidParent(c, target)) {
13121                 if (Ext.isNumber(position)) {
13122                     position = target.dom.childNodes[position];
13123                 }
13124                 
13125                 target.dom.insertBefore(c.getPositionEl().dom, position || null);
13126                 c.container = target;
13127                 this.configureItem(c);
13128             }
13129         }
13130     },
13131
13132     
13133     
13134     getRenderedItems: function(ct){
13135         var t = ct.getLayoutTarget(), cti = ct.items.items, len = cti.length, i, c, items = [];
13136         for (i = 0; i < len; i++) {
13137             if((c = cti[i]).rendered && this.isValidParent(c, t) && c.shouldLayout !== false){
13138                 items.push(c);
13139             }
13140         };
13141         return items;
13142     },
13143
13144     
13145     configureItem: function(c){
13146         if (this.extraCls) {
13147             var t = c.getPositionEl ? c.getPositionEl() : c;
13148             t.addClass(this.extraCls);
13149         }
13150         
13151         
13152         if (c.doLayout && this.forceLayout) {
13153             c.doLayout();
13154         }
13155         if (this.renderHidden && c != this.activeItem) {
13156             c.hide();
13157         }
13158     },
13159
13160     onRemove: function(c){
13161         if(this.activeItem == c){
13162             delete this.activeItem;
13163         }
13164         if(c.rendered && this.extraCls){
13165             var t = c.getPositionEl ? c.getPositionEl() : c;
13166             t.removeClass(this.extraCls);
13167         }
13168     },
13169
13170     afterRemove: function(c){
13171         if(c.removeRestore){
13172             c.removeMode = 'container';
13173             delete c.removeRestore;
13174         }
13175     },
13176
13177     
13178     onResize: function(){
13179         var ct = this.container,
13180             b;
13181         if(ct.collapsed){
13182             return;
13183         }
13184         if(b = ct.bufferResize && ct.shouldBufferLayout()){
13185             if(!this.resizeTask){
13186                 this.resizeTask = new Ext.util.DelayedTask(this.runLayout, this);
13187                 this.resizeBuffer = Ext.isNumber(b) ? b : 50;
13188             }
13189             ct.layoutPending = true;
13190             this.resizeTask.delay(this.resizeBuffer);
13191         }else{
13192             this.runLayout();
13193         }
13194     },
13195
13196     runLayout: function(){
13197         var ct = this.container;
13198         this.layout();
13199         ct.onLayout();
13200         delete ct.layoutPending;
13201     },
13202
13203     
13204     setContainer : function(ct){
13205         
13206         if(this.monitorResize && ct != this.container){
13207             var old = this.container;
13208             if(old){
13209                 old.un(old.resizeEvent, this.onResize, this);
13210             }
13211             if(ct){
13212                 ct.on(ct.resizeEvent, this.onResize, this);
13213             }
13214         }
13215         this.container = ct;
13216     },
13217
13218     
13219     parseMargins : function(v){
13220         if (Ext.isNumber(v)) {
13221             v = v.toString();
13222         }
13223         var ms  = v.split(' '),
13224             len = ms.length;
13225             
13226         if (len == 1) {
13227             ms[1] = ms[2] = ms[3] = ms[0];
13228         } else if(len == 2) {
13229             ms[2] = ms[0];
13230             ms[3] = ms[1];
13231         } else if(len == 3) {
13232             ms[3] = ms[1];
13233         }
13234         
13235         return {
13236             top   :parseInt(ms[0], 10) || 0,
13237             right :parseInt(ms[1], 10) || 0,
13238             bottom:parseInt(ms[2], 10) || 0,
13239             left  :parseInt(ms[3], 10) || 0
13240         };
13241     },
13242
13243     
13244     fieldTpl: (function() {
13245         var t = new Ext.Template(
13246             '<div class="x-form-item {itemCls}" tabIndex="-1">',
13247                 '<label for="{id}" style="{labelStyle}" class="x-form-item-label">{label}{labelSeparator}</label>',
13248                 '<div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">',
13249                 '</div><div class="{clearCls}"></div>',
13250             '</div>'
13251         );
13252         t.disableFormats = true;
13253         return t.compile();
13254     })(),
13255
13256     
13257     destroy : function(){
13258         
13259         if(this.resizeTask && this.resizeTask.cancel){
13260             this.resizeTask.cancel();
13261         }
13262         if(!Ext.isEmpty(this.targetCls)){
13263             var target = this.container.getLayoutTarget();
13264             if(target){
13265                 target.removeClass(this.targetCls);
13266             }
13267         }
13268     }
13269 });
13270 Ext.layout.AutoLayout = Ext.extend(Ext.layout.ContainerLayout, {
13271     type: 'auto',
13272
13273     monitorResize: true,
13274
13275     onLayout : function(ct, target){
13276         Ext.layout.AutoLayout.superclass.onLayout.call(this, ct, target);
13277         var cs = this.getRenderedItems(ct), len = cs.length, i, c;
13278         for(i = 0; i < len; i++){
13279             c = cs[i];
13280             if (c.doLayout){
13281                 
13282                 c.doLayout(true);
13283             }
13284         }
13285     }
13286 });
13287
13288 Ext.Container.LAYOUTS['auto'] = Ext.layout.AutoLayout;
13289
13290 Ext.layout.FitLayout = Ext.extend(Ext.layout.ContainerLayout, {
13291     
13292     monitorResize:true,
13293
13294     type: 'fit',
13295
13296     getLayoutTargetSize : function() {
13297         var target = this.container.getLayoutTarget();
13298         if (!target) {
13299             return {};
13300         }
13301         
13302         return target.getStyleSize();
13303     },
13304
13305     
13306     onLayout : function(ct, target){
13307         Ext.layout.FitLayout.superclass.onLayout.call(this, ct, target);
13308         if(!ct.collapsed){
13309             this.setItemSize(this.activeItem || ct.items.itemAt(0), this.getLayoutTargetSize());
13310         }
13311     },
13312
13313     
13314     setItemSize : function(item, size){
13315         if(item && size.height > 0){ 
13316             item.setSize(size);
13317         }
13318     }
13319 });
13320 Ext.Container.LAYOUTS['fit'] = Ext.layout.FitLayout;
13321 Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {
13322     
13323     deferredRender : false,
13324
13325     
13326     layoutOnCardChange : false,
13327
13328     
13329     
13330     renderHidden : true,
13331
13332     type: 'card',
13333
13334     
13335     setActiveItem : function(item){
13336         var ai = this.activeItem,
13337             ct = this.container;
13338         item = ct.getComponent(item);
13339
13340         
13341         if(item && ai != item){
13342
13343             
13344             if(ai){
13345                 ai.hide();
13346                 if (ai.hidden !== true) {
13347                     return false;
13348                 }
13349                 ai.fireEvent('deactivate', ai);
13350             }
13351
13352             var layout = item.doLayout && (this.layoutOnCardChange || !item.rendered);
13353
13354             
13355             this.activeItem = item;
13356
13357             
13358             
13359             delete item.deferLayout;
13360
13361             
13362             item.show();
13363
13364             this.layout();
13365
13366             if(layout){
13367                 item.doLayout();
13368             }
13369             item.fireEvent('activate', item);
13370         }
13371     },
13372
13373     
13374     renderAll : function(ct, target){
13375         if(this.deferredRender){
13376             this.renderItem(this.activeItem, undefined, target);
13377         }else{
13378             Ext.layout.CardLayout.superclass.renderAll.call(this, ct, target);
13379         }
13380     }
13381 });
13382 Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;
13383
13384 Ext.layout.AnchorLayout = Ext.extend(Ext.layout.ContainerLayout, {
13385     
13386
13387     
13388     monitorResize : true,
13389
13390     type : 'anchor',
13391
13392     
13393     defaultAnchor : '100%',
13394
13395     parseAnchorRE : /^(r|right|b|bottom)$/i,
13396
13397
13398     getLayoutTargetSize : function() {
13399         var target = this.container.getLayoutTarget(), ret = {};
13400         if (target) {
13401             ret = target.getViewSize();
13402
13403             
13404             
13405             
13406             if (Ext.isIE && Ext.isStrict && ret.width == 0){
13407                 ret =  target.getStyleSize();
13408             }
13409             ret.width -= target.getPadding('lr');
13410             ret.height -= target.getPadding('tb');
13411         }
13412         return ret;
13413     },
13414
13415     
13416     onLayout : function(container, target) {
13417         Ext.layout.AnchorLayout.superclass.onLayout.call(this, container, target);
13418
13419         var size = this.getLayoutTargetSize(),
13420             containerWidth = size.width,
13421             containerHeight = size.height,
13422             overflow = target.getStyle('overflow'),
13423             components = this.getRenderedItems(container),
13424             len = components.length,
13425             boxes = [],
13426             box,
13427             anchorWidth,
13428             anchorHeight,
13429             component,
13430             anchorSpec,
13431             calcWidth,
13432             calcHeight,
13433             anchorsArray,
13434             totalHeight = 0,
13435             i,
13436             el;
13437
13438         if(containerWidth < 20 && containerHeight < 20){
13439             return;
13440         }
13441
13442         
13443         if(container.anchorSize) {
13444             if(typeof container.anchorSize == 'number') {
13445                 anchorWidth = container.anchorSize;
13446             } else {
13447                 anchorWidth = container.anchorSize.width;
13448                 anchorHeight = container.anchorSize.height;
13449             }
13450         } else {
13451             anchorWidth = container.initialConfig.width;
13452             anchorHeight = container.initialConfig.height;
13453         }
13454
13455         for(i = 0; i < len; i++) {
13456             component = components[i];
13457             el = component.getPositionEl();
13458
13459             
13460             if (!component.anchor && component.items && !Ext.isNumber(component.width) && !(Ext.isIE6 && Ext.isStrict)){
13461                 component.anchor = this.defaultAnchor;
13462             }
13463
13464             if(component.anchor) {
13465                 anchorSpec = component.anchorSpec;
13466                 
13467                 if(!anchorSpec){
13468                     anchorsArray = component.anchor.split(' ');
13469                     component.anchorSpec = anchorSpec = {
13470                         right: this.parseAnchor(anchorsArray[0], component.initialConfig.width, anchorWidth),
13471                         bottom: this.parseAnchor(anchorsArray[1], component.initialConfig.height, anchorHeight)
13472                     };
13473                 }
13474                 calcWidth = anchorSpec.right ? this.adjustWidthAnchor(anchorSpec.right(containerWidth) - el.getMargins('lr'), component) : undefined;
13475                 calcHeight = anchorSpec.bottom ? this.adjustHeightAnchor(anchorSpec.bottom(containerHeight) - el.getMargins('tb'), component) : undefined;
13476
13477                 if(calcWidth || calcHeight) {
13478                     boxes.push({
13479                         component: component,
13480                         width: calcWidth || undefined,
13481                         height: calcHeight || undefined
13482                     });
13483                 }
13484             }
13485         }
13486         for (i = 0, len = boxes.length; i < len; i++) {
13487             box = boxes[i];
13488             box.component.setSize(box.width, box.height);
13489         }
13490
13491         if (overflow && overflow != 'hidden' && !this.adjustmentPass) {
13492             var newTargetSize = this.getLayoutTargetSize();
13493             if (newTargetSize.width != size.width || newTargetSize.height != size.height){
13494                 this.adjustmentPass = true;
13495                 this.onLayout(container, target);
13496             }
13497         }
13498
13499         delete this.adjustmentPass;
13500     },
13501
13502     
13503     parseAnchor : function(a, start, cstart) {
13504         if (a && a != 'none') {
13505             var last;
13506             
13507             if (this.parseAnchorRE.test(a)) {
13508                 var diff = cstart - start;
13509                 return function(v){
13510                     if(v !== last){
13511                         last = v;
13512                         return v - diff;
13513                     }
13514                 };
13515             
13516             } else if(a.indexOf('%') != -1) {
13517                 var ratio = parseFloat(a.replace('%', ''))*.01;
13518                 return function(v){
13519                     if(v !== last){
13520                         last = v;
13521                         return Math.floor(v*ratio);
13522                     }
13523                 };
13524             
13525             } else {
13526                 a = parseInt(a, 10);
13527                 if (!isNaN(a)) {
13528                     return function(v) {
13529                         if (v !== last) {
13530                             last = v;
13531                             return v + a;
13532                         }
13533                     };
13534                 }
13535             }
13536         }
13537         return false;
13538     },
13539
13540     
13541     adjustWidthAnchor : function(value, comp){
13542         return value;
13543     },
13544
13545     
13546     adjustHeightAnchor : function(value, comp){
13547         return value;
13548     }
13549
13550     
13551 });
13552 Ext.Container.LAYOUTS['anchor'] = Ext.layout.AnchorLayout;
13553
13554 Ext.layout.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {
13555     
13556     monitorResize:true,
13557
13558     type: 'column',
13559
13560     extraCls: 'x-column',
13561
13562     scrollOffset : 0,
13563
13564     
13565
13566     targetCls: 'x-column-layout-ct',
13567
13568     isValidParent : function(c, target){
13569         return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
13570     },
13571
13572     getLayoutTargetSize : function() {
13573         var target = this.container.getLayoutTarget(), ret;
13574         if (target) {
13575             ret = target.getViewSize();
13576
13577             
13578             
13579             
13580             if (Ext.isIE && Ext.isStrict && ret.width == 0){
13581                 ret =  target.getStyleSize();
13582             }
13583
13584             ret.width -= target.getPadding('lr');
13585             ret.height -= target.getPadding('tb');
13586         }
13587         return ret;
13588     },
13589
13590     renderAll : function(ct, target) {
13591         if(!this.innerCt){
13592             
13593             
13594             this.innerCt = target.createChild({cls:'x-column-inner'});
13595             this.innerCt.createChild({cls:'x-clear'});
13596         }
13597         Ext.layout.ColumnLayout.superclass.renderAll.call(this, ct, this.innerCt);
13598     },
13599
13600     
13601     onLayout : function(ct, target){
13602         var cs = ct.items.items,
13603             len = cs.length,
13604             c,
13605             i,
13606             m,
13607             margins = [];
13608
13609         this.renderAll(ct, target);
13610
13611         var size = this.getLayoutTargetSize();
13612
13613         if(size.width < 1 && size.height < 1){ 
13614             return;
13615         }
13616
13617         var w = size.width - this.scrollOffset,
13618             h = size.height,
13619             pw = w;
13620
13621         this.innerCt.setWidth(w);
13622
13623         
13624         
13625
13626         for(i = 0; i < len; i++){
13627             c = cs[i];
13628             m = c.getPositionEl().getMargins('lr');
13629             margins[i] = m;
13630             if(!c.columnWidth){
13631                 pw -= (c.getWidth() + m);
13632             }
13633         }
13634
13635         pw = pw < 0 ? 0 : pw;
13636
13637         for(i = 0; i < len; i++){
13638             c = cs[i];
13639             m = margins[i];
13640             if(c.columnWidth){
13641                 c.setSize(Math.floor(c.columnWidth * pw) - m);
13642             }
13643         }
13644
13645         
13646         
13647         if (Ext.isIE) {
13648             if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
13649                 var ts = this.getLayoutTargetSize();
13650                 if (ts.width != size.width){
13651                     this.adjustmentPass = true;
13652                     this.onLayout(ct, target);
13653                 }
13654             }
13655         }
13656         delete this.adjustmentPass;
13657     }
13658
13659     
13660 });
13661
13662 Ext.Container.LAYOUTS['column'] = Ext.layout.ColumnLayout;
13663
13664 Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {
13665     
13666     monitorResize:true,
13667     
13668     rendered : false,
13669
13670     type: 'border',
13671
13672     targetCls: 'x-border-layout-ct',
13673
13674     getLayoutTargetSize : function() {
13675         var target = this.container.getLayoutTarget();
13676         return target ? target.getViewSize() : {};
13677     },
13678
13679     
13680     onLayout : function(ct, target){
13681         var collapsed, i, c, pos, items = ct.items.items, len = items.length;
13682         if(!this.rendered){
13683             collapsed = [];
13684             for(i = 0; i < len; i++) {
13685                 c = items[i];
13686                 pos = c.region;
13687                 if(c.collapsed){
13688                     collapsed.push(c);
13689                 }
13690                 c.collapsed = false;
13691                 if(!c.rendered){
13692                     c.render(target, i);
13693                     c.getPositionEl().addClass('x-border-panel');
13694                 }
13695                 this[pos] = pos != 'center' && c.split ?
13696                     new Ext.layout.BorderLayout.SplitRegion(this, c.initialConfig, pos) :
13697                     new Ext.layout.BorderLayout.Region(this, c.initialConfig, pos);
13698                 this[pos].render(target, c);
13699             }
13700             this.rendered = true;
13701         }
13702
13703         var size = this.getLayoutTargetSize();
13704         if(size.width < 20 || size.height < 20){ 
13705             if(collapsed){
13706                 this.restoreCollapsed = collapsed;
13707             }
13708             return;
13709         }else if(this.restoreCollapsed){
13710             collapsed = this.restoreCollapsed;
13711             delete this.restoreCollapsed;
13712         }
13713
13714         var w = size.width, h = size.height,
13715             centerW = w, centerH = h, centerY = 0, centerX = 0,
13716             n = this.north, s = this.south, west = this.west, e = this.east, c = this.center,
13717             b, m, totalWidth, totalHeight;
13718         if(!c && Ext.layout.BorderLayout.WARN !== false){
13719             throw 'No center region defined in BorderLayout ' + ct.id;
13720         }
13721
13722         if(n && n.isVisible()){
13723             b = n.getSize();
13724             m = n.getMargins();
13725             b.width = w - (m.left+m.right);
13726             b.x = m.left;
13727             b.y = m.top;
13728             centerY = b.height + b.y + m.bottom;
13729             centerH -= centerY;
13730             n.applyLayout(b);
13731         }
13732         if(s && s.isVisible()){
13733             b = s.getSize();
13734             m = s.getMargins();
13735             b.width = w - (m.left+m.right);
13736             b.x = m.left;
13737             totalHeight = (b.height + m.top + m.bottom);
13738             b.y = h - totalHeight + m.top;
13739             centerH -= totalHeight;
13740             s.applyLayout(b);
13741         }
13742         if(west && west.isVisible()){
13743             b = west.getSize();
13744             m = west.getMargins();
13745             b.height = centerH - (m.top+m.bottom);
13746             b.x = m.left;
13747             b.y = centerY + m.top;
13748             totalWidth = (b.width + m.left + m.right);
13749             centerX += totalWidth;
13750             centerW -= totalWidth;
13751             west.applyLayout(b);
13752         }
13753         if(e && e.isVisible()){
13754             b = e.getSize();
13755             m = e.getMargins();
13756             b.height = centerH - (m.top+m.bottom);
13757             totalWidth = (b.width + m.left + m.right);
13758             b.x = w - totalWidth + m.left;
13759             b.y = centerY + m.top;
13760             centerW -= totalWidth;
13761             e.applyLayout(b);
13762         }
13763         if(c){
13764             m = c.getMargins();
13765             var centerBox = {
13766                 x: centerX + m.left,
13767                 y: centerY + m.top,
13768                 width: centerW - (m.left+m.right),
13769                 height: centerH - (m.top+m.bottom)
13770             };
13771             c.applyLayout(centerBox);
13772         }
13773         if(collapsed){
13774             for(i = 0, len = collapsed.length; i < len; i++){
13775                 collapsed[i].collapse(false);
13776             }
13777         }
13778         if(Ext.isIE && Ext.isStrict){ 
13779             target.repaint();
13780         }
13781         
13782         if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
13783             var ts = this.getLayoutTargetSize();
13784             if (ts.width != size.width || ts.height != size.height){
13785                 this.adjustmentPass = true;
13786                 this.onLayout(ct, target);
13787             }
13788         }
13789         delete this.adjustmentPass;
13790     },
13791
13792     destroy: function() {
13793         var r = ['north', 'south', 'east', 'west'], i, region;
13794         for (i = 0; i < r.length; i++) {
13795             region = this[r[i]];
13796             if(region){
13797                 if(region.destroy){
13798                     region.destroy();
13799                 }else if (region.split){
13800                     region.split.destroy(true);
13801                 }
13802             }
13803         }
13804         Ext.layout.BorderLayout.superclass.destroy.call(this);
13805     }
13806
13807     
13808 });
13809
13810
13811 Ext.layout.BorderLayout.Region = function(layout, config, pos){
13812     Ext.apply(this, config);
13813     this.layout = layout;
13814     this.position = pos;
13815     this.state = {};
13816     if(typeof this.margins == 'string'){
13817         this.margins = this.layout.parseMargins(this.margins);
13818     }
13819     this.margins = Ext.applyIf(this.margins || {}, this.defaultMargins);
13820     if(this.collapsible){
13821         if(typeof this.cmargins == 'string'){
13822             this.cmargins = this.layout.parseMargins(this.cmargins);
13823         }
13824         if(this.collapseMode == 'mini' && !this.cmargins){
13825             this.cmargins = {left:0,top:0,right:0,bottom:0};
13826         }else{
13827             this.cmargins = Ext.applyIf(this.cmargins || {},
13828                 pos == 'north' || pos == 'south' ? this.defaultNSCMargins : this.defaultEWCMargins);
13829         }
13830     }
13831 };
13832
13833 Ext.layout.BorderLayout.Region.prototype = {
13834     
13835     
13836     
13837     
13838     
13839     
13840     collapsible : false,
13841     
13842     split:false,
13843     
13844     floatable: true,
13845     
13846     minWidth:50,
13847     
13848     minHeight:50,
13849
13850     
13851     defaultMargins : {left:0,top:0,right:0,bottom:0},
13852     
13853     defaultNSCMargins : {left:5,top:5,right:5,bottom:5},
13854     
13855     defaultEWCMargins : {left:5,top:0,right:5,bottom:0},
13856     floatingZIndex: 100,
13857
13858     
13859     isCollapsed : false,
13860
13861     
13862     
13863     
13864
13865     
13866     render : function(ct, p){
13867         this.panel = p;
13868         p.el.enableDisplayMode();
13869         this.targetEl = ct;
13870         this.el = p.el;
13871
13872         var gs = p.getState, ps = this.position;
13873         p.getState = function(){
13874             return Ext.apply(gs.call(p) || {}, this.state);
13875         }.createDelegate(this);
13876
13877         if(ps != 'center'){
13878             p.allowQueuedExpand = false;
13879             p.on({
13880                 beforecollapse: this.beforeCollapse,
13881                 collapse: this.onCollapse,
13882                 beforeexpand: this.beforeExpand,
13883                 expand: this.onExpand,
13884                 hide: this.onHide,
13885                 show: this.onShow,
13886                 scope: this
13887             });
13888             if(this.collapsible || this.floatable){
13889                 p.collapseEl = 'el';
13890                 p.slideAnchor = this.getSlideAnchor();
13891             }
13892             if(p.tools && p.tools.toggle){
13893                 p.tools.toggle.addClass('x-tool-collapse-'+ps);
13894                 p.tools.toggle.addClassOnOver('x-tool-collapse-'+ps+'-over');
13895             }
13896         }
13897     },
13898
13899     
13900     getCollapsedEl : function(){
13901         if(!this.collapsedEl){
13902             if(!this.toolTemplate){
13903                 var tt = new Ext.Template(
13904                      '<div class="x-tool x-tool-{id}">&#160;</div>'
13905                 );
13906                 tt.disableFormats = true;
13907                 tt.compile();
13908                 Ext.layout.BorderLayout.Region.prototype.toolTemplate = tt;
13909             }
13910             this.collapsedEl = this.targetEl.createChild({
13911                 cls: "x-layout-collapsed x-layout-collapsed-"+this.position,
13912                 id: this.panel.id + '-xcollapsed'
13913             });
13914             this.collapsedEl.enableDisplayMode('block');
13915
13916             if(this.collapseMode == 'mini'){
13917                 this.collapsedEl.addClass('x-layout-cmini-'+this.position);
13918                 this.miniCollapsedEl = this.collapsedEl.createChild({
13919                     cls: "x-layout-mini x-layout-mini-"+this.position, html: "&#160;"
13920                 });
13921                 this.miniCollapsedEl.addClassOnOver('x-layout-mini-over');
13922                 this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
13923                 this.collapsedEl.on('click', this.onExpandClick, this, {stopEvent:true});
13924             }else {
13925                 if(this.collapsible !== false && !this.hideCollapseTool) {
13926                     var t = this.expandToolEl = this.toolTemplate.append(
13927                             this.collapsedEl.dom,
13928                             {id:'expand-'+this.position}, true);
13929                     t.addClassOnOver('x-tool-expand-'+this.position+'-over');
13930                     t.on('click', this.onExpandClick, this, {stopEvent:true});
13931                 }
13932                 if(this.floatable !== false || this.titleCollapse){
13933                    this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
13934                    this.collapsedEl.on("click", this[this.floatable ? 'collapseClick' : 'onExpandClick'], this);
13935                 }
13936             }
13937         }
13938         return this.collapsedEl;
13939     },
13940
13941     
13942     onExpandClick : function(e){
13943         if(this.isSlid){
13944             this.panel.expand(false);
13945         }else{
13946             this.panel.expand();
13947         }
13948     },
13949
13950     
13951     onCollapseClick : function(e){
13952         this.panel.collapse();
13953     },
13954
13955     
13956     beforeCollapse : function(p, animate){
13957         this.lastAnim = animate;
13958         if(this.splitEl){
13959             this.splitEl.hide();
13960         }
13961         this.getCollapsedEl().show();
13962         var el = this.panel.getEl();
13963         this.originalZIndex = el.getStyle('z-index');
13964         el.setStyle('z-index', 100);
13965         this.isCollapsed = true;
13966         this.layout.layout();
13967     },
13968
13969     
13970     onCollapse : function(animate){
13971         this.panel.el.setStyle('z-index', 1);
13972         if(this.lastAnim === false || this.panel.animCollapse === false){
13973             this.getCollapsedEl().dom.style.visibility = 'visible';
13974         }else{
13975             this.getCollapsedEl().slideIn(this.panel.slideAnchor, {duration:.2});
13976         }
13977         this.state.collapsed = true;
13978         this.panel.saveState();
13979     },
13980
13981     
13982     beforeExpand : function(animate){
13983         if(this.isSlid){
13984             this.afterSlideIn();
13985         }
13986         var c = this.getCollapsedEl();
13987         this.el.show();
13988         if(this.position == 'east' || this.position == 'west'){
13989             this.panel.setSize(undefined, c.getHeight());
13990         }else{
13991             this.panel.setSize(c.getWidth(), undefined);
13992         }
13993         c.hide();
13994         c.dom.style.visibility = 'hidden';
13995         this.panel.el.setStyle('z-index', this.floatingZIndex);
13996     },
13997
13998     
13999     onExpand : function(){
14000         this.isCollapsed = false;
14001         if(this.splitEl){
14002             this.splitEl.show();
14003         }
14004         this.layout.layout();
14005         this.panel.el.setStyle('z-index', this.originalZIndex);
14006         this.state.collapsed = false;
14007         this.panel.saveState();
14008     },
14009
14010     
14011     collapseClick : function(e){
14012         if(this.isSlid){
14013            e.stopPropagation();
14014            this.slideIn();
14015         }else{
14016            e.stopPropagation();
14017            this.slideOut();
14018         }
14019     },
14020
14021     
14022     onHide : function(){
14023         if(this.isCollapsed){
14024             this.getCollapsedEl().hide();
14025         }else if(this.splitEl){
14026             this.splitEl.hide();
14027         }
14028     },
14029
14030     
14031     onShow : function(){
14032         if(this.isCollapsed){
14033             this.getCollapsedEl().show();
14034         }else if(this.splitEl){
14035             this.splitEl.show();
14036         }
14037     },
14038
14039     
14040     isVisible : function(){
14041         return !this.panel.hidden;
14042     },
14043
14044     
14045     getMargins : function(){
14046         return this.isCollapsed && this.cmargins ? this.cmargins : this.margins;
14047     },
14048
14049     
14050     getSize : function(){
14051         return this.isCollapsed ? this.getCollapsedEl().getSize() : this.panel.getSize();
14052     },
14053
14054     
14055     setPanel : function(panel){
14056         this.panel = panel;
14057     },
14058
14059     
14060     getMinWidth: function(){
14061         return this.minWidth;
14062     },
14063
14064     
14065     getMinHeight: function(){
14066         return this.minHeight;
14067     },
14068
14069     
14070     applyLayoutCollapsed : function(box){
14071         var ce = this.getCollapsedEl();
14072         ce.setLeftTop(box.x, box.y);
14073         ce.setSize(box.width, box.height);
14074     },
14075
14076     
14077     applyLayout : function(box){
14078         if(this.isCollapsed){
14079             this.applyLayoutCollapsed(box);
14080         }else{
14081             this.panel.setPosition(box.x, box.y);
14082             this.panel.setSize(box.width, box.height);
14083         }
14084     },
14085
14086     
14087     beforeSlide: function(){
14088         this.panel.beforeEffect();
14089     },
14090
14091     
14092     afterSlide : function(){
14093         this.panel.afterEffect();
14094     },
14095
14096     
14097     initAutoHide : function(){
14098         if(this.autoHide !== false){
14099             if(!this.autoHideHd){
14100                 this.autoHideSlideTask = new Ext.util.DelayedTask(this.slideIn, this);
14101                 this.autoHideHd = {
14102                     "mouseout": function(e){
14103                         if(!e.within(this.el, true)){
14104                             this.autoHideSlideTask.delay(500);
14105                         }
14106                     },
14107                     "mouseover" : function(e){
14108                         this.autoHideSlideTask.cancel();
14109                     },
14110                     scope : this
14111                 };
14112             }
14113             this.el.on(this.autoHideHd);
14114             this.collapsedEl.on(this.autoHideHd);
14115         }
14116     },
14117
14118     
14119     clearAutoHide : function(){
14120         if(this.autoHide !== false){
14121             this.el.un("mouseout", this.autoHideHd.mouseout);
14122             this.el.un("mouseover", this.autoHideHd.mouseover);
14123             this.collapsedEl.un("mouseout", this.autoHideHd.mouseout);
14124             this.collapsedEl.un("mouseover", this.autoHideHd.mouseover);
14125         }
14126     },
14127
14128     
14129     clearMonitor : function(){
14130         Ext.getDoc().un("click", this.slideInIf, this);
14131     },
14132
14133     
14134     slideOut : function(){
14135         if(this.isSlid || this.el.hasActiveFx()){
14136             return;
14137         }
14138         this.isSlid = true;
14139         var ts = this.panel.tools, dh, pc;
14140         if(ts && ts.toggle){
14141             ts.toggle.hide();
14142         }
14143         this.el.show();
14144
14145         
14146         pc = this.panel.collapsed;
14147         this.panel.collapsed = false;
14148
14149         if(this.position == 'east' || this.position == 'west'){
14150             
14151             dh = this.panel.deferHeight;
14152             this.panel.deferHeight = false;
14153
14154             this.panel.setSize(undefined, this.collapsedEl.getHeight());
14155
14156             
14157             this.panel.deferHeight = dh;
14158         }else{
14159             this.panel.setSize(this.collapsedEl.getWidth(), undefined);
14160         }
14161
14162         
14163         this.panel.collapsed = pc;
14164
14165         this.restoreLT = [this.el.dom.style.left, this.el.dom.style.top];
14166         this.el.alignTo(this.collapsedEl, this.getCollapseAnchor());
14167         this.el.setStyle("z-index", this.floatingZIndex+2);
14168         this.panel.el.replaceClass('x-panel-collapsed', 'x-panel-floating');
14169         if(this.animFloat !== false){
14170             this.beforeSlide();
14171             this.el.slideIn(this.getSlideAnchor(), {
14172                 callback: function(){
14173                     this.afterSlide();
14174                     this.initAutoHide();
14175                     Ext.getDoc().on("click", this.slideInIf, this);
14176                 },
14177                 scope: this,
14178                 block: true
14179             });
14180         }else{
14181             this.initAutoHide();
14182              Ext.getDoc().on("click", this.slideInIf, this);
14183         }
14184     },
14185
14186     
14187     afterSlideIn : function(){
14188         this.clearAutoHide();
14189         this.isSlid = false;
14190         this.clearMonitor();
14191         this.el.setStyle("z-index", "");
14192         this.panel.el.replaceClass('x-panel-floating', 'x-panel-collapsed');
14193         this.el.dom.style.left = this.restoreLT[0];
14194         this.el.dom.style.top = this.restoreLT[1];
14195
14196         var ts = this.panel.tools;
14197         if(ts && ts.toggle){
14198             ts.toggle.show();
14199         }
14200     },
14201
14202     
14203     slideIn : function(cb){
14204         if(!this.isSlid || this.el.hasActiveFx()){
14205             Ext.callback(cb);
14206             return;
14207         }
14208         this.isSlid = false;
14209         if(this.animFloat !== false){
14210             this.beforeSlide();
14211             this.el.slideOut(this.getSlideAnchor(), {
14212                 callback: function(){
14213                     this.el.hide();
14214                     this.afterSlide();
14215                     this.afterSlideIn();
14216                     Ext.callback(cb);
14217                 },
14218                 scope: this,
14219                 block: true
14220             });
14221         }else{
14222             this.el.hide();
14223             this.afterSlideIn();
14224         }
14225     },
14226
14227     
14228     slideInIf : function(e){
14229         if(!e.within(this.el)){
14230             this.slideIn();
14231         }
14232     },
14233
14234     
14235     anchors : {
14236         "west" : "left",
14237         "east" : "right",
14238         "north" : "top",
14239         "south" : "bottom"
14240     },
14241
14242     
14243     sanchors : {
14244         "west" : "l",
14245         "east" : "r",
14246         "north" : "t",
14247         "south" : "b"
14248     },
14249
14250     
14251     canchors : {
14252         "west" : "tl-tr",
14253         "east" : "tr-tl",
14254         "north" : "tl-bl",
14255         "south" : "bl-tl"
14256     },
14257
14258     
14259     getAnchor : function(){
14260         return this.anchors[this.position];
14261     },
14262
14263     
14264     getCollapseAnchor : function(){
14265         return this.canchors[this.position];
14266     },
14267
14268     
14269     getSlideAnchor : function(){
14270         return this.sanchors[this.position];
14271     },
14272
14273     
14274     getAlignAdj : function(){
14275         var cm = this.cmargins;
14276         switch(this.position){
14277             case "west":
14278                 return [0, 0];
14279             break;
14280             case "east":
14281                 return [0, 0];
14282             break;
14283             case "north":
14284                 return [0, 0];
14285             break;
14286             case "south":
14287                 return [0, 0];
14288             break;
14289         }
14290     },
14291
14292     
14293     getExpandAdj : function(){
14294         var c = this.collapsedEl, cm = this.cmargins;
14295         switch(this.position){
14296             case "west":
14297                 return [-(cm.right+c.getWidth()+cm.left), 0];
14298             break;
14299             case "east":
14300                 return [cm.right+c.getWidth()+cm.left, 0];
14301             break;
14302             case "north":
14303                 return [0, -(cm.top+cm.bottom+c.getHeight())];
14304             break;
14305             case "south":
14306                 return [0, cm.top+cm.bottom+c.getHeight()];
14307             break;
14308         }
14309     },
14310
14311     destroy : function(){
14312         if (this.autoHideSlideTask && this.autoHideSlideTask.cancel){
14313             this.autoHideSlideTask.cancel();
14314         }
14315         Ext.destroyMembers(this, 'miniCollapsedEl', 'collapsedEl', 'expandToolEl');
14316     }
14317 };
14318
14319
14320 Ext.layout.BorderLayout.SplitRegion = function(layout, config, pos){
14321     Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this, layout, config, pos);
14322     
14323     this.applyLayout = this.applyFns[pos];
14324 };
14325
14326 Ext.extend(Ext.layout.BorderLayout.SplitRegion, Ext.layout.BorderLayout.Region, {
14327     
14328     
14329     splitTip : "Drag to resize.",
14330     
14331     collapsibleSplitTip : "Drag to resize. Double click to hide.",
14332     
14333     useSplitTips : false,
14334
14335     
14336     splitSettings : {
14337         north : {
14338             orientation: Ext.SplitBar.VERTICAL,
14339             placement: Ext.SplitBar.TOP,
14340             maxFn : 'getVMaxSize',
14341             minProp: 'minHeight',
14342             maxProp: 'maxHeight'
14343         },
14344         south : {
14345             orientation: Ext.SplitBar.VERTICAL,
14346             placement: Ext.SplitBar.BOTTOM,
14347             maxFn : 'getVMaxSize',
14348             minProp: 'minHeight',
14349             maxProp: 'maxHeight'
14350         },
14351         east : {
14352             orientation: Ext.SplitBar.HORIZONTAL,
14353             placement: Ext.SplitBar.RIGHT,
14354             maxFn : 'getHMaxSize',
14355             minProp: 'minWidth',
14356             maxProp: 'maxWidth'
14357         },
14358         west : {
14359             orientation: Ext.SplitBar.HORIZONTAL,
14360             placement: Ext.SplitBar.LEFT,
14361             maxFn : 'getHMaxSize',
14362             minProp: 'minWidth',
14363             maxProp: 'maxWidth'
14364         }
14365     },
14366
14367     
14368     applyFns : {
14369         west : function(box){
14370             if(this.isCollapsed){
14371                 return this.applyLayoutCollapsed(box);
14372             }
14373             var sd = this.splitEl.dom, s = sd.style;
14374             this.panel.setPosition(box.x, box.y);
14375             var sw = sd.offsetWidth;
14376             s.left = (box.x+box.width-sw)+'px';
14377             s.top = (box.y)+'px';
14378             s.height = Math.max(0, box.height)+'px';
14379             this.panel.setSize(box.width-sw, box.height);
14380         },
14381         east : function(box){
14382             if(this.isCollapsed){
14383                 return this.applyLayoutCollapsed(box);
14384             }
14385             var sd = this.splitEl.dom, s = sd.style;
14386             var sw = sd.offsetWidth;
14387             this.panel.setPosition(box.x+sw, box.y);
14388             s.left = (box.x)+'px';
14389             s.top = (box.y)+'px';
14390             s.height = Math.max(0, box.height)+'px';
14391             this.panel.setSize(box.width-sw, box.height);
14392         },
14393         north : function(box){
14394             if(this.isCollapsed){
14395                 return this.applyLayoutCollapsed(box);
14396             }
14397             var sd = this.splitEl.dom, s = sd.style;
14398             var sh = sd.offsetHeight;
14399             this.panel.setPosition(box.x, box.y);
14400             s.left = (box.x)+'px';
14401             s.top = (box.y+box.height-sh)+'px';
14402             s.width = Math.max(0, box.width)+'px';
14403             this.panel.setSize(box.width, box.height-sh);
14404         },
14405         south : function(box){
14406             if(this.isCollapsed){
14407                 return this.applyLayoutCollapsed(box);
14408             }
14409             var sd = this.splitEl.dom, s = sd.style;
14410             var sh = sd.offsetHeight;
14411             this.panel.setPosition(box.x, box.y+sh);
14412             s.left = (box.x)+'px';
14413             s.top = (box.y)+'px';
14414             s.width = Math.max(0, box.width)+'px';
14415             this.panel.setSize(box.width, box.height-sh);
14416         }
14417     },
14418
14419     
14420     render : function(ct, p){
14421         Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this, ct, p);
14422
14423         var ps = this.position;
14424
14425         this.splitEl = ct.createChild({
14426             cls: "x-layout-split x-layout-split-"+ps, html: "&#160;",
14427             id: this.panel.id + '-xsplit'
14428         });
14429
14430         if(this.collapseMode == 'mini'){
14431             this.miniSplitEl = this.splitEl.createChild({
14432                 cls: "x-layout-mini x-layout-mini-"+ps, html: "&#160;"
14433             });
14434             this.miniSplitEl.addClassOnOver('x-layout-mini-over');
14435             this.miniSplitEl.on('click', this.onCollapseClick, this, {stopEvent:true});
14436         }
14437
14438         var s = this.splitSettings[ps];
14439
14440         this.split = new Ext.SplitBar(this.splitEl.dom, p.el, s.orientation);
14441         this.split.tickSize = this.tickSize;
14442         this.split.placement = s.placement;
14443         this.split.getMaximumSize = this[s.maxFn].createDelegate(this);
14444         this.split.minSize = this.minSize || this[s.minProp];
14445         this.split.on("beforeapply", this.onSplitMove, this);
14446         this.split.useShim = this.useShim === true;
14447         this.maxSize = this.maxSize || this[s.maxProp];
14448
14449         if(p.hidden){
14450             this.splitEl.hide();
14451         }
14452
14453         if(this.useSplitTips){
14454             this.splitEl.dom.title = this.collapsible ? this.collapsibleSplitTip : this.splitTip;
14455         }
14456         if(this.collapsible){
14457             this.splitEl.on("dblclick", this.onCollapseClick,  this);
14458         }
14459     },
14460
14461     
14462     getSize : function(){
14463         if(this.isCollapsed){
14464             return this.collapsedEl.getSize();
14465         }
14466         var s = this.panel.getSize();
14467         if(this.position == 'north' || this.position == 'south'){
14468             s.height += this.splitEl.dom.offsetHeight;
14469         }else{
14470             s.width += this.splitEl.dom.offsetWidth;
14471         }
14472         return s;
14473     },
14474
14475     
14476     getHMaxSize : function(){
14477          var cmax = this.maxSize || 10000;
14478          var center = this.layout.center;
14479          return Math.min(cmax, (this.el.getWidth()+center.el.getWidth())-center.getMinWidth());
14480     },
14481
14482     
14483     getVMaxSize : function(){
14484         var cmax = this.maxSize || 10000;
14485         var center = this.layout.center;
14486         return Math.min(cmax, (this.el.getHeight()+center.el.getHeight())-center.getMinHeight());
14487     },
14488
14489     
14490     onSplitMove : function(split, newSize){
14491         var s = this.panel.getSize();
14492         this.lastSplitSize = newSize;
14493         if(this.position == 'north' || this.position == 'south'){
14494             this.panel.setSize(s.width, newSize);
14495             this.state.height = newSize;
14496         }else{
14497             this.panel.setSize(newSize, s.height);
14498             this.state.width = newSize;
14499         }
14500         this.layout.layout();
14501         this.panel.saveState();
14502         return false;
14503     },
14504
14505     
14506     getSplitBar : function(){
14507         return this.split;
14508     },
14509
14510     
14511     destroy : function() {
14512         Ext.destroy(this.miniSplitEl, this.split, this.splitEl);
14513         Ext.layout.BorderLayout.SplitRegion.superclass.destroy.call(this);
14514     }
14515 });
14516
14517 Ext.Container.LAYOUTS['border'] = Ext.layout.BorderLayout;
14518
14519 Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {
14520
14521     
14522     labelSeparator : ':',
14523
14524     
14525
14526     
14527     trackLabels: true,
14528
14529     type: 'form',
14530
14531     onRemove: function(c){
14532         Ext.layout.FormLayout.superclass.onRemove.call(this, c);
14533         if(this.trackLabels){
14534             c.un('show', this.onFieldShow, this);
14535             c.un('hide', this.onFieldHide, this);
14536         }
14537         
14538         var el = c.getPositionEl(),
14539             ct = c.getItemCt && c.getItemCt();
14540         if (c.rendered && ct) {
14541             if (el && el.dom) {
14542                 el.insertAfter(ct);
14543             }
14544             Ext.destroy(ct);
14545             Ext.destroyMembers(c, 'label', 'itemCt');
14546             if (c.customItemCt) {
14547                 Ext.destroyMembers(c, 'getItemCt', 'customItemCt');
14548             }
14549         }
14550     },
14551
14552     
14553     setContainer : function(ct){
14554         Ext.layout.FormLayout.superclass.setContainer.call(this, ct);
14555         if(ct.labelAlign){
14556             ct.addClass('x-form-label-'+ct.labelAlign);
14557         }
14558
14559         if(ct.hideLabels){
14560             Ext.apply(this, {
14561                 labelStyle: 'display:none',
14562                 elementStyle: 'padding-left:0;',
14563                 labelAdjust: 0
14564             });
14565         }else{
14566             this.labelSeparator = Ext.isDefined(ct.labelSeparator) ? ct.labelSeparator : this.labelSeparator;
14567             ct.labelWidth = ct.labelWidth || 100;
14568             if(Ext.isNumber(ct.labelWidth)){
14569                 var pad = Ext.isNumber(ct.labelPad) ? ct.labelPad : 5;
14570                 Ext.apply(this, {
14571                     labelAdjust: ct.labelWidth + pad,
14572                     labelStyle: 'width:' + ct.labelWidth + 'px;',
14573                     elementStyle: 'padding-left:' + (ct.labelWidth + pad) + 'px'
14574                 });
14575             }
14576             if(ct.labelAlign == 'top'){
14577                 Ext.apply(this, {
14578                     labelStyle: 'width:auto;',
14579                     labelAdjust: 0,
14580                     elementStyle: 'padding-left:0;'
14581                 });
14582             }
14583         }
14584     },
14585
14586     
14587     isHide: function(c){
14588         return c.hideLabel || this.container.hideLabels;
14589     },
14590
14591     onFieldShow: function(c){
14592         c.getItemCt().removeClass('x-hide-' + c.hideMode);
14593
14594         
14595         if (c.isComposite) {
14596             c.doLayout();
14597         }
14598     },
14599
14600     onFieldHide: function(c){
14601         c.getItemCt().addClass('x-hide-' + c.hideMode);
14602     },
14603
14604     
14605     getLabelStyle: function(s){
14606         var ls = '', items = [this.labelStyle, s];
14607         for (var i = 0, len = items.length; i < len; ++i){
14608             if (items[i]){
14609                 ls += items[i];
14610                 if (ls.substr(-1, 1) != ';'){
14611                     ls += ';';
14612                 }
14613             }
14614         }
14615         return ls;
14616     },
14617
14618     
14619
14620     
14621     renderItem : function(c, position, target){
14622         if(c && (c.isFormField || c.fieldLabel) && c.inputType != 'hidden'){
14623             var args = this.getTemplateArgs(c);
14624             if(Ext.isNumber(position)){
14625                 position = target.dom.childNodes[position] || null;
14626             }
14627             if(position){
14628                 c.itemCt = this.fieldTpl.insertBefore(position, args, true);
14629             }else{
14630                 c.itemCt = this.fieldTpl.append(target, args, true);
14631             }
14632             if(!c.getItemCt){
14633                 
14634                 
14635                 Ext.apply(c, {
14636                     getItemCt: function(){
14637                         return c.itemCt;
14638                     },
14639                     customItemCt: true
14640                 });
14641             }
14642             c.label = c.getItemCt().child('label.x-form-item-label');
14643             if(!c.rendered){
14644                 c.render('x-form-el-' + c.id);
14645             }else if(!this.isValidParent(c, target)){
14646                 Ext.fly('x-form-el-' + c.id).appendChild(c.getPositionEl());
14647             }
14648             if(this.trackLabels){
14649                 if(c.hidden){
14650                     this.onFieldHide(c);
14651                 }
14652                 c.on({
14653                     scope: this,
14654                     show: this.onFieldShow,
14655                     hide: this.onFieldHide
14656                 });
14657             }
14658             this.configureItem(c);
14659         }else {
14660             Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments);
14661         }
14662     },
14663
14664     
14665     getTemplateArgs: function(field) {
14666         var noLabelSep = !field.fieldLabel || field.hideLabel;
14667
14668         return {
14669             id            : field.id,
14670             label         : field.fieldLabel,
14671             itemCls       : (field.itemCls || this.container.itemCls || '') + (field.hideLabel ? ' x-hide-label' : ''),
14672             clearCls      : field.clearCls || 'x-form-clear-left',
14673             labelStyle    : this.getLabelStyle(field.labelStyle),
14674             elementStyle  : this.elementStyle || '',
14675             labelSeparator: noLabelSep ? '' : (Ext.isDefined(field.labelSeparator) ? field.labelSeparator : this.labelSeparator)
14676         };
14677     },
14678
14679     
14680     adjustWidthAnchor: function(value, c){
14681         if(c.label && !this.isHide(c) && (this.container.labelAlign != 'top')){
14682             var adjust = Ext.isIE6 || (Ext.isIE && !Ext.isStrict);
14683             return value - this.labelAdjust + (adjust ? -3 : 0);
14684         }
14685         return value;
14686     },
14687
14688     adjustHeightAnchor : function(value, c){
14689         if(c.label && !this.isHide(c) && (this.container.labelAlign == 'top')){
14690             return value - c.label.getHeight();
14691         }
14692         return value;
14693     },
14694
14695     
14696     isValidParent : function(c, target){
14697         return target && this.container.getEl().contains(c.getPositionEl());
14698     }
14699
14700     
14701 });
14702
14703 Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout;
14704
14705 Ext.layout.AccordionLayout = Ext.extend(Ext.layout.FitLayout, {
14706     
14707     fill : true,
14708     
14709     autoWidth : true,
14710     
14711     titleCollapse : true,
14712     
14713     hideCollapseTool : false,
14714     
14715     collapseFirst : false,
14716     
14717     animate : false,
14718     
14719     sequence : false,
14720     
14721     activeOnTop : false,
14722
14723     type: 'accordion',
14724
14725     renderItem : function(c){
14726         if(this.animate === false){
14727             c.animCollapse = false;
14728         }
14729         c.collapsible = true;
14730         if(this.autoWidth){
14731             c.autoWidth = true;
14732         }
14733         if(this.titleCollapse){
14734             c.titleCollapse = true;
14735         }
14736         if(this.hideCollapseTool){
14737             c.hideCollapseTool = true;
14738         }
14739         if(this.collapseFirst !== undefined){
14740             c.collapseFirst = this.collapseFirst;
14741         }
14742         if(!this.activeItem && !c.collapsed){
14743             this.setActiveItem(c, true);
14744         }else if(this.activeItem && this.activeItem != c){
14745             c.collapsed = true;
14746         }
14747         Ext.layout.AccordionLayout.superclass.renderItem.apply(this, arguments);
14748         c.header.addClass('x-accordion-hd');
14749         c.on('beforeexpand', this.beforeExpand, this);
14750     },
14751
14752     onRemove: function(c){
14753         Ext.layout.AccordionLayout.superclass.onRemove.call(this, c);
14754         if(c.rendered){
14755             c.header.removeClass('x-accordion-hd');
14756         }
14757         c.un('beforeexpand', this.beforeExpand, this);
14758     },
14759
14760     
14761     beforeExpand : function(p, anim){
14762         var ai = this.activeItem;
14763         if(ai){
14764             if(this.sequence){
14765                 delete this.activeItem;
14766                 if (!ai.collapsed){
14767                     ai.collapse({callback:function(){
14768                         p.expand(anim || true);
14769                     }, scope: this});
14770                     return false;
14771                 }
14772             }else{
14773                 ai.collapse(this.animate);
14774             }
14775         }
14776         this.setActive(p);
14777         if(this.activeOnTop){
14778             p.el.dom.parentNode.insertBefore(p.el.dom, p.el.dom.parentNode.firstChild);
14779         }
14780         
14781         this.layout();
14782     },
14783
14784     
14785     setItemSize : function(item, size){
14786         if(this.fill && item){
14787             var hh = 0, i, ct = this.getRenderedItems(this.container), len = ct.length, p;
14788             
14789             for (i = 0; i < len; i++) {
14790                 if((p = ct[i]) != item && !p.hidden){
14791                     hh += p.header.getHeight();
14792                 }
14793             };
14794             
14795             size.height -= hh;
14796             
14797             
14798             item.setSize(size);
14799         }
14800     },
14801
14802     
14803     setActiveItem : function(item){
14804         this.setActive(item, true);
14805     },
14806
14807     
14808     setActive : function(item, expand){
14809         var ai = this.activeItem;
14810         item = this.container.getComponent(item);
14811         if(ai != item){
14812             if(item.rendered && item.collapsed && expand){
14813                 item.expand();
14814             }else{
14815                 if(ai){
14816                    ai.fireEvent('deactivate', ai);
14817                 }
14818                 this.activeItem = item;
14819                 item.fireEvent('activate', item);
14820             }
14821         }
14822     }
14823 });
14824 Ext.Container.LAYOUTS.accordion = Ext.layout.AccordionLayout;
14825
14826
14827 Ext.layout.Accordion = Ext.layout.AccordionLayout;
14828 Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {
14829     
14830
14831     
14832     monitorResize:false,
14833
14834     type: 'table',
14835
14836     targetCls: 'x-table-layout-ct',
14837
14838     
14839     tableAttrs:null,
14840
14841     
14842     setContainer : function(ct){
14843         Ext.layout.TableLayout.superclass.setContainer.call(this, ct);
14844
14845         this.currentRow = 0;
14846         this.currentColumn = 0;
14847         this.cells = [];
14848     },
14849     
14850     
14851     onLayout : function(ct, target){
14852         var cs = ct.items.items, len = cs.length, c, i;
14853
14854         if(!this.table){
14855             target.addClass('x-table-layout-ct');
14856
14857             this.table = target.createChild(
14858                 Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);
14859         }
14860         this.renderAll(ct, target);
14861     },
14862
14863     
14864     getRow : function(index){
14865         var row = this.table.tBodies[0].childNodes[index];
14866         if(!row){
14867             row = document.createElement('tr');
14868             this.table.tBodies[0].appendChild(row);
14869         }
14870         return row;
14871     },
14872
14873     
14874     getNextCell : function(c){
14875         var cell = this.getNextNonSpan(this.currentColumn, this.currentRow);
14876         var curCol = this.currentColumn = cell[0], curRow = this.currentRow = cell[1];
14877         for(var rowIndex = curRow; rowIndex < curRow + (c.rowspan || 1); rowIndex++){
14878             if(!this.cells[rowIndex]){
14879                 this.cells[rowIndex] = [];
14880             }
14881             for(var colIndex = curCol; colIndex < curCol + (c.colspan || 1); colIndex++){
14882                 this.cells[rowIndex][colIndex] = true;
14883             }
14884         }
14885         var td = document.createElement('td');
14886         if(c.cellId){
14887             td.id = c.cellId;
14888         }
14889         var cls = 'x-table-layout-cell';
14890         if(c.cellCls){
14891             cls += ' ' + c.cellCls;
14892         }
14893         td.className = cls;
14894         if(c.colspan){
14895             td.colSpan = c.colspan;
14896         }
14897         if(c.rowspan){
14898             td.rowSpan = c.rowspan;
14899         }
14900         this.getRow(curRow).appendChild(td);
14901         return td;
14902     },
14903
14904     
14905     getNextNonSpan: function(colIndex, rowIndex){
14906         var cols = this.columns;
14907         while((cols && colIndex >= cols) || (this.cells[rowIndex] && this.cells[rowIndex][colIndex])) {
14908             if(cols && colIndex >= cols){
14909                 rowIndex++;
14910                 colIndex = 0;
14911             }else{
14912                 colIndex++;
14913             }
14914         }
14915         return [colIndex, rowIndex];
14916     },
14917
14918     
14919     renderItem : function(c, position, target){
14920         
14921         if(!this.table){
14922             this.table = target.createChild(
14923                 Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);
14924         }
14925         if(c && !c.rendered){
14926             c.render(this.getNextCell(c));
14927             this.configureItem(c);
14928         }else if(c && !this.isValidParent(c, target)){
14929             var container = this.getNextCell(c);
14930             container.insertBefore(c.getPositionEl().dom, null);
14931             c.container = Ext.get(container);
14932             this.configureItem(c);
14933         }
14934     },
14935
14936     
14937     isValidParent : function(c, target){
14938         return c.getPositionEl().up('table', 5).dom.parentNode === (target.dom || target);
14939     },
14940     
14941     destroy: function(){
14942         delete this.table;
14943         Ext.layout.TableLayout.superclass.destroy.call(this);
14944     }
14945
14946     
14947 });
14948
14949 Ext.Container.LAYOUTS['table'] = Ext.layout.TableLayout;
14950 Ext.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {
14951
14952     extraCls: 'x-abs-layout-item',
14953
14954     type: 'absolute',
14955
14956     onLayout : function(ct, target){
14957         target.position();
14958         this.paddingLeft = target.getPadding('l');
14959         this.paddingTop = target.getPadding('t');
14960         Ext.layout.AbsoluteLayout.superclass.onLayout.call(this, ct, target);
14961     },
14962
14963     
14964     adjustWidthAnchor : function(value, comp){
14965         return value ? value - comp.getPosition(true)[0] + this.paddingLeft : value;
14966     },
14967
14968     
14969     adjustHeightAnchor : function(value, comp){
14970         return  value ? value - comp.getPosition(true)[1] + this.paddingTop : value;
14971     }
14972     
14973 });
14974 Ext.Container.LAYOUTS['absolute'] = Ext.layout.AbsoluteLayout;
14975
14976 Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
14977     
14978     defaultMargins : {left:0,top:0,right:0,bottom:0},
14979     
14980     padding : '0',
14981     
14982     pack : 'start',
14983
14984     
14985     monitorResize : true,
14986     type: 'box',
14987     scrollOffset : 0,
14988     extraCls : 'x-box-item',
14989     targetCls : 'x-box-layout-ct',
14990     innerCls : 'x-box-inner',
14991
14992     constructor : function(config){
14993         Ext.layout.BoxLayout.superclass.constructor.call(this, config);
14994
14995         if (Ext.isString(this.defaultMargins)) {
14996             this.defaultMargins = this.parseMargins(this.defaultMargins);
14997         }
14998         
14999         var handler = this.overflowHandler;
15000         
15001         if (typeof handler == 'string') {
15002             handler = {
15003                 type: handler
15004             };
15005         }
15006         
15007         var handlerType = 'none';
15008         if (handler && handler.type != undefined) {
15009             handlerType = handler.type;
15010         }
15011         
15012         var constructor = Ext.layout.boxOverflow[handlerType];
15013         if (constructor[this.type]) {
15014             constructor = constructor[this.type];
15015         }
15016         
15017         this.overflowHandler = new constructor(this, handler);
15018     },
15019
15020     
15021     onLayout: function(container, target) {
15022         Ext.layout.BoxLayout.superclass.onLayout.call(this, container, target);
15023
15024         var tSize = this.getLayoutTargetSize(),
15025             items = this.getVisibleItems(container),
15026             calcs = this.calculateChildBoxes(items, tSize),
15027             boxes = calcs.boxes,
15028             meta  = calcs.meta;
15029         
15030         
15031         if (tSize.width > 0) {
15032             var handler = this.overflowHandler,
15033                 method  = meta.tooNarrow ? 'handleOverflow' : 'clearOverflow';
15034             
15035             var results = handler[method](calcs, tSize);
15036             
15037             if (results) {
15038                 if (results.targetSize) {
15039                     tSize = results.targetSize;
15040                 }
15041                 
15042                 if (results.recalculate) {
15043                     items = this.getVisibleItems(container);
15044                     calcs = this.calculateChildBoxes(items, tSize);
15045                     boxes = calcs.boxes;
15046                 }
15047             }
15048         }
15049         
15050         
15051         this.layoutTargetLastSize = tSize;
15052         
15053         
15054         this.childBoxCache = calcs;
15055         
15056         this.updateInnerCtSize(tSize, calcs);
15057         this.updateChildBoxes(boxes);
15058
15059         
15060         this.handleTargetOverflow(tSize, container, target);
15061     },
15062
15063     
15064     updateChildBoxes: function(boxes) {
15065         for (var i = 0, length = boxes.length; i < length; i++) {
15066             var box  = boxes[i],
15067                 comp = box.component;
15068             
15069             if (box.dirtySize) {
15070                 comp.setSize(box.width, box.height);
15071             }
15072             
15073             if (isNaN(box.left) || isNaN(box.top)) {
15074                 continue;
15075             }
15076             
15077             comp.setPosition(box.left, box.top);
15078         }
15079     },
15080
15081     
15082     updateInnerCtSize: function(tSize, calcs) {
15083         var align   = this.align,
15084             padding = this.padding,
15085             width   = tSize.width,
15086             height  = tSize.height;
15087         
15088         if (this.type == 'hbox') {
15089             var innerCtWidth  = width,
15090                 innerCtHeight = calcs.meta.maxHeight + padding.top + padding.bottom;
15091
15092             if (align == 'stretch') {
15093                 innerCtHeight = height;
15094             } else if (align == 'middle') {
15095                 innerCtHeight = Math.max(height, innerCtHeight);
15096             }
15097         } else {
15098             var innerCtHeight = height,
15099                 innerCtWidth  = calcs.meta.maxWidth + padding.left + padding.right;
15100
15101             if (align == 'stretch') {
15102                 innerCtWidth = width;
15103             } else if (align == 'center') {
15104                 innerCtWidth = Math.max(width, innerCtWidth);
15105             }
15106         }
15107
15108         this.innerCt.setSize(innerCtWidth || undefined, innerCtHeight || undefined);
15109     },
15110
15111     
15112     handleTargetOverflow: function(previousTargetSize, container, target) {
15113         var overflow = target.getStyle('overflow');
15114
15115         if (overflow && overflow != 'hidden' &&!this.adjustmentPass) {
15116             var newTargetSize = this.getLayoutTargetSize();
15117             if (newTargetSize.width != previousTargetSize.width || newTargetSize.height != previousTargetSize.height){
15118                 this.adjustmentPass = true;
15119                 this.onLayout(container, target);
15120             }
15121         }
15122
15123         delete this.adjustmentPass;
15124     },
15125
15126     
15127     isValidParent : function(c, target) {
15128         return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
15129     },
15130
15131     
15132     getVisibleItems: function(ct) {
15133         var ct  = ct || this.container,
15134             t   = ct.getLayoutTarget(),
15135             cti = ct.items.items,
15136             len = cti.length,
15137
15138             i, c, items = [];
15139
15140         for (i = 0; i < len; i++) {
15141             if((c = cti[i]).rendered && this.isValidParent(c, t) && c.hidden !== true  && c.collapsed !== true && c.shouldLayout !== false){
15142                 items.push(c);
15143             }
15144         }
15145
15146         return items;
15147     },
15148
15149     
15150     renderAll : function(ct, target) {
15151         if (!this.innerCt) {
15152             
15153             this.innerCt = target.createChild({cls:this.innerCls});
15154             this.padding = this.parseMargins(this.padding);
15155         }
15156         Ext.layout.BoxLayout.superclass.renderAll.call(this, ct, this.innerCt);
15157     },
15158
15159     getLayoutTargetSize : function() {
15160         var target = this.container.getLayoutTarget(), ret;
15161         
15162         if (target) {
15163             ret = target.getViewSize();
15164
15165             
15166             
15167             
15168             if (Ext.isIE && Ext.isStrict && ret.width == 0){
15169                 ret =  target.getStyleSize();
15170             }
15171
15172             ret.width  -= target.getPadding('lr');
15173             ret.height -= target.getPadding('tb');
15174         }
15175         
15176         return ret;
15177     },
15178
15179     
15180     renderItem : function(c) {
15181         if(Ext.isString(c.margins)){
15182             c.margins = this.parseMargins(c.margins);
15183         }else if(!c.margins){
15184             c.margins = this.defaultMargins;
15185         }
15186         Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments);
15187     },
15188     
15189     
15190     destroy: function() {
15191         Ext.destroy(this.overflowHandler);
15192         
15193         Ext.layout.BoxLayout.superclass.destroy.apply(this, arguments);
15194     }
15195 });
15196
15197
15198
15199 Ext.ns('Ext.layout.boxOverflow');
15200
15201
15202
15203 Ext.layout.boxOverflow.None = Ext.extend(Object, {
15204     constructor: function(layout, config) {
15205         this.layout = layout;
15206         
15207         Ext.apply(this, config || {});
15208     },
15209     
15210     handleOverflow: Ext.emptyFn,
15211     
15212     clearOverflow: Ext.emptyFn
15213 });
15214
15215
15216 Ext.layout.boxOverflow.none = Ext.layout.boxOverflow.None;
15217
15218 Ext.layout.boxOverflow.Menu = Ext.extend(Ext.layout.boxOverflow.None, {
15219     
15220     afterCls: 'x-strip-right',
15221     
15222     
15223     noItemsMenuText : '<div class="x-toolbar-no-items">(None)</div>',
15224     
15225     constructor: function(layout) {
15226         Ext.layout.boxOverflow.Menu.superclass.constructor.apply(this, arguments);
15227         
15228         
15229         this.menuItems = [];
15230     },
15231     
15232     
15233     createInnerElements: function() {
15234         if (!this.afterCt) {
15235             this.afterCt  = this.layout.innerCt.insertSibling({cls: this.afterCls},  'before');
15236         }
15237     },
15238     
15239     
15240     clearOverflow: function(calculations, targetSize) {
15241         var newWidth = targetSize.width + (this.afterCt ? this.afterCt.getWidth() : 0),
15242             items    = this.menuItems;
15243         
15244         this.hideTrigger();
15245         
15246         for (var index = 0, length = items.length; index < length; index++) {
15247             items.pop().component.show();
15248         }
15249         
15250         return {
15251             targetSize: {
15252                 height: targetSize.height,
15253                 width : newWidth
15254             }
15255         };
15256     },
15257     
15258     
15259     showTrigger: function() {
15260         this.createMenu();
15261         this.menuTrigger.show();
15262     },
15263     
15264     
15265     hideTrigger: function() {
15266         if (this.menuTrigger != undefined) {
15267             this.menuTrigger.hide();
15268         }
15269     },
15270     
15271     
15272     beforeMenuShow: function(menu) {
15273         var items = this.menuItems,
15274             len   = items.length,
15275             item,
15276             prev;
15277
15278         var needsSep = function(group, item){
15279             return group.isXType('buttongroup') && !(item instanceof Ext.Toolbar.Separator);
15280         };
15281         
15282         this.clearMenu();
15283         menu.removeAll();
15284         
15285         for (var i = 0; i < len; i++) {
15286             item = items[i].component;
15287             
15288             if (prev && (needsSep(item, prev) || needsSep(prev, item))) {
15289                 menu.add('-');
15290             }
15291             
15292             this.addComponentToMenu(menu, item);
15293             prev = item;
15294         }
15295
15296         
15297         if (menu.items.length < 1) {
15298             menu.add(this.noItemsMenuText);
15299         }
15300     },
15301     
15302     
15303     createMenuConfig : function(component, hideOnClick){
15304         var config = Ext.apply({}, component.initialConfig),
15305             group  = component.toggleGroup;
15306
15307         Ext.copyTo(config, component, [
15308             'iconCls', 'icon', 'itemId', 'disabled', 'handler', 'scope', 'menu'
15309         ]);
15310
15311         Ext.apply(config, {
15312             text       : component.overflowText || component.text,
15313             hideOnClick: hideOnClick
15314         });
15315
15316         if (group || component.enableToggle) {
15317             Ext.apply(config, {
15318                 group  : group,
15319                 checked: component.pressed,
15320                 listeners: {
15321                     checkchange: function(item, checked){
15322                         component.toggle(checked);
15323                     }
15324                 }
15325             });
15326         }
15327
15328         delete config.ownerCt;
15329         delete config.xtype;
15330         delete config.id;
15331
15332         return config;
15333     },
15334
15335     
15336     addComponentToMenu : function(menu, component) {
15337         if (component instanceof Ext.Toolbar.Separator) {
15338             menu.add('-');
15339
15340         } else if (Ext.isFunction(component.isXType)) {
15341             if (component.isXType('splitbutton')) {
15342                 menu.add(this.createMenuConfig(component, true));
15343
15344             } else if (component.isXType('button')) {
15345                 menu.add(this.createMenuConfig(component, !component.menu));
15346
15347             } else if (component.isXType('buttongroup')) {
15348                 component.items.each(function(item){
15349                      this.addComponentToMenu(menu, item);
15350                 }, this);
15351             }
15352         }
15353     },
15354     
15355     
15356     clearMenu : function(){
15357         var menu = this.moreMenu;
15358         if (menu && menu.items) {
15359             menu.items.each(function(item){
15360                 delete item.menu;
15361             });
15362         }
15363     },
15364     
15365     
15366     createMenu: function() {
15367         if (!this.menuTrigger) {
15368             this.createInnerElements();
15369             
15370             
15371             this.menu = new Ext.menu.Menu({
15372                 ownerCt : this.layout.container,
15373                 listeners: {
15374                     scope: this,
15375                     beforeshow: this.beforeMenuShow
15376                 }
15377             });
15378
15379             
15380             this.menuTrigger = new Ext.Button({
15381                 iconCls : 'x-toolbar-more-icon',
15382                 cls     : 'x-toolbar-more',
15383                 menu    : this.menu,
15384                 renderTo: this.afterCt
15385             });
15386         }
15387     },
15388     
15389     
15390     destroy: function() {
15391         Ext.destroy(this.menu, this.menuTrigger);
15392     }
15393 });
15394
15395 Ext.layout.boxOverflow.menu = Ext.layout.boxOverflow.Menu;
15396
15397
15398
15399 Ext.layout.boxOverflow.HorizontalMenu = Ext.extend(Ext.layout.boxOverflow.Menu, {
15400     
15401     constructor: function() {
15402         Ext.layout.boxOverflow.HorizontalMenu.superclass.constructor.apply(this, arguments);
15403         
15404         var me = this,
15405             layout = me.layout,
15406             origFunction = layout.calculateChildBoxes;
15407         
15408         layout.calculateChildBoxes = function(visibleItems, targetSize) {
15409             var calcs = origFunction.apply(layout, arguments),
15410                 meta  = calcs.meta,
15411                 items = me.menuItems;
15412             
15413             
15414             
15415             var hiddenWidth = 0;
15416             for (var index = 0, length = items.length; index < length; index++) {
15417                 hiddenWidth += items[index].width;
15418             }
15419             
15420             meta.minimumWidth += hiddenWidth;
15421             meta.tooNarrow = meta.minimumWidth > targetSize.width;
15422             
15423             return calcs;
15424         };        
15425     },
15426     
15427     handleOverflow: function(calculations, targetSize) {
15428         this.showTrigger();
15429         
15430         var newWidth    = targetSize.width - this.afterCt.getWidth(),
15431             boxes       = calculations.boxes,
15432             usedWidth   = 0,
15433             recalculate = false;
15434         
15435         
15436         for (var index = 0, length = boxes.length; index < length; index++) {
15437             usedWidth += boxes[index].width;
15438         }
15439         
15440         var spareWidth = newWidth - usedWidth,
15441             showCount  = 0;
15442         
15443         
15444         for (var index = 0, length = this.menuItems.length; index < length; index++) {
15445             var hidden = this.menuItems[index],
15446                 comp   = hidden.component,
15447                 width  = hidden.width;
15448             
15449             if (width < spareWidth) {
15450                 comp.show();
15451                 
15452                 spareWidth -= width;
15453                 showCount ++;
15454                 recalculate = true;
15455             } else {
15456                 break;
15457             }
15458         }
15459                 
15460         if (recalculate) {
15461             this.menuItems = this.menuItems.slice(showCount);
15462         } else {
15463             for (var i = boxes.length - 1; i >= 0; i--) {
15464                 var item  = boxes[i].component,
15465                     right = boxes[i].left + boxes[i].width;
15466
15467                 if (right >= newWidth) {
15468                     this.menuItems.unshift({
15469                         component: item,
15470                         width    : boxes[i].width
15471                     });
15472
15473                     item.hide();
15474                 } else {
15475                     break;
15476                 }
15477             }
15478         }
15479         
15480         if (this.menuItems.length == 0) {
15481             this.hideTrigger();
15482         }
15483         
15484         return {
15485             targetSize: {
15486                 height: targetSize.height,
15487                 width : newWidth
15488             },
15489             recalculate: recalculate
15490         };
15491     }
15492 });
15493
15494 Ext.layout.boxOverflow.menu.hbox = Ext.layout.boxOverflow.HorizontalMenu;
15495 Ext.layout.boxOverflow.Scroller = Ext.extend(Ext.layout.boxOverflow.None, {
15496     
15497     animateScroll: true,
15498     
15499     
15500     scrollIncrement: 100,
15501     
15502     
15503     wheelIncrement: 3,
15504     
15505     
15506     scrollRepeatInterval: 400,
15507     
15508     
15509     scrollDuration: 0.4,
15510     
15511     
15512     beforeCls: 'x-strip-left',
15513     
15514     
15515     afterCls: 'x-strip-right',
15516     
15517     
15518     scrollerCls: 'x-strip-scroller',
15519     
15520     
15521     beforeScrollerCls: 'x-strip-scroller-left',
15522     
15523     
15524     afterScrollerCls: 'x-strip-scroller-right',
15525     
15526     
15527     createWheelListener: function() {
15528         this.layout.innerCt.on({
15529             scope     : this,
15530             mousewheel: function(e) {
15531                 e.stopEvent();
15532
15533                 this.scrollBy(e.getWheelDelta() * this.wheelIncrement * -1, false);
15534             }
15535         });
15536     },
15537     
15538     
15539     handleOverflow: function(calculations, targetSize) {
15540         this.createInnerElements();
15541         this.showScrollers();
15542     },
15543     
15544     
15545     clearOverflow: function() {
15546         this.hideScrollers();
15547     },
15548     
15549     
15550     showScrollers: function() {
15551         this.createScrollers();
15552         
15553         this.beforeScroller.show();
15554         this.afterScroller.show();
15555         
15556         this.updateScrollButtons();
15557     },
15558     
15559     
15560     hideScrollers: function() {
15561         if (this.beforeScroller != undefined) {
15562             this.beforeScroller.hide();
15563             this.afterScroller.hide();          
15564         }
15565     },
15566     
15567     
15568     createScrollers: function() {
15569         if (!this.beforeScroller && !this.afterScroller) {
15570             var before = this.beforeCt.createChild({
15571                 cls: String.format("{0} {1} ", this.scrollerCls, this.beforeScrollerCls)
15572             });
15573             
15574             var after = this.afterCt.createChild({
15575                 cls: String.format("{0} {1}", this.scrollerCls, this.afterScrollerCls)
15576             });
15577             
15578             before.addClassOnOver(this.beforeScrollerCls + '-hover');
15579             after.addClassOnOver(this.afterScrollerCls + '-hover');
15580             
15581             before.setVisibilityMode(Ext.Element.DISPLAY);
15582             after.setVisibilityMode(Ext.Element.DISPLAY);
15583             
15584             this.beforeRepeater = new Ext.util.ClickRepeater(before, {
15585                 interval: this.scrollRepeatInterval,
15586                 handler : this.scrollLeft,
15587                 scope   : this
15588             });
15589             
15590             this.afterRepeater = new Ext.util.ClickRepeater(after, {
15591                 interval: this.scrollRepeatInterval,
15592                 handler : this.scrollRight,
15593                 scope   : this
15594             });
15595             
15596             
15597             this.beforeScroller = before;
15598             
15599             
15600             this.afterScroller = after;
15601         }
15602     },
15603     
15604     
15605     destroy: function() {
15606         Ext.destroy(this.beforeScroller, this.afterScroller, this.beforeRepeater, this.afterRepeater, this.beforeCt, this.afterCt);
15607     },
15608     
15609     
15610     scrollBy: function(delta, animate) {
15611         this.scrollTo(this.getScrollPosition() + delta, animate);
15612     },
15613     
15614     
15615     getItem: function(item) {
15616         if (Ext.isString(item)) {
15617             item = Ext.getCmp(item);
15618         } else if (Ext.isNumber(item)) {
15619             item = this.items[item];
15620         }
15621         
15622         return item;
15623     },
15624     
15625     
15626     getScrollAnim: function() {
15627         return {
15628             duration: this.scrollDuration, 
15629             callback: this.updateScrollButtons, 
15630             scope   : this
15631         };
15632     },
15633     
15634     
15635     updateScrollButtons: function() {
15636         if (this.beforeScroller == undefined || this.afterScroller == undefined) {
15637             return;
15638         }
15639         
15640         var beforeMeth = this.atExtremeBefore()  ? 'addClass' : 'removeClass',
15641             afterMeth  = this.atExtremeAfter() ? 'addClass' : 'removeClass',
15642             beforeCls  = this.beforeScrollerCls + '-disabled',
15643             afterCls   = this.afterScrollerCls  + '-disabled';
15644         
15645         this.beforeScroller[beforeMeth](beforeCls);
15646         this.afterScroller[afterMeth](afterCls);
15647         this.scrolling = false;
15648     },
15649     
15650     
15651     atExtremeBefore: function() {
15652         return this.getScrollPosition() === 0;
15653     },
15654     
15655     
15656     scrollLeft: function(animate) {
15657         this.scrollBy(-this.scrollIncrement, animate);
15658     },
15659     
15660     
15661     scrollRight: function(animate) {
15662         this.scrollBy(this.scrollIncrement, animate);
15663     },
15664     
15665     
15666     scrollToItem: function(item, animate) {
15667         item = this.getItem(item);
15668         
15669         if (item != undefined) {
15670             var visibility = this.getItemVisibility(item);
15671             
15672             if (!visibility.fullyVisible) {
15673                 var box  = item.getBox(true, true),
15674                     newX = box.x;
15675                     
15676                 if (visibility.hiddenRight) {
15677                     newX -= (this.layout.innerCt.getWidth() - box.width);
15678                 }
15679                 
15680                 this.scrollTo(newX, animate);
15681             }
15682         }
15683     },
15684     
15685     
15686     getItemVisibility: function(item) {
15687         var box         = this.getItem(item).getBox(true, true),
15688             itemLeft    = box.x,
15689             itemRight   = box.x + box.width,
15690             scrollLeft  = this.getScrollPosition(),
15691             scrollRight = this.layout.innerCt.getWidth() + scrollLeft;
15692         
15693         return {
15694             hiddenLeft  : itemLeft < scrollLeft,
15695             hiddenRight : itemRight > scrollRight,
15696             fullyVisible: itemLeft > scrollLeft && itemRight < scrollRight
15697         };
15698     }
15699 });
15700
15701 Ext.layout.boxOverflow.scroller = Ext.layout.boxOverflow.Scroller;
15702
15703
15704 \r
15705 Ext.layout.boxOverflow.VerticalScroller = Ext.extend(Ext.layout.boxOverflow.Scroller, {
15706     scrollIncrement: 75,
15707     wheelIncrement : 2,
15708     
15709     handleOverflow: function(calculations, targetSize) {
15710         Ext.layout.boxOverflow.VerticalScroller.superclass.handleOverflow.apply(this, arguments);
15711         
15712         return {
15713             targetSize: {
15714                 height: targetSize.height - (this.beforeCt.getHeight() + this.afterCt.getHeight()),
15715                 width : targetSize.width
15716             }
15717         };
15718     },
15719     
15720     
15721     createInnerElements: function() {
15722         var target = this.layout.innerCt;
15723         
15724         
15725         
15726         if (!this.beforeCt) {
15727             this.beforeCt = target.insertSibling({cls: this.beforeCls}, 'before');
15728             this.afterCt  = target.insertSibling({cls: this.afterCls},  'after');
15729
15730             this.createWheelListener();
15731         }
15732     },
15733     
15734     
15735     scrollTo: function(position, animate) {
15736         var oldPosition = this.getScrollPosition(),
15737             newPosition = position.constrain(0, this.getMaxScrollBottom());
15738         
15739         if (newPosition != oldPosition && !this.scrolling) {
15740             if (animate == undefined) {
15741                 animate = this.animateScroll;
15742             }
15743             
15744             this.layout.innerCt.scrollTo('top', newPosition, animate ? this.getScrollAnim() : false);
15745             
15746             if (animate) {
15747                 this.scrolling = true;
15748             } else {
15749                 this.scrolling = false;
15750                 this.updateScrollButtons();
15751             }
15752         }
15753     },
15754     
15755     
15756     getScrollPosition: function(){
15757         return parseInt(this.layout.innerCt.dom.scrollTop, 10) || 0;
15758     },
15759     
15760     
15761     getMaxScrollBottom: function() {
15762         return this.layout.innerCt.dom.scrollHeight - this.layout.innerCt.getHeight();
15763     },
15764     
15765     
15766     atExtremeAfter: function() {
15767         return this.getScrollPosition() >= this.getMaxScrollBottom();
15768     }
15769 });
15770
15771 Ext.layout.boxOverflow.scroller.vbox = Ext.layout.boxOverflow.VerticalScroller;
15772
15773
15774
15775 Ext.layout.boxOverflow.HorizontalScroller = Ext.extend(Ext.layout.boxOverflow.Scroller, {
15776     handleOverflow: function(calculations, targetSize) {
15777         Ext.layout.boxOverflow.HorizontalScroller.superclass.handleOverflow.apply(this, arguments);
15778         
15779         return {
15780             targetSize: {
15781                 height: targetSize.height,
15782                 width : targetSize.width - (this.beforeCt.getWidth() + this.afterCt.getWidth())
15783             }
15784         };
15785     },
15786     
15787     
15788     createInnerElements: function() {
15789         var target = this.layout.innerCt;
15790         
15791         
15792         
15793         if (!this.beforeCt) {
15794             this.afterCt  = target.insertSibling({cls: this.afterCls},  'before');
15795             this.beforeCt = target.insertSibling({cls: this.beforeCls}, 'before');
15796             
15797             this.createWheelListener();
15798         }
15799     },
15800     
15801     
15802     scrollTo: function(position, animate) {
15803         var oldPosition = this.getScrollPosition(),
15804             newPosition = position.constrain(0, this.getMaxScrollRight());
15805         
15806         if (newPosition != oldPosition && !this.scrolling) {
15807             if (animate == undefined) {
15808                 animate = this.animateScroll;
15809             }
15810             
15811             this.layout.innerCt.scrollTo('left', newPosition, animate ? this.getScrollAnim() : false);
15812             
15813             if (animate) {
15814                 this.scrolling = true;
15815             } else {
15816                 this.scrolling = false;
15817                 this.updateScrollButtons();
15818             }
15819         }
15820     },
15821     
15822     
15823     getScrollPosition: function(){
15824         return parseInt(this.layout.innerCt.dom.scrollLeft, 10) || 0;
15825     },
15826     
15827     
15828     getMaxScrollRight: function() {
15829         return this.layout.innerCt.dom.scrollWidth - this.layout.innerCt.getWidth();
15830     },
15831     
15832     
15833     atExtremeAfter: function() {
15834         return this.getScrollPosition() >= this.getMaxScrollRight();
15835     }
15836 });
15837
15838 Ext.layout.boxOverflow.scroller.hbox = Ext.layout.boxOverflow.HorizontalScroller;
15839 Ext.layout.HBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
15840     
15841     align: 'top', 
15842
15843     type : 'hbox',
15844
15845     
15846     
15847
15848     
15849     calculateChildBoxes: function(visibleItems, targetSize) {
15850         var visibleCount = visibleItems.length,
15851
15852             padding      = this.padding,
15853             topOffset    = padding.top,
15854             leftOffset   = padding.left,
15855             paddingVert  = topOffset  + padding.bottom,
15856             paddingHoriz = leftOffset + padding.right,
15857
15858             width        = targetSize.width - this.scrollOffset,
15859             height       = targetSize.height,
15860             availHeight  = Math.max(0, height - paddingVert),
15861
15862             isStart      = this.pack == 'start',
15863             isCenter     = this.pack == 'center',
15864             isEnd        = this.pack == 'end',
15865
15866             nonFlexWidth = 0,
15867             maxHeight    = 0,
15868             totalFlex    = 0,
15869             desiredWidth = 0,
15870             minimumWidth = 0,
15871
15872             
15873             boxes        = [],
15874
15875             
15876             child, childWidth, childHeight, childSize, childMargins, canLayout, i, calcs, flexedWidth, 
15877             horizMargins, vertMargins, stretchHeight;
15878
15879         
15880         for (i = 0; i < visibleCount; i++) {
15881             child       = visibleItems[i];
15882             childHeight = child.height;
15883             childWidth  = child.width;
15884             canLayout   = !child.hasLayout && typeof child.doLayout == 'function';
15885
15886             
15887             if (typeof childWidth != 'number') {
15888
15889                 
15890                 if (child.flex && !childWidth) {
15891                     totalFlex += child.flex;
15892
15893                 
15894                 } else {
15895                     
15896                     
15897                     if (!childWidth && canLayout) {
15898                         child.doLayout();
15899                     }
15900
15901                     childSize   = child.getSize();
15902                     childWidth  = childSize.width;
15903                     childHeight = childSize.height;
15904                 }
15905             }
15906
15907             childMargins = child.margins;
15908             horizMargins = childMargins.left + childMargins.right;
15909
15910             nonFlexWidth += horizMargins + (childWidth || 0);
15911             desiredWidth += horizMargins + (child.flex ? child.minWidth || 0 : childWidth);
15912             minimumWidth += horizMargins + (child.minWidth || childWidth || 0);
15913
15914             
15915             if (typeof childHeight != 'number') {
15916                 if (canLayout) {
15917                     child.doLayout();
15918                 }
15919                 childHeight = child.getHeight();
15920             }
15921
15922             maxHeight = Math.max(maxHeight, childHeight + childMargins.top + childMargins.bottom);
15923
15924             
15925             boxes.push({
15926                 component: child,
15927                 height   : childHeight || undefined,
15928                 width    : childWidth  || undefined
15929             });
15930         }
15931                 
15932         var shortfall = desiredWidth - width,
15933             tooNarrow = minimumWidth > width;
15934             
15935         
15936         var availableWidth = Math.max(0, width - nonFlexWidth - paddingHoriz);
15937         
15938         if (tooNarrow) {
15939             for (i = 0; i < visibleCount; i++) {
15940                 boxes[i].width = visibleItems[i].minWidth || visibleItems[i].width || boxes[i].width;
15941             }
15942         } else {
15943             
15944             
15945             if (shortfall > 0) {
15946                 var minWidths = [];
15947                 
15948                 
15949                 for (var index = 0, length = visibleCount; index < length; index++) {
15950                     var item     = visibleItems[index],
15951                         minWidth = item.minWidth || 0;
15952
15953                     
15954                     
15955                     if (item.flex) {
15956                         boxes[index].width = minWidth;
15957                     } else {
15958                         minWidths.push({
15959                             minWidth : minWidth,
15960                             available: boxes[index].width - minWidth,
15961                             index    : index
15962                         });
15963                     }
15964                 }
15965                 
15966                 
15967                 minWidths.sort(function(a, b) {
15968                     return a.available > b.available ? 1 : -1;
15969                 });
15970                 
15971                 
15972                 for (var i = 0, length = minWidths.length; i < length; i++) {
15973                     var itemIndex = minWidths[i].index;
15974                     
15975                     if (itemIndex == undefined) {
15976                         continue;
15977                     }
15978                         
15979                     var item      = visibleItems[itemIndex],
15980                         box       = boxes[itemIndex],
15981                         oldWidth  = box.width,
15982                         minWidth  = item.minWidth,
15983                         newWidth  = Math.max(minWidth, oldWidth - Math.ceil(shortfall / (length - i))),
15984                         reduction = oldWidth - newWidth;
15985                     
15986                     boxes[itemIndex].width = newWidth;
15987                     shortfall -= reduction;                    
15988                 }
15989             } else {
15990                 
15991                 var remainingWidth = availableWidth,
15992                     remainingFlex  = totalFlex;
15993
15994                 
15995                 for (i = 0; i < visibleCount; i++) {
15996                     child = visibleItems[i];
15997                     calcs = boxes[i];
15998
15999                     childMargins = child.margins;
16000                     vertMargins  = childMargins.top + childMargins.bottom;
16001
16002                     if (isStart && child.flex && !child.width) {
16003                         flexedWidth     = Math.ceil((child.flex / remainingFlex) * remainingWidth);
16004                         remainingWidth -= flexedWidth;
16005                         remainingFlex  -= child.flex;
16006
16007                         calcs.width = flexedWidth;
16008                         calcs.dirtySize = true;
16009                     }
16010                 }
16011             }
16012         }
16013         
16014         if (isCenter) {
16015             leftOffset += availableWidth / 2;
16016         } else if (isEnd) {
16017             leftOffset += availableWidth;
16018         }
16019         
16020         
16021         for (i = 0; i < visibleCount; i++) {
16022             child = visibleItems[i];
16023             calcs = boxes[i];
16024             
16025             childMargins = child.margins;
16026             leftOffset  += childMargins.left;
16027             vertMargins  = childMargins.top + childMargins.bottom;
16028             
16029             calcs.left = leftOffset;
16030             calcs.top  = topOffset + childMargins.top;
16031
16032             switch (this.align) {
16033                 case 'stretch':
16034                     stretchHeight = availHeight - vertMargins;
16035                     calcs.height  = stretchHeight.constrain(child.minHeight || 0, child.maxHeight || 1000000);
16036                     calcs.dirtySize = true;
16037                     break;
16038                 case 'stretchmax':
16039                     stretchHeight = maxHeight - vertMargins;
16040                     calcs.height  = stretchHeight.constrain(child.minHeight || 0, child.maxHeight || 1000000);
16041                     calcs.dirtySize = true;
16042                     break;
16043                 case 'middle':
16044                     var diff = availHeight - calcs.height - vertMargins;
16045                     if (diff > 0) {
16046                         calcs.top = topOffset + vertMargins + (diff / 2);
16047                     }
16048             }
16049             
16050             leftOffset += calcs.width + childMargins.right;
16051         }
16052
16053         return {
16054             boxes: boxes,
16055             meta : {
16056                 maxHeight   : maxHeight,
16057                 nonFlexWidth: nonFlexWidth,
16058                 desiredWidth: desiredWidth,
16059                 minimumWidth: minimumWidth,
16060                 shortfall   : desiredWidth - width,
16061                 tooNarrow   : tooNarrow
16062             }
16063         };
16064     }
16065 });
16066
16067 Ext.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout;
16068 Ext.layout.VBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
16069     
16070     align : 'left', 
16071     type: 'vbox',
16072
16073     
16074
16075     
16076
16077     
16078     calculateChildBoxes: function(visibleItems, targetSize) {
16079         var visibleCount = visibleItems.length,
16080
16081             padding      = this.padding,
16082             topOffset    = padding.top,
16083             leftOffset   = padding.left,
16084             paddingVert  = topOffset  + padding.bottom,
16085             paddingHoriz = leftOffset + padding.right,
16086
16087             width        = targetSize.width - this.scrollOffset,
16088             height       = targetSize.height,
16089             availWidth   = Math.max(0, width - paddingHoriz),
16090
16091             isStart      = this.pack == 'start',
16092             isCenter     = this.pack == 'center',
16093             isEnd        = this.pack == 'end',
16094
16095             nonFlexHeight= 0,
16096             maxWidth     = 0,
16097             totalFlex    = 0,
16098             desiredHeight= 0,
16099             minimumHeight= 0,
16100
16101             
16102             boxes        = [],
16103             
16104             
16105             child, childWidth, childHeight, childSize, childMargins, canLayout, i, calcs, flexedWidth, 
16106             horizMargins, vertMargins, stretchWidth;
16107
16108         
16109         for (i = 0; i < visibleCount; i++) {
16110             child = visibleItems[i];
16111             childHeight = child.height;
16112             childWidth  = child.width;
16113             canLayout   = !child.hasLayout && typeof child.doLayout == 'function';
16114
16115             
16116             if (typeof childHeight != 'number') {
16117
16118                 
16119                 if (child.flex && !childHeight) {
16120                     totalFlex += child.flex;
16121
16122                 
16123                 } else {
16124                     
16125                     
16126                     if (!childHeight && canLayout) {
16127                         child.doLayout();
16128                     }
16129
16130                     childSize = child.getSize();
16131                     childWidth = childSize.width;
16132                     childHeight = childSize.height;
16133                 }
16134             }
16135             
16136             childMargins = child.margins;
16137             vertMargins  = childMargins.top + childMargins.bottom;
16138
16139             nonFlexHeight += vertMargins + (childHeight || 0);
16140             desiredHeight += vertMargins + (child.flex ? child.minHeight || 0 : childHeight);
16141             minimumHeight += vertMargins + (child.minHeight || childHeight || 0);
16142
16143             
16144             if (typeof childWidth != 'number') {
16145                 if (canLayout) {
16146                     child.doLayout();
16147                 }
16148                 childWidth = child.getWidth();
16149             }
16150
16151             maxWidth = Math.max(maxWidth, childWidth + childMargins.left + childMargins.right);
16152
16153             
16154             boxes.push({
16155                 component: child,
16156                 height   : childHeight || undefined,
16157                 width    : childWidth || undefined
16158             });
16159         }
16160                 
16161         var shortfall = desiredHeight - height,
16162             tooNarrow = minimumHeight > height;
16163
16164         
16165         var availableHeight = Math.max(0, (height - nonFlexHeight - paddingVert));
16166         
16167         if (tooNarrow) {
16168             for (i = 0, length = visibleCount; i < length; i++) {
16169                 boxes[i].height = visibleItems[i].minHeight || visibleItems[i].height || boxes[i].height;
16170             }
16171         } else {
16172             
16173             
16174             if (shortfall > 0) {
16175                 var minHeights = [];
16176
16177                 
16178                 for (var index = 0, length = visibleCount; index < length; index++) {
16179                     var item      = visibleItems[index],
16180                         minHeight = item.minHeight || 0;
16181
16182                     
16183                     
16184                     if (item.flex) {
16185                         boxes[index].height = minHeight;
16186                     } else {
16187                         minHeights.push({
16188                             minHeight: minHeight, 
16189                             available: boxes[index].height - minHeight,
16190                             index    : index
16191                         });
16192                     }
16193                 }
16194
16195                 
16196                 minHeights.sort(function(a, b) {
16197                     return a.available > b.available ? 1 : -1;
16198                 });
16199
16200                 
16201                 for (var i = 0, length = minHeights.length; i < length; i++) {
16202                     var itemIndex = minHeights[i].index;
16203
16204                     if (itemIndex == undefined) {
16205                         continue;
16206                     }
16207
16208                     var item      = visibleItems[itemIndex],
16209                         box       = boxes[itemIndex],
16210                         oldHeight  = box.height,
16211                         minHeight  = item.minHeight,
16212                         newHeight  = Math.max(minHeight, oldHeight - Math.ceil(shortfall / (length - i))),
16213                         reduction = oldHeight - newHeight;
16214
16215                     boxes[itemIndex].height = newHeight;
16216                     shortfall -= reduction;
16217                 }
16218             } else {
16219                 
16220                 var remainingHeight = availableHeight,
16221                     remainingFlex   = totalFlex;
16222                 
16223                 
16224                 for (i = 0; i < visibleCount; i++) {
16225                     child = visibleItems[i];
16226                     calcs = boxes[i];
16227
16228                     childMargins = child.margins;
16229                     horizMargins = childMargins.left + childMargins.right;
16230
16231                     if (isStart && child.flex && !child.height) {
16232                         flexedHeight     = Math.ceil((child.flex / remainingFlex) * remainingHeight);
16233                         remainingHeight -= flexedHeight;
16234                         remainingFlex   -= child.flex;
16235
16236                         calcs.height = flexedHeight;
16237                         calcs.dirtySize = true;
16238                     }
16239                 }
16240             }
16241         }
16242
16243         if (isCenter) {
16244             topOffset += availableHeight / 2;
16245         } else if (isEnd) {
16246             topOffset += availableHeight;
16247         }
16248
16249         
16250         for (i = 0; i < visibleCount; i++) {
16251             child = visibleItems[i];
16252             calcs = boxes[i];
16253
16254             childMargins = child.margins;
16255             topOffset   += childMargins.top;
16256             horizMargins = childMargins.left + childMargins.right;
16257             
16258
16259             calcs.left = leftOffset + childMargins.left;
16260             calcs.top  = topOffset;
16261             
16262             switch (this.align) {
16263                 case 'stretch':
16264                     stretchWidth = availWidth - horizMargins;
16265                     calcs.width  = stretchWidth.constrain(child.minWidth || 0, child.maxWidth || 1000000);
16266                     calcs.dirtySize = true;
16267                     break;
16268                 case 'stretchmax':
16269                     stretchWidth = maxWidth - horizMargins;
16270                     calcs.width  = stretchWidth.constrain(child.minWidth || 0, child.maxWidth || 1000000);
16271                     calcs.dirtySize = true;
16272                     break;
16273                 case 'center':
16274                     var diff = availWidth - calcs.width - horizMargins;
16275                     if (diff > 0) {
16276                         calcs.left = leftOffset + horizMargins + (diff / 2);
16277                     }
16278             }
16279
16280             topOffset += calcs.height + childMargins.bottom;
16281         }
16282         
16283         return {
16284             boxes: boxes,
16285             meta : {
16286                 maxWidth     : maxWidth,
16287                 nonFlexHeight: nonFlexHeight,
16288                 desiredHeight: desiredHeight,
16289                 minimumHeight: minimumHeight,
16290                 shortfall    : desiredHeight - height,
16291                 tooNarrow    : tooNarrow
16292             }
16293         };
16294     }
16295 });
16296
16297 Ext.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout;
16298
16299 Ext.layout.ToolbarLayout = Ext.extend(Ext.layout.ContainerLayout, {
16300     monitorResize : true,
16301
16302     type: 'toolbar',
16303
16304     
16305     triggerWidth: 18,
16306
16307     
16308     noItemsMenuText : '<div class="x-toolbar-no-items">(None)</div>',
16309
16310     
16311     lastOverflow: false,
16312
16313     
16314     tableHTML: [
16315         '<table cellspacing="0" class="x-toolbar-ct">',
16316             '<tbody>',
16317                 '<tr>',
16318                     '<td class="x-toolbar-left" align="{0}">',
16319                         '<table cellspacing="0">',
16320                             '<tbody>',
16321                                 '<tr class="x-toolbar-left-row"></tr>',
16322                             '</tbody>',
16323                         '</table>',
16324                     '</td>',
16325                     '<td class="x-toolbar-right" align="right">',
16326                         '<table cellspacing="0" class="x-toolbar-right-ct">',
16327                             '<tbody>',
16328                                 '<tr>',
16329                                     '<td>',
16330                                         '<table cellspacing="0">',
16331                                             '<tbody>',
16332                                                 '<tr class="x-toolbar-right-row"></tr>',
16333                                             '</tbody>',
16334                                         '</table>',
16335                                     '</td>',
16336                                     '<td>',
16337                                         '<table cellspacing="0">',
16338                                             '<tbody>',
16339                                                 '<tr class="x-toolbar-extras-row"></tr>',
16340                                             '</tbody>',
16341                                         '</table>',
16342                                     '</td>',
16343                                 '</tr>',
16344                             '</tbody>',
16345                         '</table>',
16346                     '</td>',
16347                 '</tr>',
16348             '</tbody>',
16349         '</table>'
16350     ].join(""),
16351
16352     
16353     onLayout : function(ct, target) {
16354         
16355         if (!this.leftTr) {
16356             var align = ct.buttonAlign == 'center' ? 'center' : 'left';
16357
16358             target.addClass('x-toolbar-layout-ct');
16359             target.insertHtml('beforeEnd', String.format(this.tableHTML, align));
16360
16361             this.leftTr   = target.child('tr.x-toolbar-left-row', true);
16362             this.rightTr  = target.child('tr.x-toolbar-right-row', true);
16363             this.extrasTr = target.child('tr.x-toolbar-extras-row', true);
16364
16365             if (this.hiddenItem == undefined) {
16366                 
16367                 this.hiddenItems = [];
16368             }
16369         }
16370
16371         var side     = ct.buttonAlign == 'right' ? this.rightTr : this.leftTr,
16372             items    = ct.items.items,
16373             position = 0;
16374
16375         
16376         for (var i = 0, len = items.length, c; i < len; i++, position++) {
16377             c = items[i];
16378
16379             if (c.isFill) {
16380                 side   = this.rightTr;
16381                 position = -1;
16382             } else if (!c.rendered) {
16383                 c.render(this.insertCell(c, side, position));
16384                 this.configureItem(c);
16385             } else {
16386                 if (!c.xtbHidden && !this.isValidParent(c, side.childNodes[position])) {
16387                     var td = this.insertCell(c, side, position);
16388                     td.appendChild(c.getPositionEl().dom);
16389                     c.container = Ext.get(td);
16390                 }
16391             }
16392         }
16393
16394         
16395         this.cleanup(this.leftTr);
16396         this.cleanup(this.rightTr);
16397         this.cleanup(this.extrasTr);
16398         this.fitToSize(target);
16399     },
16400
16401     
16402     cleanup : function(el) {
16403         var cn = el.childNodes, i, c;
16404
16405         for (i = cn.length-1; i >= 0 && (c = cn[i]); i--) {
16406             if (!c.firstChild) {
16407                 el.removeChild(c);
16408             }
16409         }
16410     },
16411
16412     
16413     insertCell : function(c, target, position) {
16414         var td = document.createElement('td');
16415         td.className = 'x-toolbar-cell';
16416
16417         target.insertBefore(td, target.childNodes[position] || null);
16418
16419         return td;
16420     },
16421
16422     
16423     hideItem : function(item) {
16424         this.hiddenItems.push(item);
16425
16426         item.xtbHidden = true;
16427         item.xtbWidth = item.getPositionEl().dom.parentNode.offsetWidth;
16428         item.hide();
16429     },
16430
16431     
16432     unhideItem : function(item) {
16433         item.show();
16434         item.xtbHidden = false;
16435         this.hiddenItems.remove(item);
16436     },
16437
16438     
16439     getItemWidth : function(c) {
16440         return c.hidden ? (c.xtbWidth || 0) : c.getPositionEl().dom.parentNode.offsetWidth;
16441     },
16442
16443     
16444     fitToSize : function(target) {
16445         if (this.container.enableOverflow === false) {
16446             return;
16447         }
16448
16449         var width       = target.dom.clientWidth,
16450             tableWidth  = target.dom.firstChild.offsetWidth,
16451             clipWidth   = width - this.triggerWidth,
16452             lastWidth   = this.lastWidth || 0,
16453
16454             hiddenItems = this.hiddenItems,
16455             hasHiddens  = hiddenItems.length != 0,
16456             isLarger    = width >= lastWidth;
16457
16458         this.lastWidth  = width;
16459
16460         if (tableWidth > width || (hasHiddens && isLarger)) {
16461             var items     = this.container.items.items,
16462                 len       = items.length,
16463                 loopWidth = 0,
16464                 item;
16465
16466             for (var i = 0; i < len; i++) {
16467                 item = items[i];
16468
16469                 if (!item.isFill) {
16470                     loopWidth += this.getItemWidth(item);
16471                     if (loopWidth > clipWidth) {
16472                         if (!(item.hidden || item.xtbHidden)) {
16473                             this.hideItem(item);
16474                         }
16475                     } else if (item.xtbHidden) {
16476                         this.unhideItem(item);
16477                     }
16478                 }
16479             }
16480         }
16481
16482         
16483         hasHiddens = hiddenItems.length != 0;
16484
16485         if (hasHiddens) {
16486             this.initMore();
16487
16488             if (!this.lastOverflow) {
16489                 this.container.fireEvent('overflowchange', this.container, true);
16490                 this.lastOverflow = true;
16491             }
16492         } else if (this.more) {
16493             this.clearMenu();
16494             this.more.destroy();
16495             delete this.more;
16496
16497             if (this.lastOverflow) {
16498                 this.container.fireEvent('overflowchange', this.container, false);
16499                 this.lastOverflow = false;
16500             }
16501         }
16502     },
16503
16504     
16505     createMenuConfig : function(component, hideOnClick){
16506         var config = Ext.apply({}, component.initialConfig),
16507             group  = component.toggleGroup;
16508
16509         Ext.copyTo(config, component, [
16510             'iconCls', 'icon', 'itemId', 'disabled', 'handler', 'scope', 'menu'
16511         ]);
16512
16513         Ext.apply(config, {
16514             text       : component.overflowText || component.text,
16515             hideOnClick: hideOnClick
16516         });
16517
16518         if (group || component.enableToggle) {
16519             Ext.apply(config, {
16520                 group  : group,
16521                 checked: component.pressed,
16522                 listeners: {
16523                     checkchange: function(item, checked){
16524                         component.toggle(checked);
16525                     }
16526                 }
16527             });
16528         }
16529
16530         delete config.ownerCt;
16531         delete config.xtype;
16532         delete config.id;
16533
16534         return config;
16535     },
16536
16537     
16538     addComponentToMenu : function(menu, component) {
16539         if (component instanceof Ext.Toolbar.Separator) {
16540             menu.add('-');
16541
16542         } else if (Ext.isFunction(component.isXType)) {
16543             if (component.isXType('splitbutton')) {
16544                 menu.add(this.createMenuConfig(component, true));
16545
16546             } else if (component.isXType('button')) {
16547                 menu.add(this.createMenuConfig(component, !component.menu));
16548
16549             } else if (component.isXType('buttongroup')) {
16550                 component.items.each(function(item){
16551                      this.addComponentToMenu(menu, item);
16552                 }, this);
16553             }
16554         }
16555     },
16556
16557     
16558     clearMenu : function(){
16559         var menu = this.moreMenu;
16560         if (menu && menu.items) {
16561             menu.items.each(function(item){
16562                 delete item.menu;
16563             });
16564         }
16565     },
16566
16567     
16568     beforeMoreShow : function(menu) {
16569         var items = this.container.items.items,
16570             len   = items.length,
16571             item,
16572             prev;
16573
16574         var needsSep = function(group, item){
16575             return group.isXType('buttongroup') && !(item instanceof Ext.Toolbar.Separator);
16576         };
16577
16578         this.clearMenu();
16579         menu.removeAll();
16580         for (var i = 0; i < len; i++) {
16581             item = items[i];
16582             if (item.xtbHidden) {
16583                 if (prev && (needsSep(item, prev) || needsSep(prev, item))) {
16584                     menu.add('-');
16585                 }
16586                 this.addComponentToMenu(menu, item);
16587                 prev = item;
16588             }
16589         }
16590
16591         
16592         if (menu.items.length < 1) {
16593             menu.add(this.noItemsMenuText);
16594         }
16595     },
16596
16597     
16598     initMore : function(){
16599         if (!this.more) {
16600             
16601             this.moreMenu = new Ext.menu.Menu({
16602                 ownerCt : this.container,
16603                 listeners: {
16604                     beforeshow: this.beforeMoreShow,
16605                     scope: this
16606                 }
16607             });
16608
16609             
16610             this.more = new Ext.Button({
16611                 iconCls: 'x-toolbar-more-icon',
16612                 cls    : 'x-toolbar-more',
16613                 menu   : this.moreMenu,
16614                 ownerCt: this.container
16615             });
16616
16617             var td = this.insertCell(this.more, this.extrasTr, 100);
16618             this.more.render(td);
16619         }
16620     },
16621
16622     destroy : function(){
16623         Ext.destroy(this.more, this.moreMenu);
16624         delete this.leftTr;
16625         delete this.rightTr;
16626         delete this.extrasTr;
16627         Ext.layout.ToolbarLayout.superclass.destroy.call(this);
16628     }
16629 });
16630
16631 Ext.Container.LAYOUTS.toolbar = Ext.layout.ToolbarLayout;
16632
16633  Ext.layout.MenuLayout = Ext.extend(Ext.layout.ContainerLayout, {
16634     monitorResize : true,
16635
16636     type: 'menu',
16637
16638     setContainer : function(ct){
16639         this.monitorResize = !ct.floating;
16640         
16641         
16642         ct.on('autosize', this.doAutoSize, this);
16643         Ext.layout.MenuLayout.superclass.setContainer.call(this, ct);
16644     },
16645
16646     renderItem : function(c, position, target){
16647         if (!this.itemTpl) {
16648             this.itemTpl = Ext.layout.MenuLayout.prototype.itemTpl = new Ext.XTemplate(
16649                 '<li id="{itemId}" class="{itemCls}">',
16650                     '<tpl if="needsIcon">',
16651                         '<img alt="{altText}" src="{icon}" class="{iconCls}"/>',
16652                     '</tpl>',
16653                 '</li>'
16654             );
16655         }
16656
16657         if(c && !c.rendered){
16658             if(Ext.isNumber(position)){
16659                 position = target.dom.childNodes[position];
16660             }
16661             var a = this.getItemArgs(c);
16662
16663
16664             c.render(c.positionEl = position ?
16665                 this.itemTpl.insertBefore(position, a, true) :
16666                 this.itemTpl.append(target, a, true));
16667
16668
16669             c.positionEl.menuItemId = c.getItemId();
16670
16671
16672
16673             if (!a.isMenuItem && a.needsIcon) {
16674                 c.positionEl.addClass('x-menu-list-item-indent');
16675             }
16676             this.configureItem(c);
16677         }else if(c && !this.isValidParent(c, target)){
16678             if(Ext.isNumber(position)){
16679                 position = target.dom.childNodes[position];
16680             }
16681             target.dom.insertBefore(c.getActionEl().dom, position || null);
16682         }
16683     },
16684
16685     getItemArgs : function(c) {
16686         var isMenuItem = c instanceof Ext.menu.Item,
16687             canHaveIcon = !(isMenuItem || c instanceof Ext.menu.Separator);
16688
16689         return {
16690             isMenuItem: isMenuItem,
16691             needsIcon: canHaveIcon && (c.icon || c.iconCls),
16692             icon: c.icon || Ext.BLANK_IMAGE_URL,
16693             iconCls: 'x-menu-item-icon ' + (c.iconCls || ''),
16694             itemId: 'x-menu-el-' + c.id,
16695             itemCls: 'x-menu-list-item ',
16696             altText: c.altText || ''
16697         };
16698     },
16699
16700     
16701     isValidParent : function(c, target) {
16702         return c.el.up('li.x-menu-list-item', 5).dom.parentNode === (target.dom || target);
16703     },
16704
16705     onLayout : function(ct, target){
16706         Ext.layout.MenuLayout.superclass.onLayout.call(this, ct, target);
16707         this.doAutoSize();
16708     },
16709
16710     doAutoSize : function(){
16711         var ct = this.container, w = ct.width;
16712         if(ct.floating){
16713             if(w){
16714                 ct.setWidth(w);
16715             }else if(Ext.isIE){
16716                 ct.setWidth(Ext.isStrict && (Ext.isIE7 || Ext.isIE8) ? 'auto' : ct.minWidth);
16717                 var el = ct.getEl(), t = el.dom.offsetWidth; 
16718                 ct.setWidth(ct.getLayoutTarget().getWidth() + el.getFrameWidth('lr'));
16719             }
16720         }
16721     }
16722 });
16723 Ext.Container.LAYOUTS['menu'] = Ext.layout.MenuLayout;
16724
16725 Ext.Viewport = Ext.extend(Ext.Container, {
16726     
16727     
16728     
16729     
16730     
16731     
16732     
16733     
16734     
16735     
16736     
16737     
16738
16739     initComponent : function() {
16740         Ext.Viewport.superclass.initComponent.call(this);
16741         document.getElementsByTagName('html')[0].className += ' x-viewport';
16742         this.el = Ext.getBody();
16743         this.el.setHeight = Ext.emptyFn;
16744         this.el.setWidth = Ext.emptyFn;
16745         this.el.setSize = Ext.emptyFn;
16746         this.el.dom.scroll = 'no';
16747         this.allowDomMove = false;
16748         this.autoWidth = true;
16749         this.autoHeight = true;
16750         Ext.EventManager.onWindowResize(this.fireResize, this);
16751         this.renderTo = this.el;
16752     },
16753
16754     fireResize : function(w, h){
16755         this.fireEvent('resize', this, w, h, w, h);
16756     }
16757 });
16758 Ext.reg('viewport', Ext.Viewport);
16759
16760 Ext.Panel = Ext.extend(Ext.Container, {
16761     
16762     
16763     
16764     
16765     
16766     
16767     
16768     
16769     
16770     
16771     
16772     
16773     
16774     
16775     
16776     
16777     
16778     
16779     
16780     
16781     
16782     
16783     
16784     
16785     
16786     
16787     
16788     
16789     
16790     
16791     
16792     
16793
16794     
16795     
16796     
16797     
16798     
16799     
16800     
16801     
16802
16803
16804     
16805     baseCls : 'x-panel',
16806     
16807     collapsedCls : 'x-panel-collapsed',
16808     
16809     maskDisabled : true,
16810     
16811     animCollapse : Ext.enableFx,
16812     
16813     headerAsText : true,
16814     
16815     buttonAlign : 'right',
16816     
16817     collapsed : false,
16818     
16819     collapseFirst : true,
16820     
16821     minButtonWidth : 75,
16822     
16823     
16824     elements : 'body',
16825     
16826     preventBodyReset : false,
16827
16828     
16829     padding: undefined,
16830
16831     
16832     resizeEvent: 'bodyresize',
16833
16834     
16835     
16836     
16837     toolTarget : 'header',
16838     collapseEl : 'bwrap',
16839     slideAnchor : 't',
16840     disabledClass : '',
16841
16842     
16843     deferHeight : true,
16844     
16845     expandDefaults: {
16846         duration : 0.25
16847     },
16848     
16849     collapseDefaults : {
16850         duration : 0.25
16851     },
16852
16853     
16854     initComponent : function(){
16855         Ext.Panel.superclass.initComponent.call(this);
16856
16857         this.addEvents(
16858             
16859             'bodyresize',
16860             
16861             'titlechange',
16862             
16863             'iconchange',
16864             
16865             'collapse',
16866             
16867             'expand',
16868             
16869             'beforecollapse',
16870             
16871             'beforeexpand',
16872             
16873             'beforeclose',
16874             
16875             'close',
16876             
16877             'activate',
16878             
16879             'deactivate'
16880         );
16881
16882         if(this.unstyled){
16883             this.baseCls = 'x-plain';
16884         }
16885
16886
16887         this.toolbars = [];
16888         
16889         if(this.tbar){
16890             this.elements += ',tbar';
16891             this.topToolbar = this.createToolbar(this.tbar);
16892             this.tbar = null;
16893
16894         }
16895         if(this.bbar){
16896             this.elements += ',bbar';
16897             this.bottomToolbar = this.createToolbar(this.bbar);
16898             this.bbar = null;
16899         }
16900
16901         if(this.header === true){
16902             this.elements += ',header';
16903             this.header = null;
16904         }else if(this.headerCfg || (this.title && this.header !== false)){
16905             this.elements += ',header';
16906         }
16907
16908         if(this.footerCfg || this.footer === true){
16909             this.elements += ',footer';
16910             this.footer = null;
16911         }
16912
16913         if(this.buttons){
16914             this.fbar = this.buttons;
16915             this.buttons = null;
16916         }
16917         if(this.fbar){
16918             this.createFbar(this.fbar);
16919         }
16920         if(this.autoLoad){
16921             this.on('render', this.doAutoLoad, this, {delay:10});
16922         }
16923     },
16924
16925     
16926     createFbar : function(fbar){
16927         var min = this.minButtonWidth;
16928         this.elements += ',footer';
16929         this.fbar = this.createToolbar(fbar, {
16930             buttonAlign: this.buttonAlign,
16931             toolbarCls: 'x-panel-fbar',
16932             enableOverflow: false,
16933             defaults: function(c){
16934                 return {
16935                     minWidth: c.minWidth || min
16936                 };
16937             }
16938         });
16939         
16940         
16941         
16942         this.fbar.items.each(function(c){
16943             c.minWidth = c.minWidth || this.minButtonWidth;
16944         }, this);
16945         this.buttons = this.fbar.items.items;
16946     },
16947
16948     
16949     createToolbar: function(tb, options){
16950         var result;
16951         
16952         if(Ext.isArray(tb)){
16953             tb = {
16954                 items: tb
16955             };
16956         }
16957         result = tb.events ? Ext.apply(tb, options) : this.createComponent(Ext.apply({}, tb, options), 'toolbar');
16958         this.toolbars.push(result);
16959         return result;
16960     },
16961
16962     
16963     createElement : function(name, pnode){
16964         if(this[name]){
16965             pnode.appendChild(this[name].dom);
16966             return;
16967         }
16968
16969         if(name === 'bwrap' || this.elements.indexOf(name) != -1){
16970             if(this[name+'Cfg']){
16971                 this[name] = Ext.fly(pnode).createChild(this[name+'Cfg']);
16972             }else{
16973                 var el = document.createElement('div');
16974                 el.className = this[name+'Cls'];
16975                 this[name] = Ext.get(pnode.appendChild(el));
16976             }
16977             if(this[name+'CssClass']){
16978                 this[name].addClass(this[name+'CssClass']);
16979             }
16980             if(this[name+'Style']){
16981                 this[name].applyStyles(this[name+'Style']);
16982             }
16983         }
16984     },
16985
16986     
16987     onRender : function(ct, position){
16988         Ext.Panel.superclass.onRender.call(this, ct, position);
16989         this.createClasses();
16990
16991         var el = this.el,
16992             d = el.dom,
16993             bw,
16994             ts;
16995
16996
16997         if(this.collapsible && !this.hideCollapseTool){
16998             this.tools = this.tools ? this.tools.slice(0) : [];
16999             this.tools[this.collapseFirst?'unshift':'push']({
17000                 id: 'toggle',
17001                 handler : this.toggleCollapse,
17002                 scope: this
17003             });
17004         }
17005
17006         if(this.tools){
17007             ts = this.tools;
17008             this.elements += (this.header !== false) ? ',header' : '';
17009         }
17010         this.tools = {};
17011
17012         el.addClass(this.baseCls);
17013         if(d.firstChild){ 
17014             this.header = el.down('.'+this.headerCls);
17015             this.bwrap = el.down('.'+this.bwrapCls);
17016             var cp = this.bwrap ? this.bwrap : el;
17017             this.tbar = cp.down('.'+this.tbarCls);
17018             this.body = cp.down('.'+this.bodyCls);
17019             this.bbar = cp.down('.'+this.bbarCls);
17020             this.footer = cp.down('.'+this.footerCls);
17021             this.fromMarkup = true;
17022         }
17023         if (this.preventBodyReset === true) {
17024             el.addClass('x-panel-reset');
17025         }
17026         if(this.cls){
17027             el.addClass(this.cls);
17028         }
17029
17030         if(this.buttons){
17031             this.elements += ',footer';
17032         }
17033
17034         
17035
17036         
17037         if(this.frame){
17038             el.insertHtml('afterBegin', String.format(Ext.Element.boxMarkup, this.baseCls));
17039
17040             this.createElement('header', d.firstChild.firstChild.firstChild);
17041             this.createElement('bwrap', d);
17042
17043             
17044             bw = this.bwrap.dom;
17045             var ml = d.childNodes[1], bl = d.childNodes[2];
17046             bw.appendChild(ml);
17047             bw.appendChild(bl);
17048
17049             var mc = bw.firstChild.firstChild.firstChild;
17050             this.createElement('tbar', mc);
17051             this.createElement('body', mc);
17052             this.createElement('bbar', mc);
17053             this.createElement('footer', bw.lastChild.firstChild.firstChild);
17054
17055             if(!this.footer){
17056                 this.bwrap.dom.lastChild.className += ' x-panel-nofooter';
17057             }
17058             
17059             this.ft = Ext.get(this.bwrap.dom.lastChild);
17060             this.mc = Ext.get(mc);
17061         }else{
17062             this.createElement('header', d);
17063             this.createElement('bwrap', d);
17064
17065             
17066             bw = this.bwrap.dom;
17067             this.createElement('tbar', bw);
17068             this.createElement('body', bw);
17069             this.createElement('bbar', bw);
17070             this.createElement('footer', bw);
17071
17072             if(!this.header){
17073                 this.body.addClass(this.bodyCls + '-noheader');
17074                 if(this.tbar){
17075                     this.tbar.addClass(this.tbarCls + '-noheader');
17076                 }
17077             }
17078         }
17079
17080         if(Ext.isDefined(this.padding)){
17081             this.body.setStyle('padding', this.body.addUnits(this.padding));
17082         }
17083
17084         if(this.border === false){
17085             this.el.addClass(this.baseCls + '-noborder');
17086             this.body.addClass(this.bodyCls + '-noborder');
17087             if(this.header){
17088                 this.header.addClass(this.headerCls + '-noborder');
17089             }
17090             if(this.footer){
17091                 this.footer.addClass(this.footerCls + '-noborder');
17092             }
17093             if(this.tbar){
17094                 this.tbar.addClass(this.tbarCls + '-noborder');
17095             }
17096             if(this.bbar){
17097                 this.bbar.addClass(this.bbarCls + '-noborder');
17098             }
17099         }
17100
17101         if(this.bodyBorder === false){
17102            this.body.addClass(this.bodyCls + '-noborder');
17103         }
17104
17105         this.bwrap.enableDisplayMode('block');
17106
17107         if(this.header){
17108             this.header.unselectable();
17109
17110             
17111             if(this.headerAsText){
17112                 this.header.dom.innerHTML =
17113                     '<span class="' + this.headerTextCls + '">'+this.header.dom.innerHTML+'</span>';
17114
17115                 if(this.iconCls){
17116                     this.setIconClass(this.iconCls);
17117                 }
17118             }
17119         }
17120
17121         if(this.floating){
17122             this.makeFloating(this.floating);
17123         }
17124
17125         if(this.collapsible && this.titleCollapse && this.header){
17126             this.mon(this.header, 'click', this.toggleCollapse, this);
17127             this.header.setStyle('cursor', 'pointer');
17128         }
17129         if(ts){
17130             this.addTool.apply(this, ts);
17131         }
17132
17133         
17134         if(this.fbar){
17135             this.footer.addClass('x-panel-btns');
17136             this.fbar.ownerCt = this;
17137             this.fbar.render(this.footer);
17138             this.footer.createChild({cls:'x-clear'});
17139         }
17140         if(this.tbar && this.topToolbar){
17141             this.topToolbar.ownerCt = this;
17142             this.topToolbar.render(this.tbar);
17143         }
17144         if(this.bbar && this.bottomToolbar){
17145             this.bottomToolbar.ownerCt = this;
17146             this.bottomToolbar.render(this.bbar);
17147         }
17148     },
17149
17150     
17151     setIconClass : function(cls){
17152         var old = this.iconCls;
17153         this.iconCls = cls;
17154         if(this.rendered && this.header){
17155             if(this.frame){
17156                 this.header.addClass('x-panel-icon');
17157                 this.header.replaceClass(old, this.iconCls);
17158             }else{
17159                 var hd = this.header,
17160                     img = hd.child('img.x-panel-inline-icon');
17161                 if(img){
17162                     Ext.fly(img).replaceClass(old, this.iconCls);
17163                 }else{
17164                     var hdspan = hd.child('span.' + this.headerTextCls);
17165                     if (hdspan) {
17166                         Ext.DomHelper.insertBefore(hdspan.dom, {
17167                             tag:'img', alt: '', src: Ext.BLANK_IMAGE_URL, cls:'x-panel-inline-icon '+this.iconCls
17168                         });
17169                     }
17170                  }
17171             }
17172         }
17173         this.fireEvent('iconchange', this, cls, old);
17174     },
17175
17176     
17177     makeFloating : function(cfg){
17178         this.floating = true;
17179         this.el = new Ext.Layer(Ext.apply({}, cfg, {
17180             shadow: Ext.isDefined(this.shadow) ? this.shadow : 'sides',
17181             shadowOffset: this.shadowOffset,
17182             constrain:false,
17183             shim: this.shim === false ? false : undefined
17184         }), this.el);
17185     },
17186
17187     
17188     getTopToolbar : function(){
17189         return this.topToolbar;
17190     },
17191
17192     
17193     getBottomToolbar : function(){
17194         return this.bottomToolbar;
17195     },
17196
17197     
17198     getFooterToolbar : function() {
17199         return this.fbar;
17200     },
17201
17202     
17203     addButton : function(config, handler, scope){
17204         if(!this.fbar){
17205             this.createFbar([]);
17206         }
17207         if(handler){
17208             if(Ext.isString(config)){
17209                 config = {text: config};
17210             }
17211             config = Ext.apply({
17212                 handler: handler,
17213                 scope: scope
17214             }, config);
17215         }
17216         return this.fbar.add(config);
17217     },
17218
17219     
17220     addTool : function(){
17221         if(!this.rendered){
17222             if(!this.tools){
17223                 this.tools = [];
17224             }
17225             Ext.each(arguments, function(arg){
17226                 this.tools.push(arg);
17227             }, this);
17228             return;
17229         }
17230          
17231         if(!this[this.toolTarget]){
17232             return;
17233         }
17234         if(!this.toolTemplate){
17235             
17236             var tt = new Ext.Template(
17237                  '<div class="x-tool x-tool-{id}">&#160;</div>'
17238             );
17239             tt.disableFormats = true;
17240             tt.compile();
17241             Ext.Panel.prototype.toolTemplate = tt;
17242         }
17243         for(var i = 0, a = arguments, len = a.length; i < len; i++) {
17244             var tc = a[i];
17245             if(!this.tools[tc.id]){
17246                 var overCls = 'x-tool-'+tc.id+'-over';
17247                 var t = this.toolTemplate.insertFirst(this[this.toolTarget], tc, true);
17248                 this.tools[tc.id] = t;
17249                 t.enableDisplayMode('block');
17250                 this.mon(t, 'click',  this.createToolHandler(t, tc, overCls, this));
17251                 if(tc.on){
17252                     this.mon(t, tc.on);
17253                 }
17254                 if(tc.hidden){
17255                     t.hide();
17256                 }
17257                 if(tc.qtip){
17258                     if(Ext.isObject(tc.qtip)){
17259                         Ext.QuickTips.register(Ext.apply({
17260                               target: t.id
17261                         }, tc.qtip));
17262                     } else {
17263                         t.dom.qtip = tc.qtip;
17264                     }
17265                 }
17266                 t.addClassOnOver(overCls);
17267             }
17268         }
17269     },
17270
17271     onLayout : function(shallow, force){
17272         Ext.Panel.superclass.onLayout.apply(this, arguments);
17273         if(this.hasLayout && this.toolbars.length > 0){
17274             Ext.each(this.toolbars, function(tb){
17275                 tb.doLayout(undefined, force);
17276             });
17277             this.syncHeight();
17278         }
17279     },
17280
17281     syncHeight : function(){
17282         var h = this.toolbarHeight,
17283                 bd = this.body,
17284                 lsh = this.lastSize.height,
17285                 sz;
17286
17287         if(this.autoHeight || !Ext.isDefined(lsh) || lsh == 'auto'){
17288             return;
17289         }
17290
17291
17292         if(h != this.getToolbarHeight()){
17293             h = Math.max(0, lsh - this.getFrameHeight());
17294             bd.setHeight(h);
17295             sz = bd.getSize();
17296             this.toolbarHeight = this.getToolbarHeight();
17297             this.onBodyResize(sz.width, sz.height);
17298         }
17299     },
17300
17301     
17302     onShow : function(){
17303         if(this.floating){
17304             return this.el.show();
17305         }
17306         Ext.Panel.superclass.onShow.call(this);
17307     },
17308
17309     
17310     onHide : function(){
17311         if(this.floating){
17312             return this.el.hide();
17313         }
17314         Ext.Panel.superclass.onHide.call(this);
17315     },
17316
17317     
17318     createToolHandler : function(t, tc, overCls, panel){
17319         return function(e){
17320             t.removeClass(overCls);
17321             if(tc.stopEvent !== false){
17322                 e.stopEvent();
17323             }
17324             if(tc.handler){
17325                 tc.handler.call(tc.scope || t, e, t, panel, tc);
17326             }
17327         };
17328     },
17329
17330     
17331     afterRender : function(){
17332         if(this.floating && !this.hidden){
17333             this.el.show();
17334         }
17335         if(this.title){
17336             this.setTitle(this.title);
17337         }
17338         Ext.Panel.superclass.afterRender.call(this); 
17339         if (this.collapsed) {
17340             this.collapsed = false;
17341             this.collapse(false);
17342         }
17343         this.initEvents();
17344     },
17345
17346     
17347     getKeyMap : function(){
17348         if(!this.keyMap){
17349             this.keyMap = new Ext.KeyMap(this.el, this.keys);
17350         }
17351         return this.keyMap;
17352     },
17353
17354     
17355     initEvents : function(){
17356         if(this.keys){
17357             this.getKeyMap();
17358         }
17359         if(this.draggable){
17360             this.initDraggable();
17361         }
17362         if(this.toolbars.length > 0){
17363             Ext.each(this.toolbars, function(tb){
17364                 tb.doLayout();
17365                 tb.on({
17366                     scope: this,
17367                     afterlayout: this.syncHeight,
17368                     remove: this.syncHeight
17369                 });
17370             }, this);
17371             this.syncHeight();
17372         }
17373
17374     },
17375
17376     
17377     initDraggable : function(){
17378         
17379         this.dd = new Ext.Panel.DD(this, Ext.isBoolean(this.draggable) ? null : this.draggable);
17380     },
17381
17382     
17383     beforeEffect : function(anim){
17384         if(this.floating){
17385             this.el.beforeAction();
17386         }
17387         if(anim !== false){
17388             this.el.addClass('x-panel-animated');
17389         }
17390     },
17391
17392     
17393     afterEffect : function(anim){
17394         this.syncShadow();
17395         this.el.removeClass('x-panel-animated');
17396     },
17397
17398     
17399     createEffect : function(a, cb, scope){
17400         var o = {
17401             scope:scope,
17402             block:true
17403         };
17404         if(a === true){
17405             o.callback = cb;
17406             return o;
17407         }else if(!a.callback){
17408             o.callback = cb;
17409         }else { 
17410             o.callback = function(){
17411                 cb.call(scope);
17412                 Ext.callback(a.callback, a.scope);
17413             };
17414         }
17415         return Ext.applyIf(o, a);
17416     },
17417
17418     
17419     collapse : function(animate){
17420         if(this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforecollapse', this, animate) === false){
17421             return;
17422         }
17423         var doAnim = animate === true || (animate !== false && this.animCollapse);
17424         this.beforeEffect(doAnim);
17425         this.onCollapse(doAnim, animate);
17426         return this;
17427     },
17428
17429     
17430     onCollapse : function(doAnim, animArg){
17431         if(doAnim){
17432             this[this.collapseEl].slideOut(this.slideAnchor,
17433                     Ext.apply(this.createEffect(animArg||true, this.afterCollapse, this),
17434                         this.collapseDefaults));
17435         }else{
17436             this[this.collapseEl].hide(this.hideMode);
17437             this.afterCollapse(false);
17438         }
17439     },
17440
17441     
17442     afterCollapse : function(anim){
17443         this.collapsed = true;
17444         this.el.addClass(this.collapsedCls);
17445         if(anim !== false){
17446             this[this.collapseEl].hide(this.hideMode);
17447         }
17448         this.afterEffect(anim);
17449
17450         
17451         this.cascade(function(c) {
17452             if (c.lastSize) {
17453                 c.lastSize = { width: undefined, height: undefined };
17454             }
17455         });
17456         this.fireEvent('collapse', this);
17457     },
17458
17459     
17460     expand : function(animate){
17461         if(!this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforeexpand', this, animate) === false){
17462             return;
17463         }
17464         var doAnim = animate === true || (animate !== false && this.animCollapse);
17465         this.el.removeClass(this.collapsedCls);
17466         this.beforeEffect(doAnim);
17467         this.onExpand(doAnim, animate);
17468         return this;
17469     },
17470
17471     
17472     onExpand : function(doAnim, animArg){
17473         if(doAnim){
17474             this[this.collapseEl].slideIn(this.slideAnchor,
17475                     Ext.apply(this.createEffect(animArg||true, this.afterExpand, this),
17476                         this.expandDefaults));
17477         }else{
17478             this[this.collapseEl].show(this.hideMode);
17479             this.afterExpand(false);
17480         }
17481     },
17482
17483     
17484     afterExpand : function(anim){
17485         this.collapsed = false;
17486         if(anim !== false){
17487             this[this.collapseEl].show(this.hideMode);
17488         }
17489         this.afterEffect(anim);
17490         if (this.deferLayout) {
17491             delete this.deferLayout;
17492             this.doLayout(true);
17493         }
17494         this.fireEvent('expand', this);
17495     },
17496
17497     
17498     toggleCollapse : function(animate){
17499         this[this.collapsed ? 'expand' : 'collapse'](animate);
17500         return this;
17501     },
17502
17503     
17504     onDisable : function(){
17505         if(this.rendered && this.maskDisabled){
17506             this.el.mask();
17507         }
17508         Ext.Panel.superclass.onDisable.call(this);
17509     },
17510
17511     
17512     onEnable : function(){
17513         if(this.rendered && this.maskDisabled){
17514             this.el.unmask();
17515         }
17516         Ext.Panel.superclass.onEnable.call(this);
17517     },
17518
17519     
17520     onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
17521         var w = adjWidth,
17522             h = adjHeight;
17523
17524         if(Ext.isDefined(w) || Ext.isDefined(h)){
17525             if(!this.collapsed){
17526                 
17527                 
17528                 
17529
17530                 if(Ext.isNumber(w)){
17531                     this.body.setWidth(w = this.adjustBodyWidth(w - this.getFrameWidth()));
17532                 } else if (w == 'auto') {
17533                     w = this.body.setWidth('auto').dom.offsetWidth;
17534                 } else {
17535                     w = this.body.dom.offsetWidth;
17536                 }
17537
17538                 if(this.tbar){
17539                     this.tbar.setWidth(w);
17540                     if(this.topToolbar){
17541                         this.topToolbar.setSize(w);
17542                     }
17543                 }
17544                 if(this.bbar){
17545                     this.bbar.setWidth(w);
17546                     if(this.bottomToolbar){
17547                         this.bottomToolbar.setSize(w);
17548                         
17549                         if (Ext.isIE) {
17550                             this.bbar.setStyle('position', 'static');
17551                             this.bbar.setStyle('position', '');
17552                         }
17553                     }
17554                 }
17555                 if(this.footer){
17556                     this.footer.setWidth(w);
17557                     if(this.fbar){
17558                         this.fbar.setSize(Ext.isIE ? (w - this.footer.getFrameWidth('lr')) : 'auto');
17559                     }
17560                 }
17561
17562                 
17563                 if(Ext.isNumber(h)){
17564                     h = Math.max(0, h - this.getFrameHeight());
17565                     
17566                     this.body.setHeight(h);
17567                 }else if(h == 'auto'){
17568                     this.body.setHeight(h);
17569                 }
17570
17571                 if(this.disabled && this.el._mask){
17572                     this.el._mask.setSize(this.el.dom.clientWidth, this.el.getHeight());
17573                 }
17574             }else{
17575                 
17576                 this.queuedBodySize = {width: w, height: h};
17577                 if(!this.queuedExpand && this.allowQueuedExpand !== false){
17578                     this.queuedExpand = true;
17579                     this.on('expand', function(){
17580                         delete this.queuedExpand;
17581                         this.onResize(this.queuedBodySize.width, this.queuedBodySize.height);
17582                     }, this, {single:true});
17583                 }
17584             }
17585             this.onBodyResize(w, h);
17586         }
17587         this.syncShadow();
17588         Ext.Panel.superclass.onResize.call(this, adjWidth, adjHeight, rawWidth, rawHeight);
17589
17590     },
17591
17592     
17593     onBodyResize: function(w, h){
17594         this.fireEvent('bodyresize', this, w, h);
17595     },
17596
17597     
17598     getToolbarHeight: function(){
17599         var h = 0;
17600         if(this.rendered){
17601             Ext.each(this.toolbars, function(tb){
17602                 h += tb.getHeight();
17603             }, this);
17604         }
17605         return h;
17606     },
17607
17608     
17609     adjustBodyHeight : function(h){
17610         return h;
17611     },
17612
17613     
17614     adjustBodyWidth : function(w){
17615         return w;
17616     },
17617
17618     
17619     onPosition : function(){
17620         this.syncShadow();
17621     },
17622
17623     
17624     getFrameWidth : function(){
17625         var w = this.el.getFrameWidth('lr') + this.bwrap.getFrameWidth('lr');
17626
17627         if(this.frame){
17628             var l = this.bwrap.dom.firstChild;
17629             w += (Ext.fly(l).getFrameWidth('l') + Ext.fly(l.firstChild).getFrameWidth('r'));
17630             w += this.mc.getFrameWidth('lr');
17631         }
17632         return w;
17633     },
17634
17635     
17636     getFrameHeight : function() {
17637         var h  = this.el.getFrameWidth('tb') + this.bwrap.getFrameWidth('tb');
17638         h += (this.tbar ? this.tbar.getHeight() : 0) +
17639              (this.bbar ? this.bbar.getHeight() : 0);
17640
17641         if(this.frame){
17642             h += this.el.dom.firstChild.offsetHeight + this.ft.dom.offsetHeight + this.mc.getFrameWidth('tb');
17643         }else{
17644             h += (this.header ? this.header.getHeight() : 0) +
17645                 (this.footer ? this.footer.getHeight() : 0);
17646         }
17647         return h;
17648     },
17649
17650     
17651     getInnerWidth : function(){
17652         return this.getSize().width - this.getFrameWidth();
17653     },
17654
17655     
17656     getInnerHeight : function(){
17657         return this.body.getHeight();
17658         
17659     },
17660
17661     
17662     syncShadow : function(){
17663         if(this.floating){
17664             this.el.sync(true);
17665         }
17666     },
17667
17668     
17669     getLayoutTarget : function(){
17670         return this.body;
17671     },
17672
17673     
17674     getContentTarget : function(){
17675         return this.body;
17676     },
17677
17678     
17679     setTitle : function(title, iconCls){
17680         this.title = title;
17681         if(this.header && this.headerAsText){
17682             this.header.child('span').update(title);
17683         }
17684         if(iconCls){
17685             this.setIconClass(iconCls);
17686         }
17687         this.fireEvent('titlechange', this, title);
17688         return this;
17689     },
17690
17691     
17692     getUpdater : function(){
17693         return this.body.getUpdater();
17694     },
17695
17696      
17697     load : function(){
17698         var um = this.body.getUpdater();
17699         um.update.apply(um, arguments);
17700         return this;
17701     },
17702
17703     
17704     beforeDestroy : function(){
17705         Ext.Panel.superclass.beforeDestroy.call(this);
17706         if(this.header){
17707             this.header.removeAllListeners();
17708         }
17709         if(this.tools){
17710             for(var k in this.tools){
17711                 Ext.destroy(this.tools[k]);
17712             }
17713         }
17714         if(this.toolbars.length > 0){
17715             Ext.each(this.toolbars, function(tb){
17716                 tb.un('afterlayout', this.syncHeight, this);
17717                 tb.un('remove', this.syncHeight, this);
17718             }, this);
17719         }
17720         if(Ext.isArray(this.buttons)){
17721             while(this.buttons.length) {
17722                 Ext.destroy(this.buttons[0]);
17723             }
17724         }
17725         if(this.rendered){
17726             Ext.destroy(
17727                 this.ft,
17728                 this.header,
17729                 this.footer,
17730                 this.tbar,
17731                 this.bbar,
17732                 this.body,
17733                 this.mc,
17734                 this.bwrap,
17735                 this.dd
17736             );
17737             if (this.fbar) {
17738                 Ext.destroy(
17739                     this.fbar,
17740                     this.fbar.el
17741                 );
17742             }
17743         }
17744         Ext.destroy(this.toolbars);
17745     },
17746
17747     
17748     createClasses : function(){
17749         this.headerCls = this.baseCls + '-header';
17750         this.headerTextCls = this.baseCls + '-header-text';
17751         this.bwrapCls = this.baseCls + '-bwrap';
17752         this.tbarCls = this.baseCls + '-tbar';
17753         this.bodyCls = this.baseCls + '-body';
17754         this.bbarCls = this.baseCls + '-bbar';
17755         this.footerCls = this.baseCls + '-footer';
17756     },
17757
17758     
17759     createGhost : function(cls, useShim, appendTo){
17760         var el = document.createElement('div');
17761         el.className = 'x-panel-ghost ' + (cls ? cls : '');
17762         if(this.header){
17763             el.appendChild(this.el.dom.firstChild.cloneNode(true));
17764         }
17765         Ext.fly(el.appendChild(document.createElement('ul'))).setHeight(this.bwrap.getHeight());
17766         el.style.width = this.el.dom.offsetWidth + 'px';;
17767         if(!appendTo){
17768             this.container.dom.appendChild(el);
17769         }else{
17770             Ext.getDom(appendTo).appendChild(el);
17771         }
17772         if(useShim !== false && this.el.useShim !== false){
17773             var layer = new Ext.Layer({shadow:false, useDisplay:true, constrain:false}, el);
17774             layer.show();
17775             return layer;
17776         }else{
17777             return new Ext.Element(el);
17778         }
17779     },
17780
17781     
17782     doAutoLoad : function(){
17783         var u = this.body.getUpdater();
17784         if(this.renderer){
17785             u.setRenderer(this.renderer);
17786         }
17787         u.update(Ext.isObject(this.autoLoad) ? this.autoLoad : {url: this.autoLoad});
17788     },
17789
17790     
17791     getTool : function(id) {
17792         return this.tools[id];
17793     }
17794
17795
17796 });
17797 Ext.reg('panel', Ext.Panel);
17798
17799 Ext.Editor = function(field, config){
17800     if(field.field){
17801         this.field = Ext.create(field.field, 'textfield');
17802         config = Ext.apply({}, field); 
17803         delete config.field;
17804     }else{
17805         this.field = field;
17806     }
17807     Ext.Editor.superclass.constructor.call(this, config);
17808 };
17809
17810 Ext.extend(Ext.Editor, Ext.Component, {
17811     
17812     
17813     allowBlur: true,
17814     
17815     
17816     
17817     
17818     
17819     value : "",
17820     
17821     alignment: "c-c?",
17822     
17823     offsets: [0, 0],
17824     
17825     shadow : "frame",
17826     
17827     constrain : false,
17828     
17829     swallowKeys : true,
17830     
17831     completeOnEnter : true,
17832     
17833     cancelOnEsc : true,
17834     
17835     updateEl : false,
17836
17837     initComponent : function(){
17838         Ext.Editor.superclass.initComponent.call(this);
17839         this.addEvents(
17840             
17841             "beforestartedit",
17842             
17843             "startedit",
17844             
17845             "beforecomplete",
17846             
17847             "complete",
17848             
17849             "canceledit",
17850             
17851             "specialkey"
17852         );
17853     },
17854
17855     
17856     onRender : function(ct, position){
17857         this.el = new Ext.Layer({
17858             shadow: this.shadow,
17859             cls: "x-editor",
17860             parentEl : ct,
17861             shim : this.shim,
17862             shadowOffset: this.shadowOffset || 4,
17863             id: this.id,
17864             constrain: this.constrain
17865         });
17866         if(this.zIndex){
17867             this.el.setZIndex(this.zIndex);
17868         }
17869         this.el.setStyle("overflow", Ext.isGecko ? "auto" : "hidden");
17870         if(this.field.msgTarget != 'title'){
17871             this.field.msgTarget = 'qtip';
17872         }
17873         this.field.inEditor = true;
17874         this.mon(this.field, {
17875             scope: this,
17876             blur: this.onBlur,
17877             specialkey: this.onSpecialKey
17878         });
17879         if(this.field.grow){
17880             this.mon(this.field, "autosize", this.el.sync,  this.el, {delay:1});
17881         }
17882         this.field.render(this.el).show();
17883         this.field.getEl().dom.name = '';
17884         if(this.swallowKeys){
17885             this.field.el.swallowEvent([
17886                 'keypress', 
17887                 'keydown'   
17888             ]);
17889         }
17890     },
17891
17892     
17893     onSpecialKey : function(field, e){
17894         var key = e.getKey(),
17895             complete = this.completeOnEnter && key == e.ENTER,
17896             cancel = this.cancelOnEsc && key == e.ESC;
17897         if(complete || cancel){
17898             e.stopEvent();
17899             if(complete){
17900                 this.completeEdit();
17901             }else{
17902                 this.cancelEdit();
17903             }
17904             if(field.triggerBlur){
17905                 field.triggerBlur();
17906             }
17907         }
17908         this.fireEvent('specialkey', field, e);
17909     },
17910
17911     
17912     startEdit : function(el, value){
17913         if(this.editing){
17914             this.completeEdit();
17915         }
17916         this.boundEl = Ext.get(el);
17917         var v = value !== undefined ? value : this.boundEl.dom.innerHTML;
17918         if(!this.rendered){
17919             this.render(this.parentEl || document.body);
17920         }
17921         if(this.fireEvent("beforestartedit", this, this.boundEl, v) !== false){
17922             this.startValue = v;
17923             this.field.reset();
17924             this.field.setValue(v);
17925             this.realign(true);
17926             this.editing = true;
17927             this.show();
17928         }
17929     },
17930
17931     
17932     doAutoSize : function(){
17933         if(this.autoSize){
17934             var sz = this.boundEl.getSize(),
17935                 fs = this.field.getSize();
17936
17937             switch(this.autoSize){
17938                 case "width":
17939                     this.setSize(sz.width, fs.height);
17940                     break;
17941                 case "height":
17942                     this.setSize(fs.width, sz.height);
17943                     break;
17944                 case "none":
17945                     this.setSize(fs.width, fs.height);
17946                     break;
17947                 default:
17948                     this.setSize(sz.width, sz.height);
17949             }
17950         }
17951     },
17952
17953     
17954     setSize : function(w, h){
17955         delete this.field.lastSize;
17956         this.field.setSize(w, h);
17957         if(this.el){
17958             
17959             if(Ext.isGecko2 || Ext.isOpera || (Ext.isIE7 && Ext.isStrict)){
17960                 
17961                 this.el.setSize(w, h);
17962             }
17963             this.el.sync();
17964         }
17965     },
17966
17967     
17968     realign : function(autoSize){
17969         if(autoSize === true){
17970             this.doAutoSize();
17971         }
17972         this.el.alignTo(this.boundEl, this.alignment, this.offsets);
17973     },
17974
17975     
17976     completeEdit : function(remainVisible){
17977         if(!this.editing){
17978             return;
17979         }
17980         
17981         if (this.field.assertValue) {
17982             this.field.assertValue();
17983         }
17984         var v = this.getValue();
17985         if(!this.field.isValid()){
17986             if(this.revertInvalid !== false){
17987                 this.cancelEdit(remainVisible);
17988             }
17989             return;
17990         }
17991         if(String(v) === String(this.startValue) && this.ignoreNoChange){
17992             this.hideEdit(remainVisible);
17993             return;
17994         }
17995         if(this.fireEvent("beforecomplete", this, v, this.startValue) !== false){
17996             v = this.getValue();
17997             if(this.updateEl && this.boundEl){
17998                 this.boundEl.update(v);
17999             }
18000             this.hideEdit(remainVisible);
18001             this.fireEvent("complete", this, v, this.startValue);
18002         }
18003     },
18004
18005     
18006     onShow : function(){
18007         this.el.show();
18008         if(this.hideEl !== false){
18009             this.boundEl.hide();
18010         }
18011         this.field.show().focus(false, true);
18012         this.fireEvent("startedit", this.boundEl, this.startValue);
18013     },
18014
18015     
18016     cancelEdit : function(remainVisible){
18017         if(this.editing){
18018             var v = this.getValue();
18019             this.setValue(this.startValue);
18020             this.hideEdit(remainVisible);
18021             this.fireEvent("canceledit", this, v, this.startValue);
18022         }
18023     },
18024
18025     
18026     hideEdit: function(remainVisible){
18027         if(remainVisible !== true){
18028             this.editing = false;
18029             this.hide();
18030         }
18031     },
18032
18033     
18034     onBlur : function(){
18035         
18036         if(this.allowBlur === true && this.editing && this.selectSameEditor !== true){
18037             this.completeEdit();
18038         }
18039     },
18040
18041     
18042     onHide : function(){
18043         if(this.editing){
18044             this.completeEdit();
18045             return;
18046         }
18047         this.field.blur();
18048         if(this.field.collapse){
18049             this.field.collapse();
18050         }
18051         this.el.hide();
18052         if(this.hideEl !== false){
18053             this.boundEl.show();
18054         }
18055     },
18056
18057     
18058     setValue : function(v){
18059         this.field.setValue(v);
18060     },
18061
18062     
18063     getValue : function(){
18064         return this.field.getValue();
18065     },
18066
18067     beforeDestroy : function(){
18068         Ext.destroyMembers(this, 'field');
18069
18070         delete this.parentEl;
18071         delete this.boundEl;
18072     }
18073 });
18074 Ext.reg('editor', Ext.Editor);
18075
18076 Ext.ColorPalette = Ext.extend(Ext.Component, {
18077         
18078     
18079     itemCls : 'x-color-palette',
18080     
18081     value : null,
18082     
18083     clickEvent :'click',
18084     
18085     ctype : 'Ext.ColorPalette',
18086
18087     
18088     allowReselect : false,
18089
18090     
18091     colors : [
18092         '000000', '993300', '333300', '003300', '003366', '000080', '333399', '333333',
18093         '800000', 'FF6600', '808000', '008000', '008080', '0000FF', '666699', '808080',
18094         'FF0000', 'FF9900', '99CC00', '339966', '33CCCC', '3366FF', '800080', '969696',
18095         'FF00FF', 'FFCC00', 'FFFF00', '00FF00', '00FFFF', '00CCFF', '993366', 'C0C0C0',
18096         'FF99CC', 'FFCC99', 'FFFF99', 'CCFFCC', 'CCFFFF', '99CCFF', 'CC99FF', 'FFFFFF'
18097     ],
18098
18099     
18100     
18101     
18102     
18103     initComponent : function(){
18104         Ext.ColorPalette.superclass.initComponent.call(this);
18105         this.addEvents(
18106             
18107             'select'
18108         );
18109
18110         if(this.handler){
18111             this.on('select', this.handler, this.scope, true);
18112         }    
18113     },
18114
18115     
18116     onRender : function(container, position){
18117         this.autoEl = {
18118             tag: 'div',
18119             cls: this.itemCls
18120         };
18121         Ext.ColorPalette.superclass.onRender.call(this, container, position);
18122         var t = this.tpl || new Ext.XTemplate(
18123             '<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on">&#160;</span></em></a></tpl>'
18124         );
18125         t.overwrite(this.el, this.colors);
18126         this.mon(this.el, this.clickEvent, this.handleClick, this, {delegate: 'a'});
18127         if(this.clickEvent != 'click'){
18128                 this.mon(this.el, 'click', Ext.emptyFn, this, {delegate: 'a', preventDefault: true});
18129         }
18130     },
18131
18132     
18133     afterRender : function(){
18134         Ext.ColorPalette.superclass.afterRender.call(this);
18135         if(this.value){
18136             var s = this.value;
18137             this.value = null;
18138             this.select(s, true);
18139         }
18140     },
18141
18142     
18143     handleClick : function(e, t){
18144         e.preventDefault();
18145         if(!this.disabled){
18146             var c = t.className.match(/(?:^|\s)color-(.{6})(?:\s|$)/)[1];
18147             this.select(c.toUpperCase());
18148         }
18149     },
18150
18151     
18152     select : function(color, suppressEvent){
18153         color = color.replace('#', '');
18154         if(color != this.value || this.allowReselect){
18155             var el = this.el;
18156             if(this.value){
18157                 el.child('a.color-'+this.value).removeClass('x-color-palette-sel');
18158             }
18159             el.child('a.color-'+color).addClass('x-color-palette-sel');
18160             this.value = color;
18161             if(suppressEvent !== true){
18162                 this.fireEvent('select', this, color);
18163             }
18164         }
18165     }
18166
18167     
18168 });
18169 Ext.reg('colorpalette', Ext.ColorPalette);
18170 Ext.DatePicker = Ext.extend(Ext.BoxComponent, {
18171     
18172     todayText : 'Today',
18173     
18174     okText : '&#160;OK&#160;',
18175     
18176     cancelText : 'Cancel',
18177     
18178     
18179     
18180     todayTip : '{0} (Spacebar)',
18181     
18182     minText : 'This date is before the minimum date',
18183     
18184     maxText : 'This date is after the maximum date',
18185     
18186     format : 'm/d/y',
18187     
18188     disabledDaysText : 'Disabled',
18189     
18190     disabledDatesText : 'Disabled',
18191     
18192     monthNames : Date.monthNames,
18193     
18194     dayNames : Date.dayNames,
18195     
18196     nextText : 'Next Month (Control+Right)',
18197     
18198     prevText : 'Previous Month (Control+Left)',
18199     
18200     monthYearText : 'Choose a month (Control+Up/Down to move years)',
18201     
18202     startDay : 0,
18203     
18204     showToday : true,
18205     
18206     
18207     
18208     
18209     
18210
18211     
18212     
18213     focusOnSelect: true,
18214
18215     
18216     
18217     initHour: 12, 
18218
18219     
18220     initComponent : function(){
18221         Ext.DatePicker.superclass.initComponent.call(this);
18222
18223         this.value = this.value ?
18224                  this.value.clearTime(true) : new Date().clearTime();
18225
18226         this.addEvents(
18227             
18228             'select'
18229         );
18230
18231         if(this.handler){
18232             this.on('select', this.handler,  this.scope || this);
18233         }
18234
18235         this.initDisabledDays();
18236     },
18237
18238     
18239     initDisabledDays : function(){
18240         if(!this.disabledDatesRE && this.disabledDates){
18241             var dd = this.disabledDates,
18242                 len = dd.length - 1,
18243                 re = '(?:';
18244
18245             Ext.each(dd, function(d, i){
18246                 re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];
18247                 if(i != len){
18248                     re += '|';
18249                 }
18250             }, this);
18251             this.disabledDatesRE = new RegExp(re + ')');
18252         }
18253     },
18254
18255     
18256     setDisabledDates : function(dd){
18257         if(Ext.isArray(dd)){
18258             this.disabledDates = dd;
18259             this.disabledDatesRE = null;
18260         }else{
18261             this.disabledDatesRE = dd;
18262         }
18263         this.initDisabledDays();
18264         this.update(this.value, true);
18265     },
18266
18267     
18268     setDisabledDays : function(dd){
18269         this.disabledDays = dd;
18270         this.update(this.value, true);
18271     },
18272
18273     
18274     setMinDate : function(dt){
18275         this.minDate = dt;
18276         this.update(this.value, true);
18277     },
18278
18279     
18280     setMaxDate : function(dt){
18281         this.maxDate = dt;
18282         this.update(this.value, true);
18283     },
18284
18285     
18286     setValue : function(value){
18287         this.value = value.clearTime(true);
18288         this.update(this.value);
18289     },
18290
18291     
18292     getValue : function(){
18293         return this.value;
18294     },
18295
18296     
18297     focus : function(){
18298         this.update(this.activeDate);
18299     },
18300
18301     
18302     onEnable: function(initial){
18303         Ext.DatePicker.superclass.onEnable.call(this);
18304         this.doDisabled(false);
18305         this.update(initial ? this.value : this.activeDate);
18306         if(Ext.isIE){
18307             this.el.repaint();
18308         }
18309
18310     },
18311
18312     
18313     onDisable : function(){
18314         Ext.DatePicker.superclass.onDisable.call(this);
18315         this.doDisabled(true);
18316         if(Ext.isIE && !Ext.isIE8){
18317             
18318              Ext.each([].concat(this.textNodes, this.el.query('th span')), function(el){
18319                  Ext.fly(el).repaint();
18320              });
18321         }
18322     },
18323
18324     
18325     doDisabled : function(disabled){
18326         this.keyNav.setDisabled(disabled);
18327         this.prevRepeater.setDisabled(disabled);
18328         this.nextRepeater.setDisabled(disabled);
18329         if(this.showToday){
18330             this.todayKeyListener.setDisabled(disabled);
18331             this.todayBtn.setDisabled(disabled);
18332         }
18333     },
18334
18335     
18336     onRender : function(container, position){
18337         var m = [
18338              '<table cellspacing="0">',
18339                 '<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>',
18340                 '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'],
18341                 dn = this.dayNames,
18342                 i;
18343         for(i = 0; i < 7; i++){
18344             var d = this.startDay+i;
18345             if(d > 6){
18346                 d = d-7;
18347             }
18348             m.push('<th><span>', dn[d].substr(0,1), '</span></th>');
18349         }
18350         m[m.length] = '</tr></thead><tbody><tr>';
18351         for(i = 0; i < 42; i++) {
18352             if(i % 7 === 0 && i !== 0){
18353                 m[m.length] = '</tr><tr>';
18354             }
18355             m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
18356         }
18357         m.push('</tr></tbody></table></td></tr>',
18358                 this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>' : '',
18359                 '</table><div class="x-date-mp"></div>');
18360
18361         var el = document.createElement('div');
18362         el.className = 'x-date-picker';
18363         el.innerHTML = m.join('');
18364
18365         container.dom.insertBefore(el, position);
18366
18367         this.el = Ext.get(el);
18368         this.eventEl = Ext.get(el.firstChild);
18369
18370         this.prevRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-left a'), {
18371             handler: this.showPrevMonth,
18372             scope: this,
18373             preventDefault:true,
18374             stopDefault:true
18375         });
18376
18377         this.nextRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-right a'), {
18378             handler: this.showNextMonth,
18379             scope: this,
18380             preventDefault:true,
18381             stopDefault:true
18382         });
18383
18384         this.monthPicker = this.el.down('div.x-date-mp');
18385         this.monthPicker.enableDisplayMode('block');
18386
18387         this.keyNav = new Ext.KeyNav(this.eventEl, {
18388             'left' : function(e){
18389                 if(e.ctrlKey){
18390                     this.showPrevMonth();
18391                 }else{
18392                     this.update(this.activeDate.add('d', -1));
18393                 }
18394             },
18395
18396             'right' : function(e){
18397                 if(e.ctrlKey){
18398                     this.showNextMonth();
18399                 }else{
18400                     this.update(this.activeDate.add('d', 1));
18401                 }
18402             },
18403
18404             'up' : function(e){
18405                 if(e.ctrlKey){
18406                     this.showNextYear();
18407                 }else{
18408                     this.update(this.activeDate.add('d', -7));
18409                 }
18410             },
18411
18412             'down' : function(e){
18413                 if(e.ctrlKey){
18414                     this.showPrevYear();
18415                 }else{
18416                     this.update(this.activeDate.add('d', 7));
18417                 }
18418             },
18419
18420             'pageUp' : function(e){
18421                 this.showNextMonth();
18422             },
18423
18424             'pageDown' : function(e){
18425                 this.showPrevMonth();
18426             },
18427
18428             'enter' : function(e){
18429                 e.stopPropagation();
18430                 return true;
18431             },
18432
18433             scope : this
18434         });
18435
18436         this.el.unselectable();
18437
18438         this.cells = this.el.select('table.x-date-inner tbody td');
18439         this.textNodes = this.el.query('table.x-date-inner tbody span');
18440
18441         this.mbtn = new Ext.Button({
18442             text: '&#160;',
18443             tooltip: this.monthYearText,
18444             renderTo: this.el.child('td.x-date-middle', true)
18445         });
18446         this.mbtn.el.child('em').addClass('x-btn-arrow');
18447
18448         if(this.showToday){
18449             this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday,  this);
18450             var today = (new Date()).dateFormat(this.format);
18451             this.todayBtn = new Ext.Button({
18452                 renderTo: this.el.child('td.x-date-bottom', true),
18453                 text: String.format(this.todayText, today),
18454                 tooltip: String.format(this.todayTip, today),
18455                 handler: this.selectToday,
18456                 scope: this
18457             });
18458         }
18459         this.mon(this.eventEl, 'mousewheel', this.handleMouseWheel, this);
18460         this.mon(this.eventEl, 'click', this.handleDateClick,  this, {delegate: 'a.x-date-date'});
18461         this.mon(this.mbtn, 'click', this.showMonthPicker, this);
18462         this.onEnable(true);
18463     },
18464
18465     
18466     createMonthPicker : function(){
18467         if(!this.monthPicker.dom.firstChild){
18468             var buf = ['<table border="0" cellspacing="0">'];
18469             for(var i = 0; i < 6; i++){
18470                 buf.push(
18471                     '<tr><td class="x-date-mp-month"><a href="#">', Date.getShortMonthName(i), '</a></td>',
18472                     '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', Date.getShortMonthName(i + 6), '</a></td>',
18473                     i === 0 ?
18474                     '<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>' :
18475                     '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'
18476                 );
18477             }
18478             buf.push(
18479                 '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',
18480                     this.okText,
18481                     '</button><button type="button" class="x-date-mp-cancel">',
18482                     this.cancelText,
18483                     '</button></td></tr>',
18484                 '</table>'
18485             );
18486             this.monthPicker.update(buf.join(''));
18487
18488             this.mon(this.monthPicker, 'click', this.onMonthClick, this);
18489             this.mon(this.monthPicker, 'dblclick', this.onMonthDblClick, this);
18490
18491             this.mpMonths = this.monthPicker.select('td.x-date-mp-month');
18492             this.mpYears = this.monthPicker.select('td.x-date-mp-year');
18493
18494             this.mpMonths.each(function(m, a, i){
18495                 i += 1;
18496                 if((i%2) === 0){
18497                     m.dom.xmonth = 5 + Math.round(i * 0.5);
18498                 }else{
18499                     m.dom.xmonth = Math.round((i-1) * 0.5);
18500                 }
18501             });
18502         }
18503     },
18504
18505     
18506     showMonthPicker : function(){
18507         if(!this.disabled){
18508             this.createMonthPicker();
18509             var size = this.el.getSize();
18510             this.monthPicker.setSize(size);
18511             this.monthPicker.child('table').setSize(size);
18512
18513             this.mpSelMonth = (this.activeDate || this.value).getMonth();
18514             this.updateMPMonth(this.mpSelMonth);
18515             this.mpSelYear = (this.activeDate || this.value).getFullYear();
18516             this.updateMPYear(this.mpSelYear);
18517
18518             this.monthPicker.slideIn('t', {duration:0.2});
18519         }
18520     },
18521
18522     
18523     updateMPYear : function(y){
18524         this.mpyear = y;
18525         var ys = this.mpYears.elements;
18526         for(var i = 1; i <= 10; i++){
18527             var td = ys[i-1], y2;
18528             if((i%2) === 0){
18529                 y2 = y + Math.round(i * 0.5);
18530                 td.firstChild.innerHTML = y2;
18531                 td.xyear = y2;
18532             }else{
18533                 y2 = y - (5-Math.round(i * 0.5));
18534                 td.firstChild.innerHTML = y2;
18535                 td.xyear = y2;
18536             }
18537             this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');
18538         }
18539     },
18540
18541     
18542     updateMPMonth : function(sm){
18543         this.mpMonths.each(function(m, a, i){
18544             m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');
18545         });
18546     },
18547
18548     
18549     selectMPMonth : function(m){
18550
18551     },
18552
18553     
18554     onMonthClick : function(e, t){
18555         e.stopEvent();
18556         var el = new Ext.Element(t), pn;
18557         if(el.is('button.x-date-mp-cancel')){
18558             this.hideMonthPicker();
18559         }
18560         else if(el.is('button.x-date-mp-ok')){
18561             var d = new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate());
18562             if(d.getMonth() != this.mpSelMonth){
18563                 
18564                 d = new Date(this.mpSelYear, this.mpSelMonth, 1).getLastDateOfMonth();
18565             }
18566             this.update(d);
18567             this.hideMonthPicker();
18568         }
18569         else if((pn = el.up('td.x-date-mp-month', 2))){
18570             this.mpMonths.removeClass('x-date-mp-sel');
18571             pn.addClass('x-date-mp-sel');
18572             this.mpSelMonth = pn.dom.xmonth;
18573         }
18574         else if((pn = el.up('td.x-date-mp-year', 2))){
18575             this.mpYears.removeClass('x-date-mp-sel');
18576             pn.addClass('x-date-mp-sel');
18577             this.mpSelYear = pn.dom.xyear;
18578         }
18579         else if(el.is('a.x-date-mp-prev')){
18580             this.updateMPYear(this.mpyear-10);
18581         }
18582         else if(el.is('a.x-date-mp-next')){
18583             this.updateMPYear(this.mpyear+10);
18584         }
18585     },
18586
18587     
18588     onMonthDblClick : function(e, t){
18589         e.stopEvent();
18590         var el = new Ext.Element(t), pn;
18591         if((pn = el.up('td.x-date-mp-month', 2))){
18592             this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));
18593             this.hideMonthPicker();
18594         }
18595         else if((pn = el.up('td.x-date-mp-year', 2))){
18596             this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
18597             this.hideMonthPicker();
18598         }
18599     },
18600
18601     
18602     hideMonthPicker : function(disableAnim){
18603         if(this.monthPicker){
18604             if(disableAnim === true){
18605                 this.monthPicker.hide();
18606             }else{
18607                 this.monthPicker.slideOut('t', {duration:0.2});
18608             }
18609         }
18610     },
18611
18612     
18613     showPrevMonth : function(e){
18614         this.update(this.activeDate.add('mo', -1));
18615     },
18616
18617     
18618     showNextMonth : function(e){
18619         this.update(this.activeDate.add('mo', 1));
18620     },
18621
18622     
18623     showPrevYear : function(){
18624         this.update(this.activeDate.add('y', -1));
18625     },
18626
18627     
18628     showNextYear : function(){
18629         this.update(this.activeDate.add('y', 1));
18630     },
18631
18632     
18633     handleMouseWheel : function(e){
18634         e.stopEvent();
18635         if(!this.disabled){
18636             var delta = e.getWheelDelta();
18637             if(delta > 0){
18638                 this.showPrevMonth();
18639             } else if(delta < 0){
18640                 this.showNextMonth();
18641             }
18642         }
18643     },
18644
18645     
18646     handleDateClick : function(e, t){
18647         e.stopEvent();
18648         if(!this.disabled && t.dateValue && !Ext.fly(t.parentNode).hasClass('x-date-disabled')){
18649             this.cancelFocus = this.focusOnSelect === false;
18650             this.setValue(new Date(t.dateValue));
18651             delete this.cancelFocus;
18652             this.fireEvent('select', this, this.value);
18653         }
18654     },
18655
18656     
18657     selectToday : function(){
18658         if(this.todayBtn && !this.todayBtn.disabled){
18659             this.setValue(new Date().clearTime());
18660             this.fireEvent('select', this, this.value);
18661         }
18662     },
18663
18664     
18665     update : function(date, forceRefresh){
18666         if(this.rendered){
18667             var vd = this.activeDate, vis = this.isVisible();
18668             this.activeDate = date;
18669             if(!forceRefresh && vd && this.el){
18670                 var t = date.getTime();
18671                 if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
18672                     this.cells.removeClass('x-date-selected');
18673                     this.cells.each(function(c){
18674                        if(c.dom.firstChild.dateValue == t){
18675                            c.addClass('x-date-selected');
18676                            if(vis && !this.cancelFocus){
18677                                Ext.fly(c.dom.firstChild).focus(50);
18678                            }
18679                            return false;
18680                        }
18681                     }, this);
18682                     return;
18683                 }
18684             }
18685             var days = date.getDaysInMonth(),
18686                 firstOfMonth = date.getFirstDateOfMonth(),
18687                 startingPos = firstOfMonth.getDay()-this.startDay;
18688
18689             if(startingPos < 0){
18690                 startingPos += 7;
18691             }
18692             days += startingPos;
18693
18694             var pm = date.add('mo', -1),
18695                 prevStart = pm.getDaysInMonth()-startingPos,
18696                 cells = this.cells.elements,
18697                 textEls = this.textNodes,
18698                 
18699                 d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart, this.initHour)),
18700                 today = new Date().clearTime().getTime(),
18701                 sel = date.clearTime(true).getTime(),
18702                 min = this.minDate ? this.minDate.clearTime(true) : Number.NEGATIVE_INFINITY,
18703                 max = this.maxDate ? this.maxDate.clearTime(true) : Number.POSITIVE_INFINITY,
18704                 ddMatch = this.disabledDatesRE,
18705                 ddText = this.disabledDatesText,
18706                 ddays = this.disabledDays ? this.disabledDays.join('') : false,
18707                 ddaysText = this.disabledDaysText,
18708                 format = this.format;
18709
18710             if(this.showToday){
18711                 var td = new Date().clearTime(),
18712                     disable = (td < min || td > max ||
18713                     (ddMatch && format && ddMatch.test(td.dateFormat(format))) ||
18714                     (ddays && ddays.indexOf(td.getDay()) != -1));
18715
18716                 if(!this.disabled){
18717                     this.todayBtn.setDisabled(disable);
18718                     this.todayKeyListener[disable ? 'disable' : 'enable']();
18719                 }
18720             }
18721
18722             var setCellClass = function(cal, cell){
18723                 cell.title = '';
18724                 var t = d.clearTime(true).getTime();
18725                 cell.firstChild.dateValue = t;
18726                 if(t == today){
18727                     cell.className += ' x-date-today';
18728                     cell.title = cal.todayText;
18729                 }
18730                 if(t == sel){
18731                     cell.className += ' x-date-selected';
18732                     if(vis){
18733                         Ext.fly(cell.firstChild).focus(50);
18734                     }
18735                 }
18736                 
18737                 if(t < min) {
18738                     cell.className = ' x-date-disabled';
18739                     cell.title = cal.minText;
18740                     return;
18741                 }
18742                 if(t > max) {
18743                     cell.className = ' x-date-disabled';
18744                     cell.title = cal.maxText;
18745                     return;
18746                 }
18747                 if(ddays){
18748                     if(ddays.indexOf(d.getDay()) != -1){
18749                         cell.title = ddaysText;
18750                         cell.className = ' x-date-disabled';
18751                     }
18752                 }
18753                 if(ddMatch && format){
18754                     var fvalue = d.dateFormat(format);
18755                     if(ddMatch.test(fvalue)){
18756                         cell.title = ddText.replace('%0', fvalue);
18757                         cell.className = ' x-date-disabled';
18758                     }
18759                 }
18760             };
18761
18762             var i = 0;
18763             for(; i < startingPos; i++) {
18764                 textEls[i].innerHTML = (++prevStart);
18765                 d.setDate(d.getDate()+1);
18766                 cells[i].className = 'x-date-prevday';
18767                 setCellClass(this, cells[i]);
18768             }
18769             for(; i < days; i++){
18770                 var intDay = i - startingPos + 1;
18771                 textEls[i].innerHTML = (intDay);
18772                 d.setDate(d.getDate()+1);
18773                 cells[i].className = 'x-date-active';
18774                 setCellClass(this, cells[i]);
18775             }
18776             var extraDays = 0;
18777             for(; i < 42; i++) {
18778                  textEls[i].innerHTML = (++extraDays);
18779                  d.setDate(d.getDate()+1);
18780                  cells[i].className = 'x-date-nextday';
18781                  setCellClass(this, cells[i]);
18782             }
18783
18784             this.mbtn.setText(this.monthNames[date.getMonth()] + ' ' + date.getFullYear());
18785
18786             if(!this.internalRender){
18787                 var main = this.el.dom.firstChild,
18788                     w = main.offsetWidth;
18789                 this.el.setWidth(w + this.el.getBorderWidth('lr'));
18790                 Ext.fly(main).setWidth(w);
18791                 this.internalRender = true;
18792                 
18793                 
18794                 
18795                 if(Ext.isOpera && !this.secondPass){
18796                     main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + 'px';
18797                     this.secondPass = true;
18798                     this.update.defer(10, this, [date]);
18799                 }
18800             }
18801         }
18802     },
18803
18804     
18805     beforeDestroy : function() {
18806         if(this.rendered){
18807             Ext.destroy(
18808                 this.keyNav,
18809                 this.monthPicker,
18810                 this.eventEl,
18811                 this.mbtn,
18812                 this.nextRepeater,
18813                 this.prevRepeater,
18814                 this.cells.el,
18815                 this.todayBtn
18816             );
18817             delete this.textNodes;
18818             delete this.cells.elements;
18819         }
18820     }
18821
18822     
18823 });
18824
18825 Ext.reg('datepicker', Ext.DatePicker);
18826
18827 Ext.LoadMask = function(el, config){
18828     this.el = Ext.get(el);
18829     Ext.apply(this, config);
18830     if(this.store){
18831         this.store.on({
18832             scope: this,
18833             beforeload: this.onBeforeLoad,
18834             load: this.onLoad,
18835             exception: this.onLoad
18836         });
18837         this.removeMask = Ext.value(this.removeMask, false);
18838     }else{
18839         var um = this.el.getUpdater();
18840         um.showLoadIndicator = false; 
18841         um.on({
18842             scope: this,
18843             beforeupdate: this.onBeforeLoad,
18844             update: this.onLoad,
18845             failure: this.onLoad
18846         });
18847         this.removeMask = Ext.value(this.removeMask, true);
18848     }
18849 };
18850
18851 Ext.LoadMask.prototype = {
18852     
18853     
18854     
18855     msg : 'Loading...',
18856     
18857     msgCls : 'x-mask-loading',
18858
18859     
18860     disabled: false,
18861
18862     
18863     disable : function(){
18864        this.disabled = true;
18865     },
18866
18867     
18868     enable : function(){
18869         this.disabled = false;
18870     },
18871
18872     
18873     onLoad : function(){
18874         this.el.unmask(this.removeMask);
18875     },
18876
18877     
18878     onBeforeLoad : function(){
18879         if(!this.disabled){
18880             this.el.mask(this.msg, this.msgCls);
18881         }
18882     },
18883
18884     
18885     show: function(){
18886         this.onBeforeLoad();
18887     },
18888
18889     
18890     hide: function(){
18891         this.onLoad();
18892     },
18893
18894     
18895     destroy : function(){
18896         if(this.store){
18897             this.store.un('beforeload', this.onBeforeLoad, this);
18898             this.store.un('load', this.onLoad, this);
18899             this.store.un('exception', this.onLoad, this);
18900         }else{
18901             var um = this.el.getUpdater();
18902             um.un('beforeupdate', this.onBeforeLoad, this);
18903             um.un('update', this.onLoad, this);
18904             um.un('failure', this.onLoad, this);
18905         }
18906     }
18907 };Ext.ns('Ext.slider');
18908
18909
18910 Ext.slider.Thumb = Ext.extend(Object, {
18911     
18912     
18913     dragging: false,
18914
18915     
18916     constructor: function(config) {
18917         
18918         Ext.apply(this, config || {}, {
18919             cls: 'x-slider-thumb',
18920
18921             
18922             constrain: false
18923         });
18924
18925         Ext.slider.Thumb.superclass.constructor.call(this, config);
18926
18927         if (this.slider.vertical) {
18928             Ext.apply(this, Ext.slider.Thumb.Vertical);
18929         }
18930     },
18931
18932     
18933     render: function() {
18934         this.el = this.slider.innerEl.insertFirst({cls: this.cls});
18935
18936         this.initEvents();
18937     },
18938
18939     
18940     enable: function() {
18941         this.disabled = false;
18942         this.el.removeClass(this.slider.disabledClass);
18943     },
18944
18945     
18946     disable: function() {
18947         this.disabled = true;
18948         this.el.addClass(this.slider.disabledClass);
18949     },
18950
18951     
18952     initEvents: function() {
18953         var el = this.el;
18954
18955         el.addClassOnOver('x-slider-thumb-over');
18956
18957         this.tracker = new Ext.dd.DragTracker({
18958             onBeforeStart: this.onBeforeDragStart.createDelegate(this),
18959             onStart      : this.onDragStart.createDelegate(this),
18960             onDrag       : this.onDrag.createDelegate(this),
18961             onEnd        : this.onDragEnd.createDelegate(this),
18962             tolerance    : 3,
18963             autoStart    : 300
18964         });
18965
18966         this.tracker.initEl(el);
18967     },
18968
18969     
18970     onBeforeDragStart : function(e) {
18971         if (this.disabled) {
18972             return false;
18973         } else {
18974             this.slider.promoteThumb(this);
18975             return true;
18976         }
18977     },
18978
18979     
18980     onDragStart: function(e){
18981         this.el.addClass('x-slider-thumb-drag');
18982         this.dragging = true;
18983         this.dragStartValue = this.value;
18984
18985         this.slider.fireEvent('dragstart', this.slider, e, this);
18986     },
18987
18988     
18989     onDrag: function(e) {
18990         var slider   = this.slider,
18991             index    = this.index,
18992             newValue = this.getNewValue();
18993
18994         if (this.constrain) {
18995             var above = slider.thumbs[index + 1],
18996                 below = slider.thumbs[index - 1];
18997
18998             if (below != undefined && newValue <= below.value) newValue = below.value;
18999             if (above != undefined && newValue >= above.value) newValue = above.value;
19000         }
19001
19002         slider.setValue(index, newValue, false);
19003         slider.fireEvent('drag', slider, e, this);
19004     },
19005
19006     getNewValue: function() {
19007         var slider   = this.slider,
19008             pos      = slider.innerEl.translatePoints(this.tracker.getXY());
19009
19010         return Ext.util.Format.round(slider.reverseValue(pos.left), slider.decimalPrecision);
19011     },
19012
19013     
19014     onDragEnd: function(e) {
19015         var slider = this.slider,
19016             value  = this.value;
19017
19018         this.el.removeClass('x-slider-thumb-drag');
19019
19020         this.dragging = false;
19021         slider.fireEvent('dragend', slider, e);
19022
19023         if (this.dragStartValue != value) {
19024             slider.fireEvent('changecomplete', slider, value, this);
19025         }
19026     },
19027     
19028     
19029     destroy: function(){
19030         Ext.destroyMembers(this, 'tracker', 'el');
19031     }
19032 });
19033
19034
19035 Ext.slider.MultiSlider = Ext.extend(Ext.BoxComponent, {
19036     
19037     
19038     vertical: false,
19039     
19040     minValue: 0,
19041     
19042     maxValue: 100,
19043     
19044     decimalPrecision: 0,
19045     
19046     keyIncrement: 1,
19047     
19048     increment: 0,
19049
19050     
19051     clickRange: [5,15],
19052
19053     
19054     clickToChange : true,
19055     
19056     animate: true,
19057     
19058     constrainThumbs: true,
19059
19060     
19061     topThumbZIndex: 10000,
19062
19063     
19064     initComponent : function(){
19065         if(!Ext.isDefined(this.value)){
19066             this.value = this.minValue;
19067         }
19068
19069         
19070         this.thumbs = [];
19071
19072         Ext.slider.MultiSlider.superclass.initComponent.call(this);
19073
19074         this.keyIncrement = Math.max(this.increment, this.keyIncrement);
19075         this.addEvents(
19076             
19077             'beforechange',
19078
19079             
19080             'change',
19081
19082             
19083             'changecomplete',
19084
19085             
19086             'dragstart',
19087
19088             
19089             'drag',
19090
19091             
19092             'dragend'
19093         );
19094
19095         
19096         if (this.values == undefined || Ext.isEmpty(this.values)) this.values = [0];
19097
19098         var values = this.values;
19099
19100         for (var i=0; i < values.length; i++) {
19101             this.addThumb(values[i]);
19102         }
19103
19104         if(this.vertical){
19105             Ext.apply(this, Ext.slider.Vertical);
19106         }
19107     },
19108
19109     
19110     addThumb: function(value) {
19111         var thumb = new Ext.slider.Thumb({
19112             value    : value,
19113             slider   : this,
19114             index    : this.thumbs.length,
19115             constrain: this.constrainThumbs
19116         });
19117         this.thumbs.push(thumb);
19118
19119         
19120         if (this.rendered) thumb.render();
19121     },
19122
19123     
19124     promoteThumb: function(topThumb) {
19125         var thumbs = this.thumbs,
19126             zIndex, thumb;
19127
19128         for (var i = 0, j = thumbs.length; i < j; i++) {
19129             thumb = thumbs[i];
19130
19131             if (thumb == topThumb) {
19132                 zIndex = this.topThumbZIndex;
19133             } else {
19134                 zIndex = '';
19135             }
19136
19137             thumb.el.setStyle('zIndex', zIndex);
19138         }
19139     },
19140
19141     
19142     onRender : function() {
19143         this.autoEl = {
19144             cls: 'x-slider ' + (this.vertical ? 'x-slider-vert' : 'x-slider-horz'),
19145             cn : {
19146                 cls: 'x-slider-end',
19147                 cn : {
19148                     cls:'x-slider-inner',
19149                     cn : [{tag:'a', cls:'x-slider-focus', href:"#", tabIndex: '-1', hidefocus:'on'}]
19150                 }
19151             }
19152         };
19153
19154         Ext.slider.MultiSlider.superclass.onRender.apply(this, arguments);
19155
19156         this.endEl   = this.el.first();
19157         this.innerEl = this.endEl.first();
19158         this.focusEl = this.innerEl.child('.x-slider-focus');
19159
19160         
19161         for (var i=0; i < this.thumbs.length; i++) {
19162             this.thumbs[i].render();
19163         }
19164
19165         
19166         var thumb      = this.innerEl.child('.x-slider-thumb');
19167         this.halfThumb = (this.vertical ? thumb.getHeight() : thumb.getWidth()) / 2;
19168
19169         this.initEvents();
19170     },
19171
19172     
19173     initEvents : function(){
19174         this.mon(this.el, {
19175             scope    : this,
19176             mousedown: this.onMouseDown,
19177             keydown  : this.onKeyDown
19178         });
19179
19180         this.focusEl.swallowEvent("click", true);
19181     },
19182
19183     
19184     onMouseDown : function(e){
19185         if(this.disabled){
19186             return;
19187         }
19188
19189         
19190         var thumbClicked = false;
19191         for (var i=0; i < this.thumbs.length; i++) {
19192             thumbClicked = thumbClicked || e.target == this.thumbs[i].el.dom;
19193         }
19194
19195         if (this.clickToChange && !thumbClicked) {
19196             var local = this.innerEl.translatePoints(e.getXY());
19197             this.onClickChange(local);
19198         }
19199         this.focus();
19200     },
19201
19202     
19203     onClickChange : function(local) {
19204         if (local.top > this.clickRange[0] && local.top < this.clickRange[1]) {
19205             
19206             var thumb = this.getNearest(local, 'left'),
19207                 index = thumb.index;
19208
19209             this.setValue(index, Ext.util.Format.round(this.reverseValue(local.left), this.decimalPrecision), undefined, true);
19210         }
19211     },
19212
19213     
19214     getNearest: function(local, prop) {
19215         var localValue = prop == 'top' ? this.innerEl.getHeight() - local[prop] : local[prop],
19216             clickValue = this.reverseValue(localValue),
19217             nearestDistance = (this.maxValue - this.minValue) + 5, 
19218             index = 0,
19219             nearest = null;
19220
19221         for (var i=0; i < this.thumbs.length; i++) {
19222             var thumb = this.thumbs[i],
19223                 value = thumb.value,
19224                 dist  = Math.abs(value - clickValue);
19225
19226             if (Math.abs(dist <= nearestDistance)) {
19227                 nearest = thumb;
19228                 index = i;
19229                 nearestDistance = dist;
19230             }
19231         }
19232         return nearest;
19233     },
19234
19235     
19236     onKeyDown : function(e){
19237         
19238         if(this.disabled || this.thumbs.length !== 1){
19239             e.preventDefault();
19240             return;
19241         }
19242         var k = e.getKey(),
19243             val;
19244         switch(k){
19245             case e.UP:
19246             case e.RIGHT:
19247                 e.stopEvent();
19248                 val = e.ctrlKey ? this.maxValue : this.getValue(0) + this.keyIncrement;
19249                 this.setValue(0, val, undefined, true);
19250             break;
19251             case e.DOWN:
19252             case e.LEFT:
19253                 e.stopEvent();
19254                 val = e.ctrlKey ? this.minValue : this.getValue(0) - this.keyIncrement;
19255                 this.setValue(0, val, undefined, true);
19256             break;
19257             default:
19258                 e.preventDefault();
19259         }
19260     },
19261
19262     
19263     doSnap : function(value){
19264         if (!(this.increment && value)) {
19265             return value;
19266         }
19267         var newValue = value,
19268             inc = this.increment,
19269             m = value % inc;
19270         if (m != 0) {
19271             newValue -= m;
19272             if (m * 2 >= inc) {
19273                 newValue += inc;
19274             } else if (m * 2 < -inc) {
19275                 newValue -= inc;
19276             }
19277         }
19278         return newValue.constrain(this.minValue,  this.maxValue);
19279     },
19280
19281     
19282     afterRender : function(){
19283         Ext.slider.MultiSlider.superclass.afterRender.apply(this, arguments);
19284
19285         for (var i=0; i < this.thumbs.length; i++) {
19286             var thumb = this.thumbs[i];
19287
19288             if (thumb.value !== undefined) {
19289                 var v = this.normalizeValue(thumb.value);
19290
19291                 if (v !== thumb.value) {
19292                     
19293                     this.setValue(i, v, false);
19294                 } else {
19295                     this.moveThumb(i, this.translateValue(v), false);
19296                 }
19297             }
19298         };
19299     },
19300
19301     
19302     getRatio : function(){
19303         var w = this.innerEl.getWidth(),
19304             v = this.maxValue - this.minValue;
19305         return v == 0 ? w : (w/v);
19306     },
19307
19308     
19309     normalizeValue : function(v){
19310         v = this.doSnap(v);
19311         v = Ext.util.Format.round(v, this.decimalPrecision);
19312         v = v.constrain(this.minValue, this.maxValue);
19313         return v;
19314     },
19315
19316     
19317     setMinValue : function(val){
19318         this.minValue = val;
19319         var i = 0,
19320             thumbs = this.thumbs,
19321             len = thumbs.length,
19322             t;
19323             
19324         for(; i < len; ++i){
19325             t = thumbs[i];
19326             t.value = t.value < val ? val : t.value;
19327         }
19328         this.syncThumb();
19329     },
19330
19331     
19332     setMaxValue : function(val){
19333         this.maxValue = val;
19334         var i = 0,
19335             thumbs = this.thumbs,
19336             len = thumbs.length,
19337             t;
19338             
19339         for(; i < len; ++i){
19340             t = thumbs[i];
19341             t.value = t.value > val ? val : t.value;
19342         }
19343         this.syncThumb();
19344     },
19345
19346     
19347     setValue : function(index, v, animate, changeComplete) {
19348         var thumb = this.thumbs[index],
19349             el    = thumb.el;
19350
19351         v = this.normalizeValue(v);
19352
19353         if (v !== thumb.value && this.fireEvent('beforechange', this, v, thumb.value, thumb) !== false) {
19354             thumb.value = v;
19355             if(this.rendered){
19356                 this.moveThumb(index, this.translateValue(v), animate !== false);
19357                 this.fireEvent('change', this, v, thumb);
19358                 if(changeComplete){
19359                     this.fireEvent('changecomplete', this, v, thumb);
19360                 }
19361             }
19362         }
19363     },
19364
19365     
19366     translateValue : function(v) {
19367         var ratio = this.getRatio();
19368         return (v * ratio) - (this.minValue * ratio) - this.halfThumb;
19369     },
19370
19371     
19372     reverseValue : function(pos){
19373         var ratio = this.getRatio();
19374         return (pos + (this.minValue * ratio)) / ratio;
19375     },
19376
19377     
19378     moveThumb: function(index, v, animate){
19379         var thumb = this.thumbs[index].el;
19380
19381         if(!animate || this.animate === false){
19382             thumb.setLeft(v);
19383         }else{
19384             thumb.shift({left: v, stopFx: true, duration:.35});
19385         }
19386     },
19387
19388     
19389     focus : function(){
19390         this.focusEl.focus(10);
19391     },
19392
19393     
19394     onResize : function(w, h){
19395         var thumbs = this.thumbs,
19396             len = thumbs.length,
19397             i = 0;
19398             
19399         
19400         for(; i < len; ++i){
19401             thumbs[i].el.stopFx();    
19402         }
19403         
19404         if(Ext.isNumber(w)){
19405             this.innerEl.setWidth(w - (this.el.getPadding('l') + this.endEl.getPadding('r')));
19406         }
19407         this.syncThumb();
19408         Ext.slider.MultiSlider.superclass.onResize.apply(this, arguments);
19409     },
19410
19411     
19412     onDisable: function(){
19413         Ext.slider.MultiSlider.superclass.onDisable.call(this);
19414
19415         for (var i=0; i < this.thumbs.length; i++) {
19416             var thumb = this.thumbs[i],
19417                 el    = thumb.el;
19418
19419             thumb.disable();
19420
19421             if(Ext.isIE){
19422                 
19423                 
19424                 var xy = el.getXY();
19425                 el.hide();
19426
19427                 this.innerEl.addClass(this.disabledClass).dom.disabled = true;
19428
19429                 if (!this.thumbHolder) {
19430                     this.thumbHolder = this.endEl.createChild({cls: 'x-slider-thumb ' + this.disabledClass});
19431                 }
19432
19433                 this.thumbHolder.show().setXY(xy);
19434             }
19435         }
19436     },
19437
19438     
19439     onEnable: function(){
19440         Ext.slider.MultiSlider.superclass.onEnable.call(this);
19441
19442         for (var i=0; i < this.thumbs.length; i++) {
19443             var thumb = this.thumbs[i],
19444                 el    = thumb.el;
19445
19446             thumb.enable();
19447
19448             if (Ext.isIE) {
19449                 this.innerEl.removeClass(this.disabledClass).dom.disabled = false;
19450
19451                 if (this.thumbHolder) this.thumbHolder.hide();
19452
19453                 el.show();
19454                 this.syncThumb();
19455             }
19456         }
19457     },
19458
19459     
19460     syncThumb : function() {
19461         if (this.rendered) {
19462             for (var i=0; i < this.thumbs.length; i++) {
19463                 this.moveThumb(i, this.translateValue(this.thumbs[i].value));
19464             }
19465         }
19466     },
19467
19468     
19469     getValue : function(index) {
19470         return this.thumbs[index].value;
19471     },
19472
19473     
19474     getValues: function() {
19475         var values = [];
19476
19477         for (var i=0; i < this.thumbs.length; i++) {
19478             values.push(this.thumbs[i].value);
19479         }
19480
19481         return values;
19482     },
19483
19484     
19485     beforeDestroy : function(){
19486         var thumbs = this.thumbs;
19487         for(var i = 0, len = thumbs.length; i < len; ++i){
19488             thumbs[i].destroy();
19489             thumbs[i] = null;
19490         }
19491         Ext.destroyMembers(this, 'endEl', 'innerEl', 'focusEl', 'thumbHolder');
19492         Ext.slider.MultiSlider.superclass.beforeDestroy.call(this);
19493     }
19494 });
19495
19496 Ext.reg('multislider', Ext.slider.MultiSlider);
19497
19498
19499 Ext.slider.SingleSlider = Ext.extend(Ext.slider.MultiSlider, {
19500     constructor: function(config) {
19501       config = config || {};
19502
19503       Ext.applyIf(config, {
19504           values: [config.value || 0]
19505       });
19506
19507       Ext.slider.SingleSlider.superclass.constructor.call(this, config);
19508     },
19509
19510     
19511     getValue: function() {
19512         
19513         return Ext.slider.SingleSlider.superclass.getValue.call(this, 0);
19514     },
19515
19516     
19517     setValue: function(value, animate) {
19518         var args = Ext.toArray(arguments),
19519             len  = args.length;
19520
19521         
19522         
19523         
19524         if (len == 1 || (len <= 3 && typeof arguments[1] != 'number')) {
19525             args.unshift(0);
19526         }
19527
19528         return Ext.slider.SingleSlider.superclass.setValue.apply(this, args);
19529     },
19530
19531     
19532     syncThumb : function() {
19533         return Ext.slider.SingleSlider.superclass.syncThumb.apply(this, [0].concat(arguments));
19534     },
19535     
19536     
19537     getNearest : function(){
19538         
19539         return this.thumbs[0];    
19540     }
19541 });
19542
19543
19544 Ext.Slider = Ext.slider.SingleSlider;
19545
19546 Ext.reg('slider', Ext.slider.SingleSlider);
19547
19548
19549 Ext.slider.Vertical = {
19550     onResize : function(w, h){
19551         this.innerEl.setHeight(h - (this.el.getPadding('t') + this.endEl.getPadding('b')));
19552         this.syncThumb();
19553     },
19554
19555     getRatio : function(){
19556         var h = this.innerEl.getHeight(),
19557             v = this.maxValue - this.minValue;
19558         return h/v;
19559     },
19560
19561     moveThumb: function(index, v, animate) {
19562         var thumb = this.thumbs[index],
19563             el    = thumb.el;
19564
19565         if (!animate || this.animate === false) {
19566             el.setBottom(v);
19567         } else {
19568             el.shift({bottom: v, stopFx: true, duration:.35});
19569         }
19570     },
19571
19572     onClickChange : function(local) {
19573         if (local.left > this.clickRange[0] && local.left < this.clickRange[1]) {
19574             var thumb = this.getNearest(local, 'top'),
19575                 index = thumb.index,
19576                 value = this.minValue + this.reverseValue(this.innerEl.getHeight() - local.top);
19577
19578             this.setValue(index, Ext.util.Format.round(value, this.decimalPrecision), undefined, true);
19579         }
19580     }
19581 };
19582
19583
19584 Ext.slider.Thumb.Vertical = {
19585     getNewValue: function() {
19586         var slider   = this.slider,
19587             innerEl  = slider.innerEl,
19588             pos      = innerEl.translatePoints(this.tracker.getXY()),
19589             bottom   = innerEl.getHeight() - pos.top;
19590
19591         return slider.minValue + Ext.util.Format.round(bottom / slider.getRatio(), slider.decimalPrecision);
19592     }
19593 };
19594
19595 Ext.ProgressBar = Ext.extend(Ext.BoxComponent, {
19596    
19597     baseCls : 'x-progress',
19598     
19599     
19600     animate : false,
19601
19602     
19603     waitTimer : null,
19604
19605     
19606     initComponent : function(){
19607         Ext.ProgressBar.superclass.initComponent.call(this);
19608         this.addEvents(
19609             
19610             "update"
19611         );
19612     },
19613
19614     
19615     onRender : function(ct, position){
19616         var tpl = new Ext.Template(
19617             '<div class="{cls}-wrap">',
19618                 '<div class="{cls}-inner">',
19619                     '<div class="{cls}-bar">',
19620                         '<div class="{cls}-text">',
19621                             '<div>&#160;</div>',
19622                         '</div>',
19623                     '</div>',
19624                     '<div class="{cls}-text {cls}-text-back">',
19625                         '<div>&#160;</div>',
19626                     '</div>',
19627                 '</div>',
19628             '</div>'
19629         );
19630
19631         this.el = position ? tpl.insertBefore(position, {cls: this.baseCls}, true)
19632             : tpl.append(ct, {cls: this.baseCls}, true);
19633                 
19634         if(this.id){
19635             this.el.dom.id = this.id;
19636         }
19637         var inner = this.el.dom.firstChild;
19638         this.progressBar = Ext.get(inner.firstChild);
19639
19640         if(this.textEl){
19641             
19642             this.textEl = Ext.get(this.textEl);
19643             delete this.textTopEl;
19644         }else{
19645             
19646             this.textTopEl = Ext.get(this.progressBar.dom.firstChild);
19647             var textBackEl = Ext.get(inner.childNodes[1]);
19648             this.textTopEl.setStyle("z-index", 99).addClass('x-hidden');
19649             this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, textBackEl.dom.firstChild]);
19650             this.textEl.setWidth(inner.offsetWidth);
19651         }
19652         this.progressBar.setHeight(inner.offsetHeight);
19653     },
19654     
19655     
19656     afterRender : function(){
19657         Ext.ProgressBar.superclass.afterRender.call(this);
19658         if(this.value){
19659             this.updateProgress(this.value, this.text);
19660         }else{
19661             this.updateText(this.text);
19662         }
19663     },
19664
19665     
19666     updateProgress : function(value, text, animate){
19667         this.value = value || 0;
19668         if(text){
19669             this.updateText(text);
19670         }
19671         if(this.rendered && !this.isDestroyed){
19672             var w = Math.floor(value*this.el.dom.firstChild.offsetWidth);
19673             this.progressBar.setWidth(w, animate === true || (animate !== false && this.animate));
19674             if(this.textTopEl){
19675                 
19676                 this.textTopEl.removeClass('x-hidden').setWidth(w);
19677             }
19678         }
19679         this.fireEvent('update', this, value, text);
19680         return this;
19681     },
19682
19683     
19684     wait : function(o){
19685         if(!this.waitTimer){
19686             var scope = this;
19687             o = o || {};
19688             this.updateText(o.text);
19689             this.waitTimer = Ext.TaskMgr.start({
19690                 run: function(i){
19691                     var inc = o.increment || 10;
19692                     i -= 1;
19693                     this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate);
19694                 },
19695                 interval: o.interval || 1000,
19696                 duration: o.duration,
19697                 onStop: function(){
19698                     if(o.fn){
19699                         o.fn.apply(o.scope || this);
19700                     }
19701                     this.reset();
19702                 },
19703                 scope: scope
19704             });
19705         }
19706         return this;
19707     },
19708
19709     
19710     isWaiting : function(){
19711         return this.waitTimer !== null;
19712     },
19713
19714     
19715     updateText : function(text){
19716         this.text = text || '&#160;';
19717         if(this.rendered){
19718             this.textEl.update(this.text);
19719         }
19720         return this;
19721     },
19722     
19723     
19724     syncProgressBar : function(){
19725         if(this.value){
19726             this.updateProgress(this.value, this.text);
19727         }
19728         return this;
19729     },
19730
19731     
19732     setSize : function(w, h){
19733         Ext.ProgressBar.superclass.setSize.call(this, w, h);
19734         if(this.textTopEl){
19735             var inner = this.el.dom.firstChild;
19736             this.textEl.setSize(inner.offsetWidth, inner.offsetHeight);
19737         }
19738         this.syncProgressBar();
19739         return this;
19740     },
19741
19742     
19743     reset : function(hide){
19744         this.updateProgress(0);
19745         if(this.textTopEl){
19746             this.textTopEl.addClass('x-hidden');
19747         }
19748         this.clearTimer();
19749         if(hide === true){
19750             this.hide();
19751         }
19752         return this;
19753     },
19754     
19755     
19756     clearTimer : function(){
19757         if(this.waitTimer){
19758             this.waitTimer.onStop = null; 
19759             Ext.TaskMgr.stop(this.waitTimer);
19760             this.waitTimer = null;
19761         }
19762     },
19763     
19764     onDestroy: function(){
19765         this.clearTimer();
19766         if(this.rendered){
19767             if(this.textEl.isComposite){
19768                 this.textEl.clear();
19769             }
19770             Ext.destroyMembers(this, 'textEl', 'progressBar', 'textTopEl');
19771         }
19772         Ext.ProgressBar.superclass.onDestroy.call(this);
19773     }
19774 });
19775 Ext.reg('progress', Ext.ProgressBar);
19776
19777 (function() {
19778
19779 var Event=Ext.EventManager;
19780 var Dom=Ext.lib.Dom;
19781
19782
19783 Ext.dd.DragDrop = function(id, sGroup, config) {
19784     if(id) {
19785         this.init(id, sGroup, config);
19786     }
19787 };
19788
19789 Ext.dd.DragDrop.prototype = {
19790
19791     
19792
19793     
19794     id: null,
19795
19796     
19797     config: null,
19798
19799     
19800     dragElId: null,
19801
19802     
19803     handleElId: null,
19804
19805     
19806     invalidHandleTypes: null,
19807
19808     
19809     invalidHandleIds: null,
19810
19811     
19812     invalidHandleClasses: null,
19813
19814     
19815     startPageX: 0,
19816
19817     
19818     startPageY: 0,
19819
19820     
19821     groups: null,
19822
19823     
19824     locked: false,
19825
19826     
19827     lock: function() {
19828         this.locked = true;
19829     },
19830
19831     
19832     moveOnly: false,
19833
19834     
19835     unlock: function() {
19836         this.locked = false;
19837     },
19838
19839     
19840     isTarget: true,
19841
19842     
19843     padding: null,
19844
19845     
19846     _domRef: null,
19847
19848     
19849     __ygDragDrop: true,
19850
19851     
19852     constrainX: false,
19853
19854     
19855     constrainY: false,
19856
19857     
19858     minX: 0,
19859
19860     
19861     maxX: 0,
19862
19863     
19864     minY: 0,
19865
19866     
19867     maxY: 0,
19868
19869     
19870     maintainOffset: false,
19871
19872     
19873     xTicks: null,
19874
19875     
19876     yTicks: null,
19877
19878     
19879     primaryButtonOnly: true,
19880
19881     
19882     available: false,
19883
19884     
19885     hasOuterHandles: false,
19886
19887     
19888     b4StartDrag: function(x, y) { },
19889
19890     
19891     startDrag: function(x, y) {  },
19892
19893     
19894     b4Drag: function(e) { },
19895
19896     
19897     onDrag: function(e) {  },
19898
19899     
19900     onDragEnter: function(e, id) {  },
19901
19902     
19903     b4DragOver: function(e) { },
19904
19905     
19906     onDragOver: function(e, id) {  },
19907
19908     
19909     b4DragOut: function(e) { },
19910
19911     
19912     onDragOut: function(e, id) {  },
19913
19914     
19915     b4DragDrop: function(e) { },
19916
19917     
19918     onDragDrop: function(e, id) {  },
19919
19920     
19921     onInvalidDrop: function(e) {  },
19922
19923     
19924     b4EndDrag: function(e) { },
19925
19926     
19927     endDrag: function(e) {  },
19928
19929     
19930     b4MouseDown: function(e) {  },
19931
19932     
19933     onMouseDown: function(e) {  },
19934
19935     
19936     onMouseUp: function(e) {  },
19937
19938     
19939     onAvailable: function () {
19940     },
19941
19942     
19943     defaultPadding : {left:0, right:0, top:0, bottom:0},
19944
19945     
19946     constrainTo : function(constrainTo, pad, inContent){
19947         if(Ext.isNumber(pad)){
19948             pad = {left: pad, right:pad, top:pad, bottom:pad};
19949         }
19950         pad = pad || this.defaultPadding;
19951         var b = Ext.get(this.getEl()).getBox(),
19952             ce = Ext.get(constrainTo),
19953             s = ce.getScroll(),
19954             c, 
19955             cd = ce.dom;
19956         if(cd == document.body){
19957             c = { x: s.left, y: s.top, width: Ext.lib.Dom.getViewWidth(), height: Ext.lib.Dom.getViewHeight()};
19958         }else{
19959             var xy = ce.getXY();
19960             c = {x : xy[0], y: xy[1], width: cd.clientWidth, height: cd.clientHeight};
19961         }
19962
19963
19964         var topSpace = b.y - c.y,
19965             leftSpace = b.x - c.x;
19966
19967         this.resetConstraints();
19968         this.setXConstraint(leftSpace - (pad.left||0), 
19969                 c.width - leftSpace - b.width - (pad.right||0), 
19970                                 this.xTickSize
19971         );
19972         this.setYConstraint(topSpace - (pad.top||0), 
19973                 c.height - topSpace - b.height - (pad.bottom||0), 
19974                                 this.yTickSize
19975         );
19976     },
19977
19978     
19979     getEl: function() {
19980         if (!this._domRef) {
19981             this._domRef = Ext.getDom(this.id);
19982         }
19983
19984         return this._domRef;
19985     },
19986
19987     
19988     getDragEl: function() {
19989         return Ext.getDom(this.dragElId);
19990     },
19991
19992     
19993     init: function(id, sGroup, config) {
19994         this.initTarget(id, sGroup, config);
19995         Event.on(this.id, "mousedown", this.handleMouseDown, this);
19996         
19997     },
19998
19999     
20000     initTarget: function(id, sGroup, config) {
20001
20002         
20003         this.config = config || {};
20004
20005         
20006         this.DDM = Ext.dd.DDM;
20007         
20008         this.groups = {};
20009
20010         
20011         
20012         if (typeof id !== "string") {
20013             id = Ext.id(id);
20014         }
20015
20016         
20017         this.id = id;
20018
20019         
20020         this.addToGroup((sGroup) ? sGroup : "default");
20021
20022         
20023         
20024         this.handleElId = id;
20025
20026         
20027         this.setDragElId(id);
20028
20029         
20030         this.invalidHandleTypes = { A: "A" };
20031         this.invalidHandleIds = {};
20032         this.invalidHandleClasses = [];
20033
20034         this.applyConfig();
20035
20036         this.handleOnAvailable();
20037     },
20038
20039     
20040     applyConfig: function() {
20041
20042         
20043         
20044         this.padding           = this.config.padding || [0, 0, 0, 0];
20045         this.isTarget          = (this.config.isTarget !== false);
20046         this.maintainOffset    = (this.config.maintainOffset);
20047         this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
20048
20049     },
20050
20051     
20052     handleOnAvailable: function() {
20053         this.available = true;
20054         this.resetConstraints();
20055         this.onAvailable();
20056     },
20057
20058      
20059     setPadding: function(iTop, iRight, iBot, iLeft) {
20060         
20061         if (!iRight && 0 !== iRight) {
20062             this.padding = [iTop, iTop, iTop, iTop];
20063         } else if (!iBot && 0 !== iBot) {
20064             this.padding = [iTop, iRight, iTop, iRight];
20065         } else {
20066             this.padding = [iTop, iRight, iBot, iLeft];
20067         }
20068     },
20069
20070     
20071     setInitPosition: function(diffX, diffY) {
20072         var el = this.getEl();
20073
20074         if (!this.DDM.verifyEl(el)) {
20075             return;
20076         }
20077
20078         var dx = diffX || 0;
20079         var dy = diffY || 0;
20080
20081         var p = Dom.getXY( el );
20082
20083         this.initPageX = p[0] - dx;
20084         this.initPageY = p[1] - dy;
20085
20086         this.lastPageX = p[0];
20087         this.lastPageY = p[1];
20088
20089         this.setStartPosition(p);
20090     },
20091
20092     
20093     setStartPosition: function(pos) {
20094         var p = pos || Dom.getXY( this.getEl() );
20095         this.deltaSetXY = null;
20096
20097         this.startPageX = p[0];
20098         this.startPageY = p[1];
20099     },
20100
20101     
20102     addToGroup: function(sGroup) {
20103         this.groups[sGroup] = true;
20104         this.DDM.regDragDrop(this, sGroup);
20105     },
20106
20107     
20108     removeFromGroup: function(sGroup) {
20109         if (this.groups[sGroup]) {
20110             delete this.groups[sGroup];
20111         }
20112
20113         this.DDM.removeDDFromGroup(this, sGroup);
20114     },
20115
20116     
20117     setDragElId: function(id) {
20118         this.dragElId = id;
20119     },
20120
20121     
20122     setHandleElId: function(id) {
20123         if (typeof id !== "string") {
20124             id = Ext.id(id);
20125         }
20126         this.handleElId = id;
20127         this.DDM.regHandle(this.id, id);
20128     },
20129
20130     
20131     setOuterHandleElId: function(id) {
20132         if (typeof id !== "string") {
20133             id = Ext.id(id);
20134         }
20135         Event.on(id, "mousedown",
20136                 this.handleMouseDown, this);
20137         this.setHandleElId(id);
20138
20139         this.hasOuterHandles = true;
20140     },
20141
20142     
20143     unreg: function() {
20144         Event.un(this.id, "mousedown",
20145                 this.handleMouseDown);
20146         this._domRef = null;
20147         this.DDM._remove(this);
20148     },
20149
20150     destroy : function(){
20151         this.unreg();
20152     },
20153
20154     
20155     isLocked: function() {
20156         return (this.DDM.isLocked() || this.locked);
20157     },
20158
20159     
20160     handleMouseDown: function(e, oDD){
20161         if (this.primaryButtonOnly && e.button != 0) {
20162             return;
20163         }
20164
20165         if (this.isLocked()) {
20166             return;
20167         }
20168
20169         this.DDM.refreshCache(this.groups);
20170
20171         var pt = new Ext.lib.Point(Ext.lib.Event.getPageX(e), Ext.lib.Event.getPageY(e));
20172         if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) )  {
20173         } else {
20174             if (this.clickValidator(e)) {
20175
20176                 
20177                 this.setStartPosition();
20178
20179                 this.b4MouseDown(e);
20180                 this.onMouseDown(e);
20181
20182                 this.DDM.handleMouseDown(e, this);
20183
20184                 this.DDM.stopEvent(e);
20185             } else {
20186
20187
20188             }
20189         }
20190     },
20191
20192     clickValidator: function(e) {
20193         var target = e.getTarget();
20194         return ( this.isValidHandleChild(target) &&
20195                     (this.id == this.handleElId ||
20196                         this.DDM.handleWasClicked(target, this.id)) );
20197     },
20198
20199     
20200     addInvalidHandleType: function(tagName) {
20201         var type = tagName.toUpperCase();
20202         this.invalidHandleTypes[type] = type;
20203     },
20204
20205     
20206     addInvalidHandleId: function(id) {
20207         if (typeof id !== "string") {
20208             id = Ext.id(id);
20209         }
20210         this.invalidHandleIds[id] = id;
20211     },
20212
20213     
20214     addInvalidHandleClass: function(cssClass) {
20215         this.invalidHandleClasses.push(cssClass);
20216     },
20217
20218     
20219     removeInvalidHandleType: function(tagName) {
20220         var type = tagName.toUpperCase();
20221         
20222         delete this.invalidHandleTypes[type];
20223     },
20224
20225     
20226     removeInvalidHandleId: function(id) {
20227         if (typeof id !== "string") {
20228             id = Ext.id(id);
20229         }
20230         delete this.invalidHandleIds[id];
20231     },
20232
20233     
20234     removeInvalidHandleClass: function(cssClass) {
20235         for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {
20236             if (this.invalidHandleClasses[i] == cssClass) {
20237                 delete this.invalidHandleClasses[i];
20238             }
20239         }
20240     },
20241
20242     
20243     isValidHandleChild: function(node) {
20244
20245         var valid = true;
20246         
20247         var nodeName;
20248         try {
20249             nodeName = node.nodeName.toUpperCase();
20250         } catch(e) {
20251             nodeName = node.nodeName;
20252         }
20253         valid = valid && !this.invalidHandleTypes[nodeName];
20254         valid = valid && !this.invalidHandleIds[node.id];
20255
20256         for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {
20257             valid = !Ext.fly(node).hasClass(this.invalidHandleClasses[i]);
20258         }
20259
20260
20261         return valid;
20262
20263     },
20264
20265     
20266     setXTicks: function(iStartX, iTickSize) {
20267         this.xTicks = [];
20268         this.xTickSize = iTickSize;
20269
20270         var tickMap = {};
20271
20272         for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
20273             if (!tickMap[i]) {
20274                 this.xTicks[this.xTicks.length] = i;
20275                 tickMap[i] = true;
20276             }
20277         }
20278
20279         for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
20280             if (!tickMap[i]) {
20281                 this.xTicks[this.xTicks.length] = i;
20282                 tickMap[i] = true;
20283             }
20284         }
20285
20286         this.xTicks.sort(this.DDM.numericSort) ;
20287     },
20288
20289     
20290     setYTicks: function(iStartY, iTickSize) {
20291         this.yTicks = [];
20292         this.yTickSize = iTickSize;
20293
20294         var tickMap = {};
20295
20296         for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
20297             if (!tickMap[i]) {
20298                 this.yTicks[this.yTicks.length] = i;
20299                 tickMap[i] = true;
20300             }
20301         }
20302
20303         for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
20304             if (!tickMap[i]) {
20305                 this.yTicks[this.yTicks.length] = i;
20306                 tickMap[i] = true;
20307             }
20308         }
20309
20310         this.yTicks.sort(this.DDM.numericSort) ;
20311     },
20312
20313     
20314     setXConstraint: function(iLeft, iRight, iTickSize) {
20315         this.leftConstraint = iLeft;
20316         this.rightConstraint = iRight;
20317
20318         this.minX = this.initPageX - iLeft;
20319         this.maxX = this.initPageX + iRight;
20320         if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
20321
20322         this.constrainX = true;
20323     },
20324
20325     
20326     clearConstraints: function() {
20327         this.constrainX = false;
20328         this.constrainY = false;
20329         this.clearTicks();
20330     },
20331
20332     
20333     clearTicks: function() {
20334         this.xTicks = null;
20335         this.yTicks = null;
20336         this.xTickSize = 0;
20337         this.yTickSize = 0;
20338     },
20339
20340     
20341     setYConstraint: function(iUp, iDown, iTickSize) {
20342         this.topConstraint = iUp;
20343         this.bottomConstraint = iDown;
20344
20345         this.minY = this.initPageY - iUp;
20346         this.maxY = this.initPageY + iDown;
20347         if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
20348
20349         this.constrainY = true;
20350
20351     },
20352
20353     
20354     resetConstraints: function() {
20355         
20356         if (this.initPageX || this.initPageX === 0) {
20357             
20358             var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
20359             var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
20360
20361             this.setInitPosition(dx, dy);
20362
20363         
20364         } else {
20365             this.setInitPosition();
20366         }
20367
20368         if (this.constrainX) {
20369             this.setXConstraint( this.leftConstraint,
20370                                  this.rightConstraint,
20371                                  this.xTickSize        );
20372         }
20373
20374         if (this.constrainY) {
20375             this.setYConstraint( this.topConstraint,
20376                                  this.bottomConstraint,
20377                                  this.yTickSize         );
20378         }
20379     },
20380
20381     
20382     getTick: function(val, tickArray) {
20383         if (!tickArray) {
20384             
20385             
20386             return val;
20387         } else if (tickArray[0] >= val) {
20388             
20389             
20390             return tickArray[0];
20391         } else {
20392             for (var i=0, len=tickArray.length; i<len; ++i) {
20393                 var next = i + 1;
20394                 if (tickArray[next] && tickArray[next] >= val) {
20395                     var diff1 = val - tickArray[i];
20396                     var diff2 = tickArray[next] - val;
20397                     return (diff2 > diff1) ? tickArray[i] : tickArray[next];
20398                 }
20399             }
20400
20401             
20402             
20403             return tickArray[tickArray.length - 1];
20404         }
20405     },
20406
20407     
20408     toString: function() {
20409         return ("DragDrop " + this.id);
20410     }
20411
20412 };
20413
20414 })();
20415
20416
20417
20418
20419 if (!Ext.dd.DragDropMgr) {
20420
20421
20422 Ext.dd.DragDropMgr = function() {
20423
20424     var Event = Ext.EventManager;
20425
20426     return {
20427
20428         
20429         ids: {},
20430
20431         
20432         handleIds: {},
20433
20434         
20435         dragCurrent: null,
20436
20437         
20438         dragOvers: {},
20439
20440         
20441         deltaX: 0,
20442
20443         
20444         deltaY: 0,
20445
20446         
20447         preventDefault: true,
20448
20449         
20450         stopPropagation: true,
20451
20452         
20453         initialized: false,
20454
20455         
20456         locked: false,
20457
20458         
20459         init: function() {
20460             this.initialized = true;
20461         },
20462
20463         
20464         POINT: 0,
20465
20466         
20467         INTERSECT: 1,
20468
20469         
20470         mode: 0,
20471
20472         
20473         _execOnAll: function(sMethod, args) {
20474             for (var i in this.ids) {
20475                 for (var j in this.ids[i]) {
20476                     var oDD = this.ids[i][j];
20477                     if (! this.isTypeOfDD(oDD)) {
20478                         continue;
20479                     }
20480                     oDD[sMethod].apply(oDD, args);
20481                 }
20482             }
20483         },
20484
20485         
20486         _onLoad: function() {
20487
20488             this.init();
20489
20490
20491             Event.on(document, "mouseup",   this.handleMouseUp, this, true);
20492             Event.on(document, "mousemove", this.handleMouseMove, this, true);
20493             Event.on(window,   "unload",    this._onUnload, this, true);
20494             Event.on(window,   "resize",    this._onResize, this, true);
20495             
20496
20497         },
20498
20499         
20500         _onResize: function(e) {
20501             this._execOnAll("resetConstraints", []);
20502         },
20503
20504         
20505         lock: function() { this.locked = true; },
20506
20507         
20508         unlock: function() { this.locked = false; },
20509
20510         
20511         isLocked: function() { return this.locked; },
20512
20513         
20514         locationCache: {},
20515
20516         
20517         useCache: true,
20518
20519         
20520         clickPixelThresh: 3,
20521
20522         
20523         clickTimeThresh: 350,
20524
20525         
20526         dragThreshMet: false,
20527
20528         
20529         clickTimeout: null,
20530
20531         
20532         startX: 0,
20533
20534         
20535         startY: 0,
20536
20537         
20538         regDragDrop: function(oDD, sGroup) {
20539             if (!this.initialized) { this.init(); }
20540
20541             if (!this.ids[sGroup]) {
20542                 this.ids[sGroup] = {};
20543             }
20544             this.ids[sGroup][oDD.id] = oDD;
20545         },
20546
20547         
20548         removeDDFromGroup: function(oDD, sGroup) {
20549             if (!this.ids[sGroup]) {
20550                 this.ids[sGroup] = {};
20551             }
20552
20553             var obj = this.ids[sGroup];
20554             if (obj && obj[oDD.id]) {
20555                 delete obj[oDD.id];
20556             }
20557         },
20558
20559         
20560         _remove: function(oDD) {
20561             for (var g in oDD.groups) {
20562                 if (g && this.ids[g] && this.ids[g][oDD.id]) {
20563                     delete this.ids[g][oDD.id];
20564                 }
20565             }
20566             delete this.handleIds[oDD.id];
20567         },
20568
20569         
20570         regHandle: function(sDDId, sHandleId) {
20571             if (!this.handleIds[sDDId]) {
20572                 this.handleIds[sDDId] = {};
20573             }
20574             this.handleIds[sDDId][sHandleId] = sHandleId;
20575         },
20576
20577         
20578         isDragDrop: function(id) {
20579             return ( this.getDDById(id) ) ? true : false;
20580         },
20581
20582         
20583         getRelated: function(p_oDD, bTargetsOnly) {
20584             var oDDs = [];
20585             for (var i in p_oDD.groups) {
20586                 for (var j in this.ids[i]) {
20587                     var dd = this.ids[i][j];
20588                     if (! this.isTypeOfDD(dd)) {
20589                         continue;
20590                     }
20591                     if (!bTargetsOnly || dd.isTarget) {
20592                         oDDs[oDDs.length] = dd;
20593                     }
20594                 }
20595             }
20596
20597             return oDDs;
20598         },
20599
20600         
20601         isLegalTarget: function (oDD, oTargetDD) {
20602             var targets = this.getRelated(oDD, true);
20603             for (var i=0, len=targets.length;i<len;++i) {
20604                 if (targets[i].id == oTargetDD.id) {
20605                     return true;
20606                 }
20607             }
20608
20609             return false;
20610         },
20611
20612         
20613         isTypeOfDD: function (oDD) {
20614             return (oDD && oDD.__ygDragDrop);
20615         },
20616
20617         
20618         isHandle: function(sDDId, sHandleId) {
20619             return ( this.handleIds[sDDId] &&
20620                             this.handleIds[sDDId][sHandleId] );
20621         },
20622
20623         
20624         getDDById: function(id) {
20625             for (var i in this.ids) {
20626                 if (this.ids[i][id]) {
20627                     return this.ids[i][id];
20628                 }
20629             }
20630             return null;
20631         },
20632
20633         
20634         handleMouseDown: function(e, oDD) {
20635             if(Ext.QuickTips){
20636                 Ext.QuickTips.ddDisable();
20637             }
20638             if(this.dragCurrent){
20639                 
20640                 
20641                 this.handleMouseUp(e);
20642             }
20643             
20644             this.currentTarget = e.getTarget();
20645             this.dragCurrent = oDD;
20646
20647             var el = oDD.getEl();
20648
20649             
20650             this.startX = e.getPageX();
20651             this.startY = e.getPageY();
20652
20653             this.deltaX = this.startX - el.offsetLeft;
20654             this.deltaY = this.startY - el.offsetTop;
20655
20656             this.dragThreshMet = false;
20657
20658             this.clickTimeout = setTimeout(
20659                     function() {
20660                         var DDM = Ext.dd.DDM;
20661                         DDM.startDrag(DDM.startX, DDM.startY);
20662                     },
20663                     this.clickTimeThresh );
20664         },
20665
20666         
20667         startDrag: function(x, y) {
20668             clearTimeout(this.clickTimeout);
20669             if (this.dragCurrent) {
20670                 this.dragCurrent.b4StartDrag(x, y);
20671                 this.dragCurrent.startDrag(x, y);
20672             }
20673             this.dragThreshMet = true;
20674         },
20675
20676         
20677         handleMouseUp: function(e) {
20678
20679             if(Ext.QuickTips){
20680                 Ext.QuickTips.ddEnable();
20681             }
20682             if (! this.dragCurrent) {
20683                 return;
20684             }
20685
20686             clearTimeout(this.clickTimeout);
20687
20688             if (this.dragThreshMet) {
20689                 this.fireEvents(e, true);
20690             } else {
20691             }
20692
20693             this.stopDrag(e);
20694
20695             this.stopEvent(e);
20696         },
20697
20698         
20699         stopEvent: function(e){
20700             if(this.stopPropagation) {
20701                 e.stopPropagation();
20702             }
20703
20704             if (this.preventDefault) {
20705                 e.preventDefault();
20706             }
20707         },
20708
20709         
20710         stopDrag: function(e) {
20711             
20712             if (this.dragCurrent) {
20713                 if (this.dragThreshMet) {
20714                     this.dragCurrent.b4EndDrag(e);
20715                     this.dragCurrent.endDrag(e);
20716                 }
20717
20718                 this.dragCurrent.onMouseUp(e);
20719             }
20720
20721             this.dragCurrent = null;
20722             this.dragOvers = {};
20723         },
20724
20725         
20726         handleMouseMove: function(e) {
20727             if (! this.dragCurrent) {
20728                 return true;
20729             }
20730             
20731
20732             
20733             if (Ext.isIE && (e.button !== 0 && e.button !== 1 && e.button !== 2)) {
20734                 this.stopEvent(e);
20735                 return this.handleMouseUp(e);
20736             }
20737
20738             if (!this.dragThreshMet) {
20739                 var diffX = Math.abs(this.startX - e.getPageX());
20740                 var diffY = Math.abs(this.startY - e.getPageY());
20741                 if (diffX > this.clickPixelThresh ||
20742                             diffY > this.clickPixelThresh) {
20743                     this.startDrag(this.startX, this.startY);
20744                 }
20745             }
20746
20747             if (this.dragThreshMet) {
20748                 this.dragCurrent.b4Drag(e);
20749                 this.dragCurrent.onDrag(e);
20750                 if(!this.dragCurrent.moveOnly){
20751                     this.fireEvents(e, false);
20752                 }
20753             }
20754
20755             this.stopEvent(e);
20756
20757             return true;
20758         },
20759
20760         
20761         fireEvents: function(e, isDrop) {
20762             var dc = this.dragCurrent;
20763
20764             
20765             
20766             if (!dc || dc.isLocked()) {
20767                 return;
20768             }
20769
20770             var pt = e.getPoint();
20771
20772             
20773             var oldOvers = [];
20774
20775             var outEvts   = [];
20776             var overEvts  = [];
20777             var dropEvts  = [];
20778             var enterEvts = [];
20779
20780             
20781             
20782             for (var i in this.dragOvers) {
20783
20784                 var ddo = this.dragOvers[i];
20785
20786                 if (! this.isTypeOfDD(ddo)) {
20787                     continue;
20788                 }
20789
20790                 if (! this.isOverTarget(pt, ddo, this.mode)) {
20791                     outEvts.push( ddo );
20792                 }
20793
20794                 oldOvers[i] = true;
20795                 delete this.dragOvers[i];
20796             }
20797
20798             for (var sGroup in dc.groups) {
20799
20800                 if ("string" != typeof sGroup) {
20801                     continue;
20802                 }
20803
20804                 for (i in this.ids[sGroup]) {
20805                     var oDD = this.ids[sGroup][i];
20806                     if (! this.isTypeOfDD(oDD)) {
20807                         continue;
20808                     }
20809
20810                     if (oDD.isTarget && !oDD.isLocked() && ((oDD != dc) || (dc.ignoreSelf === false))) {
20811                         if (this.isOverTarget(pt, oDD, this.mode)) {
20812                             
20813                             if (isDrop) {
20814                                 dropEvts.push( oDD );
20815                             
20816                             } else {
20817
20818                                 
20819                                 if (!oldOvers[oDD.id]) {
20820                                     enterEvts.push( oDD );
20821                                 
20822                                 } else {
20823                                     overEvts.push( oDD );
20824                                 }
20825
20826                                 this.dragOvers[oDD.id] = oDD;
20827                             }
20828                         }
20829                     }
20830                 }
20831             }
20832
20833             if (this.mode) {
20834                 if (outEvts.length) {
20835                     dc.b4DragOut(e, outEvts);
20836                     dc.onDragOut(e, outEvts);
20837                 }
20838
20839                 if (enterEvts.length) {
20840                     dc.onDragEnter(e, enterEvts);
20841                 }
20842
20843                 if (overEvts.length) {
20844                     dc.b4DragOver(e, overEvts);
20845                     dc.onDragOver(e, overEvts);
20846                 }
20847
20848                 if (dropEvts.length) {
20849                     dc.b4DragDrop(e, dropEvts);
20850                     dc.onDragDrop(e, dropEvts);
20851                 }
20852
20853             } else {
20854                 
20855                 var len = 0;
20856                 for (i=0, len=outEvts.length; i<len; ++i) {
20857                     dc.b4DragOut(e, outEvts[i].id);
20858                     dc.onDragOut(e, outEvts[i].id);
20859                 }
20860
20861                 
20862                 for (i=0,len=enterEvts.length; i<len; ++i) {
20863                     
20864                     dc.onDragEnter(e, enterEvts[i].id);
20865                 }
20866
20867                 
20868                 for (i=0,len=overEvts.length; i<len; ++i) {
20869                     dc.b4DragOver(e, overEvts[i].id);
20870                     dc.onDragOver(e, overEvts[i].id);
20871                 }
20872
20873                 
20874                 for (i=0, len=dropEvts.length; i<len; ++i) {
20875                     dc.b4DragDrop(e, dropEvts[i].id);
20876                     dc.onDragDrop(e, dropEvts[i].id);
20877                 }
20878
20879             }
20880
20881             
20882             if (isDrop && !dropEvts.length) {
20883                 dc.onInvalidDrop(e);
20884             }
20885
20886         },
20887
20888         
20889         getBestMatch: function(dds) {
20890             var winner = null;
20891             
20892             
20893                
20894             
20895             
20896
20897             var len = dds.length;
20898
20899             if (len == 1) {
20900                 winner = dds[0];
20901             } else {
20902                 
20903                 for (var i=0; i<len; ++i) {
20904                     var dd = dds[i];
20905                     
20906                     
20907                     
20908                     if (dd.cursorIsOver) {
20909                         winner = dd;
20910                         break;
20911                     
20912                     } else {
20913                         if (!winner ||
20914                             winner.overlap.getArea() < dd.overlap.getArea()) {
20915                             winner = dd;
20916                         }
20917                     }
20918                 }
20919             }
20920
20921             return winner;
20922         },
20923
20924         
20925         refreshCache: function(groups) {
20926             for (var sGroup in groups) {
20927                 if ("string" != typeof sGroup) {
20928                     continue;
20929                 }
20930                 for (var i in this.ids[sGroup]) {
20931                     var oDD = this.ids[sGroup][i];
20932
20933                     if (this.isTypeOfDD(oDD)) {
20934                     
20935                         var loc = this.getLocation(oDD);
20936                         if (loc) {
20937                             this.locationCache[oDD.id] = loc;
20938                         } else {
20939                             delete this.locationCache[oDD.id];
20940                             
20941                             
20942                             
20943                         }
20944                     }
20945                 }
20946             }
20947         },
20948
20949         
20950         verifyEl: function(el) {
20951             if (el) {
20952                 var parent;
20953                 if(Ext.isIE){
20954                     try{
20955                         parent = el.offsetParent;
20956                     }catch(e){}
20957                 }else{
20958                     parent = el.offsetParent;
20959                 }
20960                 if (parent) {
20961                     return true;
20962                 }
20963             }
20964
20965             return false;
20966         },
20967
20968         
20969         getLocation: function(oDD) {
20970             if (! this.isTypeOfDD(oDD)) {
20971                 return null;
20972             }
20973
20974             var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
20975
20976             try {
20977                 pos= Ext.lib.Dom.getXY(el);
20978             } catch (e) { }
20979
20980             if (!pos) {
20981                 return null;
20982             }
20983
20984             x1 = pos[0];
20985             x2 = x1 + el.offsetWidth;
20986             y1 = pos[1];
20987             y2 = y1 + el.offsetHeight;
20988
20989             t = y1 - oDD.padding[0];
20990             r = x2 + oDD.padding[1];
20991             b = y2 + oDD.padding[2];
20992             l = x1 - oDD.padding[3];
20993
20994             return new Ext.lib.Region( t, r, b, l );
20995         },
20996
20997         
20998         isOverTarget: function(pt, oTarget, intersect) {
20999             
21000             var loc = this.locationCache[oTarget.id];
21001             if (!loc || !this.useCache) {
21002                 loc = this.getLocation(oTarget);
21003                 this.locationCache[oTarget.id] = loc;
21004
21005             }
21006
21007             if (!loc) {
21008                 return false;
21009             }
21010
21011             oTarget.cursorIsOver = loc.contains( pt );
21012
21013             
21014             
21015             
21016             
21017             
21018             var dc = this.dragCurrent;
21019             if (!dc || !dc.getTargetCoord ||
21020                     (!intersect && !dc.constrainX && !dc.constrainY)) {
21021                 return oTarget.cursorIsOver;
21022             }
21023
21024             oTarget.overlap = null;
21025
21026             
21027             
21028             
21029             
21030             var pos = dc.getTargetCoord(pt.x, pt.y);
21031
21032             var el = dc.getDragEl();
21033             var curRegion = new Ext.lib.Region( pos.y,
21034                                                    pos.x + el.offsetWidth,
21035                                                    pos.y + el.offsetHeight,
21036                                                    pos.x );
21037
21038             var overlap = curRegion.intersect(loc);
21039
21040             if (overlap) {
21041                 oTarget.overlap = overlap;
21042                 return (intersect) ? true : oTarget.cursorIsOver;
21043             } else {
21044                 return false;
21045             }
21046         },
21047
21048         
21049         _onUnload: function(e, me) {
21050             Ext.dd.DragDropMgr.unregAll();
21051         },
21052
21053         
21054         unregAll: function() {
21055
21056             if (this.dragCurrent) {
21057                 this.stopDrag();
21058                 this.dragCurrent = null;
21059             }
21060
21061             this._execOnAll("unreg", []);
21062
21063             for (var i in this.elementCache) {
21064                 delete this.elementCache[i];
21065             }
21066
21067             this.elementCache = {};
21068             this.ids = {};
21069         },
21070
21071         
21072         elementCache: {},
21073
21074         
21075         getElWrapper: function(id) {
21076             var oWrapper = this.elementCache[id];
21077             if (!oWrapper || !oWrapper.el) {
21078                 oWrapper = this.elementCache[id] =
21079                     new this.ElementWrapper(Ext.getDom(id));
21080             }
21081             return oWrapper;
21082         },
21083
21084         
21085         getElement: function(id) {
21086             return Ext.getDom(id);
21087         },
21088
21089         
21090         getCss: function(id) {
21091             var el = Ext.getDom(id);
21092             return (el) ? el.style : null;
21093         },
21094
21095         
21096         ElementWrapper: function(el) {
21097                 
21098                 this.el = el || null;
21099                 
21100                 this.id = this.el && el.id;
21101                 
21102                 this.css = this.el && el.style;
21103             },
21104
21105         
21106         getPosX: function(el) {
21107             return Ext.lib.Dom.getX(el);
21108         },
21109
21110         
21111         getPosY: function(el) {
21112             return Ext.lib.Dom.getY(el);
21113         },
21114
21115         
21116         swapNode: function(n1, n2) {
21117             if (n1.swapNode) {
21118                 n1.swapNode(n2);
21119             } else {
21120                 var p = n2.parentNode;
21121                 var s = n2.nextSibling;
21122
21123                 if (s == n1) {
21124                     p.insertBefore(n1, n2);
21125                 } else if (n2 == n1.nextSibling) {
21126                     p.insertBefore(n2, n1);
21127                 } else {
21128                     n1.parentNode.replaceChild(n2, n1);
21129                     p.insertBefore(n1, s);
21130                 }
21131             }
21132         },
21133
21134         
21135         getScroll: function () {
21136             var t, l, dde=document.documentElement, db=document.body;
21137             if (dde && (dde.scrollTop || dde.scrollLeft)) {
21138                 t = dde.scrollTop;
21139                 l = dde.scrollLeft;
21140             } else if (db) {
21141                 t = db.scrollTop;
21142                 l = db.scrollLeft;
21143             } else {
21144
21145             }
21146             return { top: t, left: l };
21147         },
21148
21149         
21150         getStyle: function(el, styleProp) {
21151             return Ext.fly(el).getStyle(styleProp);
21152         },
21153
21154         
21155         getScrollTop: function () {
21156             return this.getScroll().top;
21157         },
21158
21159         
21160         getScrollLeft: function () {
21161             return this.getScroll().left;
21162         },
21163
21164         
21165         moveToEl: function (moveEl, targetEl) {
21166             var aCoord = Ext.lib.Dom.getXY(targetEl);
21167             Ext.lib.Dom.setXY(moveEl, aCoord);
21168         },
21169
21170         
21171         numericSort: function(a, b) {
21172             return (a - b);
21173         },
21174
21175         
21176         _timeoutCount: 0,
21177
21178         
21179         _addListeners: function() {
21180             var DDM = Ext.dd.DDM;
21181             if ( Ext.lib.Event && document ) {
21182                 DDM._onLoad();
21183             } else {
21184                 if (DDM._timeoutCount > 2000) {
21185                 } else {
21186                     setTimeout(DDM._addListeners, 10);
21187                     if (document && document.body) {
21188                         DDM._timeoutCount += 1;
21189                     }
21190                 }
21191             }
21192         },
21193
21194         
21195         handleWasClicked: function(node, id) {
21196             if (this.isHandle(id, node.id)) {
21197                 return true;
21198             } else {
21199                 
21200                 var p = node.parentNode;
21201
21202                 while (p) {
21203                     if (this.isHandle(id, p.id)) {
21204                         return true;
21205                     } else {
21206                         p = p.parentNode;
21207                     }
21208                 }
21209             }
21210
21211             return false;
21212         }
21213
21214     };
21215
21216 }();
21217
21218
21219 Ext.dd.DDM = Ext.dd.DragDropMgr;
21220 Ext.dd.DDM._addListeners();
21221
21222 }
21223
21224
21225 Ext.dd.DD = function(id, sGroup, config) {
21226     if (id) {
21227         this.init(id, sGroup, config);
21228     }
21229 };
21230
21231 Ext.extend(Ext.dd.DD, Ext.dd.DragDrop, {
21232
21233     
21234     scroll: true,
21235
21236     
21237     autoOffset: function(iPageX, iPageY) {
21238         var x = iPageX - this.startPageX;
21239         var y = iPageY - this.startPageY;
21240         this.setDelta(x, y);
21241     },
21242
21243     
21244     setDelta: function(iDeltaX, iDeltaY) {
21245         this.deltaX = iDeltaX;
21246         this.deltaY = iDeltaY;
21247     },
21248
21249     
21250     setDragElPos: function(iPageX, iPageY) {
21251         
21252         
21253
21254         var el = this.getDragEl();
21255         this.alignElWithMouse(el, iPageX, iPageY);
21256     },
21257
21258     
21259     alignElWithMouse: function(el, iPageX, iPageY) {
21260         var oCoord = this.getTargetCoord(iPageX, iPageY);
21261         var fly = el.dom ? el : Ext.fly(el, '_dd');
21262         if (!this.deltaSetXY) {
21263             var aCoord = [oCoord.x, oCoord.y];
21264             fly.setXY(aCoord);
21265             var newLeft = fly.getLeft(true);
21266             var newTop  = fly.getTop(true);
21267             this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ];
21268         } else {
21269             fly.setLeftTop(oCoord.x + this.deltaSetXY[0], oCoord.y + this.deltaSetXY[1]);
21270         }
21271
21272         this.cachePosition(oCoord.x, oCoord.y);
21273         this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
21274         return oCoord;
21275     },
21276
21277     
21278     cachePosition: function(iPageX, iPageY) {
21279         if (iPageX) {
21280             this.lastPageX = iPageX;
21281             this.lastPageY = iPageY;
21282         } else {
21283             var aCoord = Ext.lib.Dom.getXY(this.getEl());
21284             this.lastPageX = aCoord[0];
21285             this.lastPageY = aCoord[1];
21286         }
21287     },
21288
21289     
21290     autoScroll: function(x, y, h, w) {
21291
21292         if (this.scroll) {
21293             
21294             var clientH = Ext.lib.Dom.getViewHeight();
21295
21296             
21297             var clientW = Ext.lib.Dom.getViewWidth();
21298
21299             
21300             var st = this.DDM.getScrollTop();
21301
21302             
21303             var sl = this.DDM.getScrollLeft();
21304
21305             
21306             var bot = h + y;
21307
21308             
21309             var right = w + x;
21310
21311             
21312             
21313             
21314             var toBot = (clientH + st - y - this.deltaY);
21315
21316             
21317             var toRight = (clientW + sl - x - this.deltaX);
21318
21319
21320             
21321             
21322             var thresh = 40;
21323
21324             
21325             
21326             
21327             var scrAmt = (document.all) ? 80 : 30;
21328
21329             
21330             
21331             if ( bot > clientH && toBot < thresh ) {
21332                 window.scrollTo(sl, st + scrAmt);
21333             }
21334
21335             
21336             
21337             if ( y < st && st > 0 && y - st < thresh ) {
21338                 window.scrollTo(sl, st - scrAmt);
21339             }
21340
21341             
21342             
21343             if ( right > clientW && toRight < thresh ) {
21344                 window.scrollTo(sl + scrAmt, st);
21345             }
21346
21347             
21348             
21349             if ( x < sl && sl > 0 && x - sl < thresh ) {
21350                 window.scrollTo(sl - scrAmt, st);
21351             }
21352         }
21353     },
21354
21355     
21356     getTargetCoord: function(iPageX, iPageY) {
21357         var x = iPageX - this.deltaX;
21358         var y = iPageY - this.deltaY;
21359
21360         if (this.constrainX) {
21361             if (x < this.minX) { x = this.minX; }
21362             if (x > this.maxX) { x = this.maxX; }
21363         }
21364
21365         if (this.constrainY) {
21366             if (y < this.minY) { y = this.minY; }
21367             if (y > this.maxY) { y = this.maxY; }
21368         }
21369
21370         x = this.getTick(x, this.xTicks);
21371         y = this.getTick(y, this.yTicks);
21372
21373
21374         return {x:x, y:y};
21375     },
21376
21377     
21378     applyConfig: function() {
21379         Ext.dd.DD.superclass.applyConfig.call(this);
21380         this.scroll = (this.config.scroll !== false);
21381     },
21382
21383     
21384     b4MouseDown: function(e) {
21385         
21386         this.autoOffset(e.getPageX(),
21387                             e.getPageY());
21388     },
21389
21390     
21391     b4Drag: function(e) {
21392         this.setDragElPos(e.getPageX(),
21393                             e.getPageY());
21394     },
21395
21396     toString: function() {
21397         return ("DD " + this.id);
21398     }
21399
21400     
21401     
21402     
21403     
21404
21405 });
21406
21407 Ext.dd.DDProxy = function(id, sGroup, config) {
21408     if (id) {
21409         this.init(id, sGroup, config);
21410         this.initFrame();
21411     }
21412 };
21413
21414
21415 Ext.dd.DDProxy.dragElId = "ygddfdiv";
21416
21417 Ext.extend(Ext.dd.DDProxy, Ext.dd.DD, {
21418
21419     
21420     resizeFrame: true,
21421
21422     
21423     centerFrame: false,
21424
21425     
21426     createFrame: function() {
21427         var self = this;
21428         var body = document.body;
21429
21430         if (!body || !body.firstChild) {
21431             setTimeout( function() { self.createFrame(); }, 50 );
21432             return;
21433         }
21434
21435         var div = this.getDragEl();
21436
21437         if (!div) {
21438             div    = document.createElement("div");
21439             div.id = this.dragElId;
21440             var s  = div.style;
21441
21442             s.position   = "absolute";
21443             s.visibility = "hidden";
21444             s.cursor     = "move";
21445             s.border     = "2px solid #aaa";
21446             s.zIndex     = 999;
21447
21448             
21449             
21450             
21451             body.insertBefore(div, body.firstChild);
21452         }
21453     },
21454
21455     
21456     initFrame: function() {
21457         this.createFrame();
21458     },
21459
21460     applyConfig: function() {
21461         Ext.dd.DDProxy.superclass.applyConfig.call(this);
21462
21463         this.resizeFrame = (this.config.resizeFrame !== false);
21464         this.centerFrame = (this.config.centerFrame);
21465         this.setDragElId(this.config.dragElId || Ext.dd.DDProxy.dragElId);
21466     },
21467
21468     
21469     showFrame: function(iPageX, iPageY) {
21470         var el = this.getEl();
21471         var dragEl = this.getDragEl();
21472         var s = dragEl.style;
21473
21474         this._resizeProxy();
21475
21476         if (this.centerFrame) {
21477             this.setDelta( Math.round(parseInt(s.width,  10)/2),
21478                            Math.round(parseInt(s.height, 10)/2) );
21479         }
21480
21481         this.setDragElPos(iPageX, iPageY);
21482
21483         Ext.fly(dragEl).show();
21484     },
21485
21486     
21487     _resizeProxy: function() {
21488         if (this.resizeFrame) {
21489             var el = this.getEl();
21490             Ext.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);
21491         }
21492     },
21493
21494     
21495     b4MouseDown: function(e) {
21496         var x = e.getPageX();
21497         var y = e.getPageY();
21498         this.autoOffset(x, y);
21499         this.setDragElPos(x, y);
21500     },
21501
21502     
21503     b4StartDrag: function(x, y) {
21504         
21505         this.showFrame(x, y);
21506     },
21507
21508     
21509     b4EndDrag: function(e) {
21510         Ext.fly(this.getDragEl()).hide();
21511     },
21512
21513     
21514     
21515     
21516     endDrag: function(e) {
21517
21518         var lel = this.getEl();
21519         var del = this.getDragEl();
21520
21521         
21522         del.style.visibility = "";
21523
21524         this.beforeMove();
21525         
21526         
21527         lel.style.visibility = "hidden";
21528         Ext.dd.DDM.moveToEl(lel, del);
21529         del.style.visibility = "hidden";
21530         lel.style.visibility = "";
21531
21532         this.afterDrag();
21533     },
21534
21535     beforeMove : function(){
21536
21537     },
21538
21539     afterDrag : function(){
21540
21541     },
21542
21543     toString: function() {
21544         return ("DDProxy " + this.id);
21545     }
21546
21547 });
21548
21549 Ext.dd.DDTarget = function(id, sGroup, config) {
21550     if (id) {
21551         this.initTarget(id, sGroup, config);
21552     }
21553 };
21554
21555
21556 Ext.extend(Ext.dd.DDTarget, Ext.dd.DragDrop, {
21557     
21558     getDragEl: Ext.emptyFn,
21559     
21560     isValidHandleChild: Ext.emptyFn,
21561     
21562     startDrag: Ext.emptyFn,
21563     
21564     endDrag: Ext.emptyFn,
21565     
21566     onDrag: Ext.emptyFn,
21567     
21568     onDragDrop: Ext.emptyFn,
21569     
21570     onDragEnter: Ext.emptyFn,
21571     
21572     onDragOut: Ext.emptyFn,
21573     
21574     onDragOver: Ext.emptyFn,
21575     
21576     onInvalidDrop: Ext.emptyFn,
21577     
21578     onMouseDown: Ext.emptyFn,
21579     
21580     onMouseUp: Ext.emptyFn,
21581     
21582     setXConstraint: Ext.emptyFn,
21583     
21584     setYConstraint: Ext.emptyFn,
21585     
21586     resetConstraints: Ext.emptyFn,
21587     
21588     clearConstraints: Ext.emptyFn,
21589     
21590     clearTicks: Ext.emptyFn,
21591     
21592     setInitPosition: Ext.emptyFn,
21593     
21594     setDragElId: Ext.emptyFn,
21595     
21596     setHandleElId: Ext.emptyFn,
21597     
21598     setOuterHandleElId: Ext.emptyFn,
21599     
21600     addInvalidHandleClass: Ext.emptyFn,
21601     
21602     addInvalidHandleId: Ext.emptyFn,
21603     
21604     addInvalidHandleType: Ext.emptyFn,
21605     
21606     removeInvalidHandleClass: Ext.emptyFn,
21607     
21608     removeInvalidHandleId: Ext.emptyFn,
21609     
21610     removeInvalidHandleType: Ext.emptyFn,
21611
21612     toString: function() {
21613         return ("DDTarget " + this.id);
21614     }
21615 });
21616 Ext.dd.DragTracker = Ext.extend(Ext.util.Observable,  {    
21617         
21618     active: false,
21619         
21620     tolerance: 5,
21621         
21622     autoStart: false,
21623     
21624     constructor : function(config){
21625         Ext.apply(this, config);
21626             this.addEvents(
21627                 
21628                 'mousedown',
21629                 
21630                 'mouseup',
21631                 
21632                 'mousemove',
21633                 
21634                 'dragstart',
21635                 
21636                 'dragend',
21637                 
21638                 'drag'
21639             );
21640         
21641             this.dragRegion = new Ext.lib.Region(0,0,0,0);
21642         
21643             if(this.el){
21644                 this.initEl(this.el);
21645             }
21646         Ext.dd.DragTracker.superclass.constructor.call(this, config);
21647     },
21648
21649     initEl: function(el){
21650         this.el = Ext.get(el);
21651         el.on('mousedown', this.onMouseDown, this,
21652                 this.delegate ? {delegate: this.delegate} : undefined);
21653     },
21654
21655     destroy : function(){
21656         this.el.un('mousedown', this.onMouseDown, this);
21657         delete this.el;
21658     },
21659
21660     onMouseDown: function(e, target){
21661         if(this.fireEvent('mousedown', this, e) !== false && this.onBeforeStart(e) !== false){
21662             this.startXY = this.lastXY = e.getXY();
21663             this.dragTarget = this.delegate ? target : this.el.dom;
21664             if(this.preventDefault !== false){
21665                 e.preventDefault();
21666             }
21667             Ext.getDoc().on({
21668                 scope: this,
21669                 mouseup: this.onMouseUp,
21670                 mousemove: this.onMouseMove,
21671                 selectstart: this.stopSelect
21672             });
21673             if(this.autoStart){
21674                 this.timer = this.triggerStart.defer(this.autoStart === true ? 1000 : this.autoStart, this, [e]);
21675             }
21676         }
21677     },
21678
21679     onMouseMove: function(e, target){
21680         
21681         if(this.active && Ext.isIE && !e.browserEvent.button){
21682             e.preventDefault();
21683             this.onMouseUp(e);
21684             return;
21685         }
21686
21687         e.preventDefault();
21688         var xy = e.getXY(), s = this.startXY;
21689         this.lastXY = xy;
21690         if(!this.active){
21691             if(Math.abs(s[0]-xy[0]) > this.tolerance || Math.abs(s[1]-xy[1]) > this.tolerance){
21692                 this.triggerStart(e);
21693             }else{
21694                 return;
21695             }
21696         }
21697         this.fireEvent('mousemove', this, e);
21698         this.onDrag(e);
21699         this.fireEvent('drag', this, e);
21700     },
21701
21702     onMouseUp: function(e) {
21703         var doc = Ext.getDoc(),
21704             wasActive = this.active;
21705             
21706         doc.un('mousemove', this.onMouseMove, this);
21707         doc.un('mouseup', this.onMouseUp, this);
21708         doc.un('selectstart', this.stopSelect, this);
21709         e.preventDefault();
21710         this.clearStart();
21711         this.active = false;
21712         delete this.elRegion;
21713         this.fireEvent('mouseup', this, e);
21714         if(wasActive){
21715             this.onEnd(e);
21716             this.fireEvent('dragend', this, e);
21717         }
21718     },
21719
21720     triggerStart: function(e) {
21721         this.clearStart();
21722         this.active = true;
21723         this.onStart(e);
21724         this.fireEvent('dragstart', this, e);
21725     },
21726
21727     clearStart : function() {
21728         if(this.timer){
21729             clearTimeout(this.timer);
21730             delete this.timer;
21731         }
21732     },
21733
21734     stopSelect : function(e) {
21735         e.stopEvent();
21736         return false;
21737     },
21738     
21739     
21740     onBeforeStart : function(e) {
21741
21742     },
21743
21744     
21745     onStart : function(xy) {
21746
21747     },
21748
21749     
21750     onDrag : function(e) {
21751
21752     },
21753
21754     
21755     onEnd : function(e) {
21756
21757     },
21758
21759     
21760     getDragTarget : function(){
21761         return this.dragTarget;
21762     },
21763
21764     getDragCt : function(){
21765         return this.el;
21766     },
21767
21768     getXY : function(constrain){
21769         return constrain ?
21770                this.constrainModes[constrain].call(this, this.lastXY) : this.lastXY;
21771     },
21772
21773     getOffset : function(constrain){
21774         var xy = this.getXY(constrain),
21775             s = this.startXY;
21776         return [s[0]-xy[0], s[1]-xy[1]];
21777     },
21778
21779     constrainModes: {
21780         'point' : function(xy){
21781
21782             if(!this.elRegion){
21783                 this.elRegion = this.getDragCt().getRegion();
21784             }
21785
21786             var dr = this.dragRegion;
21787
21788             dr.left = xy[0];
21789             dr.top = xy[1];
21790             dr.right = xy[0];
21791             dr.bottom = xy[1];
21792
21793             dr.constrainTo(this.elRegion);
21794
21795             return [dr.left, dr.top];
21796         }
21797     }
21798 });
21799 Ext.dd.ScrollManager = function(){
21800     var ddm = Ext.dd.DragDropMgr;
21801     var els = {};
21802     var dragEl = null;
21803     var proc = {};
21804     
21805     var onStop = function(e){
21806         dragEl = null;
21807         clearProc();
21808     };
21809     
21810     var triggerRefresh = function(){
21811         if(ddm.dragCurrent){
21812              ddm.refreshCache(ddm.dragCurrent.groups);
21813         }
21814     };
21815     
21816     var doScroll = function(){
21817         if(ddm.dragCurrent){
21818             var dds = Ext.dd.ScrollManager;
21819             var inc = proc.el.ddScrollConfig ?
21820                       proc.el.ddScrollConfig.increment : dds.increment;
21821             if(!dds.animate){
21822                 if(proc.el.scroll(proc.dir, inc)){
21823                     triggerRefresh();
21824                 }
21825             }else{
21826                 proc.el.scroll(proc.dir, inc, true, dds.animDuration, triggerRefresh);
21827             }
21828         }
21829     };
21830     
21831     var clearProc = function(){
21832         if(proc.id){
21833             clearInterval(proc.id);
21834         }
21835         proc.id = 0;
21836         proc.el = null;
21837         proc.dir = "";
21838     };
21839
21840     var startProc = function(el, dir){
21841         clearProc();
21842         proc.el = el;
21843         proc.dir = dir;
21844         var group = el.ddScrollConfig ? el.ddScrollConfig.ddGroup : undefined,
21845             freq  = (el.ddScrollConfig && el.ddScrollConfig.frequency)
21846                   ? el.ddScrollConfig.frequency
21847                   : Ext.dd.ScrollManager.frequency;
21848
21849         if (group === undefined || ddm.dragCurrent.ddGroup == group) {
21850             proc.id = setInterval(doScroll, freq);
21851         }
21852     };
21853     
21854     var onFire = function(e, isDrop){
21855         if(isDrop || !ddm.dragCurrent){ return; }
21856         var dds = Ext.dd.ScrollManager;
21857         if(!dragEl || dragEl != ddm.dragCurrent){
21858             dragEl = ddm.dragCurrent;
21859             
21860             dds.refreshCache();
21861         }
21862         
21863         var xy = Ext.lib.Event.getXY(e);
21864         var pt = new Ext.lib.Point(xy[0], xy[1]);
21865         for(var id in els){
21866             var el = els[id], r = el._region;
21867             var c = el.ddScrollConfig ? el.ddScrollConfig : dds;
21868             if(r && r.contains(pt) && el.isScrollable()){
21869                 if(r.bottom - pt.y <= c.vthresh){
21870                     if(proc.el != el){
21871                         startProc(el, "down");
21872                     }
21873                     return;
21874                 }else if(r.right - pt.x <= c.hthresh){
21875                     if(proc.el != el){
21876                         startProc(el, "left");
21877                     }
21878                     return;
21879                 }else if(pt.y - r.top <= c.vthresh){
21880                     if(proc.el != el){
21881                         startProc(el, "up");
21882                     }
21883                     return;
21884                 }else if(pt.x - r.left <= c.hthresh){
21885                     if(proc.el != el){
21886                         startProc(el, "right");
21887                     }
21888                     return;
21889                 }
21890             }
21891         }
21892         clearProc();
21893     };
21894     
21895     ddm.fireEvents = ddm.fireEvents.createSequence(onFire, ddm);
21896     ddm.stopDrag = ddm.stopDrag.createSequence(onStop, ddm);
21897     
21898     return {
21899         
21900         register : function(el){
21901             if(Ext.isArray(el)){
21902                 for(var i = 0, len = el.length; i < len; i++) {
21903                         this.register(el[i]);
21904                 }
21905             }else{
21906                 el = Ext.get(el);
21907                 els[el.id] = el;
21908             }
21909         },
21910         
21911         
21912         unregister : function(el){
21913             if(Ext.isArray(el)){
21914                 for(var i = 0, len = el.length; i < len; i++) {
21915                         this.unregister(el[i]);
21916                 }
21917             }else{
21918                 el = Ext.get(el);
21919                 delete els[el.id];
21920             }
21921         },
21922         
21923         
21924         vthresh : 25,
21925         
21926         hthresh : 25,
21927
21928         
21929         increment : 100,
21930         
21931         
21932         frequency : 500,
21933         
21934         
21935         animate: true,
21936         
21937         
21938         animDuration: .4,
21939         
21940         
21941         ddGroup: undefined,
21942         
21943         
21944         refreshCache : function(){
21945             for(var id in els){
21946                 if(typeof els[id] == 'object'){ 
21947                     els[id]._region = els[id].getRegion();
21948                 }
21949             }
21950         }
21951     };
21952 }();
21953 Ext.dd.Registry = function(){
21954     var elements = {}; 
21955     var handles = {}; 
21956     var autoIdSeed = 0;
21957
21958     var getId = function(el, autogen){
21959         if(typeof el == "string"){
21960             return el;
21961         }
21962         var id = el.id;
21963         if(!id && autogen !== false){
21964             id = "extdd-" + (++autoIdSeed);
21965             el.id = id;
21966         }
21967         return id;
21968     };
21969     
21970     return {
21971     
21972         register : function(el, data){
21973             data = data || {};
21974             if(typeof el == "string"){
21975                 el = document.getElementById(el);
21976             }
21977             data.ddel = el;
21978             elements[getId(el)] = data;
21979             if(data.isHandle !== false){
21980                 handles[data.ddel.id] = data;
21981             }
21982             if(data.handles){
21983                 var hs = data.handles;
21984                 for(var i = 0, len = hs.length; i < len; i++){
21985                         handles[getId(hs[i])] = data;
21986                 }
21987             }
21988         },
21989
21990     
21991         unregister : function(el){
21992             var id = getId(el, false);
21993             var data = elements[id];
21994             if(data){
21995                 delete elements[id];
21996                 if(data.handles){
21997                     var hs = data.handles;
21998                     for(var i = 0, len = hs.length; i < len; i++){
21999                         delete handles[getId(hs[i], false)];
22000                     }
22001                 }
22002             }
22003         },
22004
22005     
22006         getHandle : function(id){
22007             if(typeof id != "string"){ 
22008                 id = id.id;
22009             }
22010             return handles[id];
22011         },
22012
22013     
22014         getHandleFromEvent : function(e){
22015             var t = Ext.lib.Event.getTarget(e);
22016             return t ? handles[t.id] : null;
22017         },
22018
22019     
22020         getTarget : function(id){
22021             if(typeof id != "string"){ 
22022                 id = id.id;
22023             }
22024             return elements[id];
22025         },
22026
22027     
22028         getTargetFromEvent : function(e){
22029             var t = Ext.lib.Event.getTarget(e);
22030             return t ? elements[t.id] || handles[t.id] : null;
22031         }
22032     };
22033 }();
22034 Ext.dd.StatusProxy = function(config){
22035     Ext.apply(this, config);
22036     this.id = this.id || Ext.id();
22037     this.el = new Ext.Layer({
22038         dh: {
22039             id: this.id, tag: "div", cls: "x-dd-drag-proxy "+this.dropNotAllowed, children: [
22040                 {tag: "div", cls: "x-dd-drop-icon"},
22041                 {tag: "div", cls: "x-dd-drag-ghost"}
22042             ]
22043         }, 
22044         shadow: !config || config.shadow !== false
22045     });
22046     this.ghost = Ext.get(this.el.dom.childNodes[1]);
22047     this.dropStatus = this.dropNotAllowed;
22048 };
22049
22050 Ext.dd.StatusProxy.prototype = {
22051     
22052     dropAllowed : "x-dd-drop-ok",
22053     
22054     dropNotAllowed : "x-dd-drop-nodrop",
22055
22056     
22057     setStatus : function(cssClass){
22058         cssClass = cssClass || this.dropNotAllowed;
22059         if(this.dropStatus != cssClass){
22060             this.el.replaceClass(this.dropStatus, cssClass);
22061             this.dropStatus = cssClass;
22062         }
22063     },
22064
22065     
22066     reset : function(clearGhost){
22067         this.el.dom.className = "x-dd-drag-proxy " + this.dropNotAllowed;
22068         this.dropStatus = this.dropNotAllowed;
22069         if(clearGhost){
22070             this.ghost.update("");
22071         }
22072     },
22073
22074     
22075     update : function(html){
22076         if(typeof html == "string"){
22077             this.ghost.update(html);
22078         }else{
22079             this.ghost.update("");
22080             html.style.margin = "0";
22081             this.ghost.dom.appendChild(html);
22082         }
22083         var el = this.ghost.dom.firstChild; 
22084         if(el){
22085             Ext.fly(el).setStyle('float', 'none');
22086         }
22087     },
22088
22089     
22090     getEl : function(){
22091         return this.el;
22092     },
22093
22094     
22095     getGhost : function(){
22096         return this.ghost;
22097     },
22098
22099     
22100     hide : function(clear){
22101         this.el.hide();
22102         if(clear){
22103             this.reset(true);
22104         }
22105     },
22106
22107     
22108     stop : function(){
22109         if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){
22110             this.anim.stop();
22111         }
22112     },
22113
22114     
22115     show : function(){
22116         this.el.show();
22117     },
22118
22119     
22120     sync : function(){
22121         this.el.sync();
22122     },
22123
22124     
22125     repair : function(xy, callback, scope){
22126         this.callback = callback;
22127         this.scope = scope;
22128         if(xy && this.animRepair !== false){
22129             this.el.addClass("x-dd-drag-repair");
22130             this.el.hideUnders(true);
22131             this.anim = this.el.shift({
22132                 duration: this.repairDuration || .5,
22133                 easing: 'easeOut',
22134                 xy: xy,
22135                 stopFx: true,
22136                 callback: this.afterRepair,
22137                 scope: this
22138             });
22139         }else{
22140             this.afterRepair();
22141         }
22142     },
22143
22144     
22145     afterRepair : function(){
22146         this.hide(true);
22147         if(typeof this.callback == "function"){
22148             this.callback.call(this.scope || this);
22149         }
22150         this.callback = null;
22151         this.scope = null;
22152     },
22153     
22154     destroy: function(){
22155         Ext.destroy(this.ghost, this.el);    
22156     }
22157 };
22158 Ext.dd.DragSource = function(el, config){
22159     this.el = Ext.get(el);
22160     if(!this.dragData){
22161         this.dragData = {};
22162     }
22163     
22164     Ext.apply(this, config);
22165     
22166     if(!this.proxy){
22167         this.proxy = new Ext.dd.StatusProxy();
22168     }
22169     Ext.dd.DragSource.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group, 
22170           {dragElId : this.proxy.id, resizeFrame: false, isTarget: false, scroll: this.scroll === true});
22171     
22172     this.dragging = false;
22173 };
22174
22175 Ext.extend(Ext.dd.DragSource, Ext.dd.DDProxy, {
22176     
22177     
22178     dropAllowed : "x-dd-drop-ok",
22179     
22180     dropNotAllowed : "x-dd-drop-nodrop",
22181
22182     
22183     getDragData : function(e){
22184         return this.dragData;
22185     },
22186
22187     
22188     onDragEnter : function(e, id){
22189         var target = Ext.dd.DragDropMgr.getDDById(id);
22190         this.cachedTarget = target;
22191         if(this.beforeDragEnter(target, e, id) !== false){
22192             if(target.isNotifyTarget){
22193                 var status = target.notifyEnter(this, e, this.dragData);
22194                 this.proxy.setStatus(status);
22195             }else{
22196                 this.proxy.setStatus(this.dropAllowed);
22197             }
22198             
22199             if(this.afterDragEnter){
22200                 
22201                 this.afterDragEnter(target, e, id);
22202             }
22203         }
22204     },
22205
22206     
22207     beforeDragEnter : function(target, e, id){
22208         return true;
22209     },
22210
22211     
22212     alignElWithMouse: function() {
22213         Ext.dd.DragSource.superclass.alignElWithMouse.apply(this, arguments);
22214         this.proxy.sync();
22215     },
22216
22217     
22218     onDragOver : function(e, id){
22219         var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
22220         if(this.beforeDragOver(target, e, id) !== false){
22221             if(target.isNotifyTarget){
22222                 var status = target.notifyOver(this, e, this.dragData);
22223                 this.proxy.setStatus(status);
22224             }
22225
22226             if(this.afterDragOver){
22227                 
22228                 this.afterDragOver(target, e, id);
22229             }
22230         }
22231     },
22232
22233     
22234     beforeDragOver : function(target, e, id){
22235         return true;
22236     },
22237
22238     
22239     onDragOut : function(e, id){
22240         var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
22241         if(this.beforeDragOut(target, e, id) !== false){
22242             if(target.isNotifyTarget){
22243                 target.notifyOut(this, e, this.dragData);
22244             }
22245             this.proxy.reset();
22246             if(this.afterDragOut){
22247                 
22248                 this.afterDragOut(target, e, id);
22249             }
22250         }
22251         this.cachedTarget = null;
22252     },
22253
22254     
22255     beforeDragOut : function(target, e, id){
22256         return true;
22257     },
22258     
22259     
22260     onDragDrop : function(e, id){
22261         var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
22262         if(this.beforeDragDrop(target, e, id) !== false){
22263             if(target.isNotifyTarget){
22264                 if(target.notifyDrop(this, e, this.dragData)){ 
22265                     this.onValidDrop(target, e, id);
22266                 }else{
22267                     this.onInvalidDrop(target, e, id);
22268                 }
22269             }else{
22270                 this.onValidDrop(target, e, id);
22271             }
22272             
22273             if(this.afterDragDrop){
22274                 
22275                 this.afterDragDrop(target, e, id);
22276             }
22277         }
22278         delete this.cachedTarget;
22279     },
22280
22281     
22282     beforeDragDrop : function(target, e, id){
22283         return true;
22284     },
22285
22286     
22287     onValidDrop : function(target, e, id){
22288         this.hideProxy();
22289         if(this.afterValidDrop){
22290             
22291             this.afterValidDrop(target, e, id);
22292         }
22293     },
22294
22295     
22296     getRepairXY : function(e, data){
22297         return this.el.getXY();  
22298     },
22299
22300     
22301     onInvalidDrop : function(target, e, id){
22302         this.beforeInvalidDrop(target, e, id);
22303         if(this.cachedTarget){
22304             if(this.cachedTarget.isNotifyTarget){
22305                 this.cachedTarget.notifyOut(this, e, this.dragData);
22306             }
22307             this.cacheTarget = null;
22308         }
22309         this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);
22310
22311         if(this.afterInvalidDrop){
22312             
22313             this.afterInvalidDrop(e, id);
22314         }
22315     },
22316
22317     
22318     afterRepair : function(){
22319         if(Ext.enableFx){
22320             this.el.highlight(this.hlColor || "c3daf9");
22321         }
22322         this.dragging = false;
22323     },
22324
22325     
22326     beforeInvalidDrop : function(target, e, id){
22327         return true;
22328     },
22329
22330     
22331     handleMouseDown : function(e){
22332         if(this.dragging) {
22333             return;
22334         }
22335         var data = this.getDragData(e);
22336         if(data && this.onBeforeDrag(data, e) !== false){
22337             this.dragData = data;
22338             this.proxy.stop();
22339             Ext.dd.DragSource.superclass.handleMouseDown.apply(this, arguments);
22340         } 
22341     },
22342
22343     
22344     onBeforeDrag : function(data, e){
22345         return true;
22346     },
22347
22348     
22349     onStartDrag : Ext.emptyFn,
22350
22351     
22352     startDrag : function(x, y){
22353         this.proxy.reset();
22354         this.dragging = true;
22355         this.proxy.update("");
22356         this.onInitDrag(x, y);
22357         this.proxy.show();
22358     },
22359
22360     
22361     onInitDrag : function(x, y){
22362         var clone = this.el.dom.cloneNode(true);
22363         clone.id = Ext.id(); 
22364         this.proxy.update(clone);
22365         this.onStartDrag(x, y);
22366         return true;
22367     },
22368
22369     
22370     getProxy : function(){
22371         return this.proxy;  
22372     },
22373
22374     
22375     hideProxy : function(){
22376         this.proxy.hide();  
22377         this.proxy.reset(true);
22378         this.dragging = false;
22379     },
22380
22381     
22382     triggerCacheRefresh : function(){
22383         Ext.dd.DDM.refreshCache(this.groups);
22384     },
22385
22386     
22387     b4EndDrag: function(e) {
22388     },
22389
22390     
22391     endDrag : function(e){
22392         this.onEndDrag(this.dragData, e);
22393     },
22394
22395     
22396     onEndDrag : function(data, e){
22397     },
22398     
22399     
22400     autoOffset : function(x, y) {
22401         this.setDelta(-12, -20);
22402     },
22403     
22404     destroy: function(){
22405         Ext.dd.DragSource.superclass.destroy.call(this);
22406         Ext.destroy(this.proxy);
22407     }
22408 });
22409 Ext.dd.DropTarget = Ext.extend(Ext.dd.DDTarget, {
22410     
22411     constructor : function(el, config){
22412         this.el = Ext.get(el);
22413     
22414         Ext.apply(this, config);
22415     
22416         if(this.containerScroll){
22417             Ext.dd.ScrollManager.register(this.el);
22418         }
22419     
22420         Ext.dd.DropTarget.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group, 
22421               {isTarget: true});        
22422     },
22423     
22424     
22425     
22426     
22427     dropAllowed : "x-dd-drop-ok",
22428     
22429     dropNotAllowed : "x-dd-drop-nodrop",
22430
22431     
22432     isTarget : true,
22433
22434     
22435     isNotifyTarget : true,
22436
22437     
22438     notifyEnter : function(dd, e, data){
22439         if(this.overClass){
22440             this.el.addClass(this.overClass);
22441         }
22442         return this.dropAllowed;
22443     },
22444
22445     
22446     notifyOver : function(dd, e, data){
22447         return this.dropAllowed;
22448     },
22449
22450     
22451     notifyOut : function(dd, e, data){
22452         if(this.overClass){
22453             this.el.removeClass(this.overClass);
22454         }
22455     },
22456
22457     
22458     notifyDrop : function(dd, e, data){
22459         return false;
22460     },
22461     
22462     destroy : function(){
22463         Ext.dd.DropTarget.superclass.destroy.call(this);
22464         if(this.containerScroll){
22465             Ext.dd.ScrollManager.unregister(this.el);
22466         }
22467     }
22468 });
22469 Ext.dd.DragZone = Ext.extend(Ext.dd.DragSource, {
22470     
22471     constructor : function(el, config){
22472         Ext.dd.DragZone.superclass.constructor.call(this, el, config);
22473         if(this.containerScroll){
22474             Ext.dd.ScrollManager.register(this.el);
22475         }
22476     },
22477     
22478     
22479     
22480     
22481
22482     
22483     getDragData : function(e){
22484         return Ext.dd.Registry.getHandleFromEvent(e);
22485     },
22486     
22487     
22488     onInitDrag : function(x, y){
22489         this.proxy.update(this.dragData.ddel.cloneNode(true));
22490         this.onStartDrag(x, y);
22491         return true;
22492     },
22493     
22494     
22495     afterRepair : function(){
22496         if(Ext.enableFx){
22497             Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
22498         }
22499         this.dragging = false;
22500     },
22501
22502     
22503     getRepairXY : function(e){
22504         return Ext.Element.fly(this.dragData.ddel).getXY();  
22505     },
22506     
22507     destroy : function(){
22508         Ext.dd.DragZone.superclass.destroy.call(this);
22509         if(this.containerScroll){
22510             Ext.dd.ScrollManager.unregister(this.el);
22511         }
22512     }
22513 });
22514 Ext.dd.DropZone = function(el, config){
22515     Ext.dd.DropZone.superclass.constructor.call(this, el, config);
22516 };
22517
22518 Ext.extend(Ext.dd.DropZone, Ext.dd.DropTarget, {
22519     
22520     getTargetFromEvent : function(e){
22521         return Ext.dd.Registry.getTargetFromEvent(e);
22522     },
22523
22524     
22525     onNodeEnter : function(n, dd, e, data){
22526         
22527     },
22528
22529     
22530     onNodeOver : function(n, dd, e, data){
22531         return this.dropAllowed;
22532     },
22533
22534     
22535     onNodeOut : function(n, dd, e, data){
22536         
22537     },
22538
22539     
22540     onNodeDrop : function(n, dd, e, data){
22541         return false;
22542     },
22543
22544     
22545     onContainerOver : function(dd, e, data){
22546         return this.dropNotAllowed;
22547     },
22548
22549     
22550     onContainerDrop : function(dd, e, data){
22551         return false;
22552     },
22553
22554     
22555     notifyEnter : function(dd, e, data){
22556         return this.dropNotAllowed;
22557     },
22558
22559     
22560     notifyOver : function(dd, e, data){
22561         var n = this.getTargetFromEvent(e);
22562         if(!n){ 
22563             if(this.lastOverNode){
22564                 this.onNodeOut(this.lastOverNode, dd, e, data);
22565                 this.lastOverNode = null;
22566             }
22567             return this.onContainerOver(dd, e, data);
22568         }
22569         if(this.lastOverNode != n){
22570             if(this.lastOverNode){
22571                 this.onNodeOut(this.lastOverNode, dd, e, data);
22572             }
22573             this.onNodeEnter(n, dd, e, data);
22574             this.lastOverNode = n;
22575         }
22576         return this.onNodeOver(n, dd, e, data);
22577     },
22578
22579     
22580     notifyOut : function(dd, e, data){
22581         if(this.lastOverNode){
22582             this.onNodeOut(this.lastOverNode, dd, e, data);
22583             this.lastOverNode = null;
22584         }
22585     },
22586
22587     
22588     notifyDrop : function(dd, e, data){
22589         if(this.lastOverNode){
22590             this.onNodeOut(this.lastOverNode, dd, e, data);
22591             this.lastOverNode = null;
22592         }
22593         var n = this.getTargetFromEvent(e);
22594         return n ?
22595             this.onNodeDrop(n, dd, e, data) :
22596             this.onContainerDrop(dd, e, data);
22597     },
22598
22599     
22600     triggerCacheRefresh : function(){
22601         Ext.dd.DDM.refreshCache(this.groups);
22602     }  
22603 });
22604 Ext.Element.addMethods({
22605     
22606     initDD : function(group, config, overrides){
22607         var dd = new Ext.dd.DD(Ext.id(this.dom), group, config);
22608         return Ext.apply(dd, overrides);
22609     },
22610
22611     
22612     initDDProxy : function(group, config, overrides){
22613         var dd = new Ext.dd.DDProxy(Ext.id(this.dom), group, config);
22614         return Ext.apply(dd, overrides);
22615     },
22616
22617     
22618     initDDTarget : function(group, config, overrides){
22619         var dd = new Ext.dd.DDTarget(Ext.id(this.dom), group, config);
22620         return Ext.apply(dd, overrides);
22621     }
22622 });
22623
22624 Ext.data.Api = (function() {
22625
22626     
22627     
22628     
22629     
22630     var validActions = {};
22631
22632     return {
22633         
22634         actions : {
22635             create  : 'create',
22636             read    : 'read',
22637             update  : 'update',
22638             destroy : 'destroy'
22639         },
22640
22641         
22642         restActions : {
22643             create  : 'POST',
22644             read    : 'GET',
22645             update  : 'PUT',
22646             destroy : 'DELETE'
22647         },
22648
22649         
22650         isAction : function(action) {
22651             return (Ext.data.Api.actions[action]) ? true : false;
22652         },
22653
22654         
22655         getVerb : function(name) {
22656             if (validActions[name]) {
22657                 return validActions[name];  
22658             }
22659             for (var verb in this.actions) {
22660                 if (this.actions[verb] === name) {
22661                     validActions[name] = verb;
22662                     break;
22663                 }
22664             }
22665             return (validActions[name] !== undefined) ? validActions[name] : null;
22666         },
22667
22668         
22669         isValid : function(api){
22670             var invalid = [];
22671             var crud = this.actions; 
22672             for (var action in api) {
22673                 if (!(action in crud)) {
22674                     invalid.push(action);
22675                 }
22676             }
22677             return (!invalid.length) ? true : invalid;
22678         },
22679
22680         
22681         hasUniqueUrl : function(proxy, verb) {
22682             var url = (proxy.api[verb]) ? proxy.api[verb].url : null;
22683             var unique = true;
22684             for (var action in proxy.api) {
22685                 if ((unique = (action === verb) ? true : (proxy.api[action].url != url) ? true : false) === false) {
22686                     break;
22687                 }
22688             }
22689             return unique;
22690         },
22691
22692         
22693         prepare : function(proxy) {
22694             if (!proxy.api) {
22695                 proxy.api = {}; 
22696             }
22697             for (var verb in this.actions) {
22698                 var action = this.actions[verb];
22699                 proxy.api[action] = proxy.api[action] || proxy.url || proxy.directFn;
22700                 if (typeof(proxy.api[action]) == 'string') {
22701                     proxy.api[action] = {
22702                         url: proxy.api[action],
22703                         method: (proxy.restful === true) ? Ext.data.Api.restActions[action] : undefined
22704                     };
22705                 }
22706             }
22707         },
22708
22709         
22710         restify : function(proxy) {
22711             proxy.restful = true;
22712             for (var verb in this.restActions) {
22713                 proxy.api[this.actions[verb]].method ||
22714                     (proxy.api[this.actions[verb]].method = this.restActions[verb]);
22715             }
22716             
22717             
22718             proxy.onWrite = proxy.onWrite.createInterceptor(function(action, o, response, rs) {
22719                 var reader = o.reader;
22720                 var res = new Ext.data.Response({
22721                     action: action,
22722                     raw: response
22723                 });
22724
22725                 switch (response.status) {
22726                     case 200:   
22727                         return true;
22728                         break;
22729                     case 201:   
22730                         if (Ext.isEmpty(res.raw.responseText)) {
22731                           res.success = true;
22732                         } else {
22733                           
22734                           return true;
22735                         }
22736                         break;
22737                     case 204:  
22738                         res.success = true;
22739                         res.data = null;
22740                         break;
22741                     default:
22742                         return true;
22743                         break;
22744                 }
22745                 if (res.success === true) {
22746                     this.fireEvent("write", this, action, res.data, res, rs, o.request.arg);
22747                 } else {
22748                     this.fireEvent('exception', this, 'remote', action, o, res, rs);
22749                 }
22750                 o.request.callback.call(o.request.scope, res.data, res, res.success);
22751
22752                 return false;   
22753             }, proxy);
22754         }
22755     };
22756 })();
22757
22758
22759 Ext.data.Response = function(params, response) {
22760     Ext.apply(this, params, {
22761         raw: response
22762     });
22763 };
22764 Ext.data.Response.prototype = {
22765     message : null,
22766     success : false,
22767     status : null,
22768     root : null,
22769     raw : null,
22770
22771     getMessage : function() {
22772         return this.message;
22773     },
22774     getSuccess : function() {
22775         return this.success;
22776     },
22777     getStatus : function() {
22778         return this.status;
22779     },
22780     getRoot : function() {
22781         return this.root;
22782     },
22783     getRawResponse : function() {
22784         return this.raw;
22785     }
22786 };
22787
22788
22789 Ext.data.Api.Error = Ext.extend(Ext.Error, {
22790     constructor : function(message, arg) {
22791         this.arg = arg;
22792         Ext.Error.call(this, message);
22793     },
22794     name: 'Ext.data.Api'
22795 });
22796 Ext.apply(Ext.data.Api.Error.prototype, {
22797     lang: {
22798         '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.',
22799         'invalid': 'received an invalid API-configuration.  Please ensure your proxy API-configuration contains only the actions defined in Ext.data.Api.actions',
22800         'invalid-url': 'Invalid url.  Please review your proxy configuration.',
22801         'execute': 'Attempted to execute an unknown action.  Valid API actions are defined in Ext.data.Api.actions"'
22802     }
22803 });
22804
22805
22806
22807
22808 Ext.data.SortTypes = {
22809     
22810     none : function(s){
22811         return s;
22812     },
22813     
22814     
22815     stripTagsRE : /<\/?[^>]+>/gi,
22816     
22817     
22818     asText : function(s){
22819         return String(s).replace(this.stripTagsRE, "");
22820     },
22821     
22822     
22823     asUCText : function(s){
22824         return String(s).toUpperCase().replace(this.stripTagsRE, "");
22825     },
22826     
22827     
22828     asUCString : function(s) {
22829         return String(s).toUpperCase();
22830     },
22831     
22832     
22833     asDate : function(s) {
22834         if(!s){
22835             return 0;
22836         }
22837         if(Ext.isDate(s)){
22838             return s.getTime();
22839         }
22840         return Date.parse(String(s));
22841     },
22842     
22843     
22844     asFloat : function(s) {
22845         var val = parseFloat(String(s).replace(/,/g, ""));
22846         return isNaN(val) ? 0 : val;
22847     },
22848     
22849     
22850     asInt : function(s) {
22851         var val = parseInt(String(s).replace(/,/g, ""), 10);
22852         return isNaN(val) ? 0 : val;
22853     }
22854 };
22855 Ext.data.Record = function(data, id){
22856     
22857     this.id = (id || id === 0) ? id : Ext.data.Record.id(this);
22858     this.data = data || {};
22859 };
22860
22861
22862 Ext.data.Record.create = function(o){
22863     var f = Ext.extend(Ext.data.Record, {});
22864     var p = f.prototype;
22865     p.fields = new Ext.util.MixedCollection(false, function(field){
22866         return field.name;
22867     });
22868     for(var i = 0, len = o.length; i < len; i++){
22869         p.fields.add(new Ext.data.Field(o[i]));
22870     }
22871     f.getField = function(name){
22872         return p.fields.get(name);
22873     };
22874     return f;
22875 };
22876
22877 Ext.data.Record.PREFIX = 'ext-record';
22878 Ext.data.Record.AUTO_ID = 1;
22879 Ext.data.Record.EDIT = 'edit';
22880 Ext.data.Record.REJECT = 'reject';
22881 Ext.data.Record.COMMIT = 'commit';
22882
22883
22884
22885 Ext.data.Record.id = function(rec) {
22886     rec.phantom = true;
22887     return [Ext.data.Record.PREFIX, '-', Ext.data.Record.AUTO_ID++].join('');
22888 };
22889
22890 Ext.data.Record.prototype = {
22891     
22892     
22893     
22894     
22895     
22896     
22897     dirty : false,
22898     editing : false,
22899     error : null,
22900     
22901     modified : null,
22902     
22903     phantom : false,
22904
22905     
22906     join : function(store){
22907         
22908         this.store = store;
22909     },
22910
22911     
22912     set : function(name, value){
22913         var encode = Ext.isPrimitive(value) ? String : Ext.encode;
22914         if(encode(this.data[name]) == encode(value)) {
22915             return;
22916         }        
22917         this.dirty = true;
22918         if(!this.modified){
22919             this.modified = {};
22920         }
22921         if(this.modified[name] === undefined){
22922             this.modified[name] = this.data[name];
22923         }
22924         this.data[name] = value;
22925         if(!this.editing){
22926             this.afterEdit();
22927         }
22928     },
22929
22930     
22931     afterEdit : function(){
22932         if (this.store != undefined && typeof this.store.afterEdit == "function") {
22933             this.store.afterEdit(this);
22934         }
22935     },
22936
22937     
22938     afterReject : function(){
22939         if(this.store){
22940             this.store.afterReject(this);
22941         }
22942     },
22943
22944     
22945     afterCommit : function(){
22946         if(this.store){
22947             this.store.afterCommit(this);
22948         }
22949     },
22950
22951     
22952     get : function(name){
22953         return this.data[name];
22954     },
22955
22956     
22957     beginEdit : function(){
22958         this.editing = true;
22959         this.modified = this.modified || {};
22960     },
22961
22962     
22963     cancelEdit : function(){
22964         this.editing = false;
22965         delete this.modified;
22966     },
22967
22968     
22969     endEdit : function(){
22970         this.editing = false;
22971         if(this.dirty){
22972             this.afterEdit();
22973         }
22974     },
22975
22976     
22977     reject : function(silent){
22978         var m = this.modified;
22979         for(var n in m){
22980             if(typeof m[n] != "function"){
22981                 this.data[n] = m[n];
22982             }
22983         }
22984         this.dirty = false;
22985         delete this.modified;
22986         this.editing = false;
22987         if(silent !== true){
22988             this.afterReject();
22989         }
22990     },
22991
22992     
22993     commit : function(silent){
22994         this.dirty = false;
22995         delete this.modified;
22996         this.editing = false;
22997         if(silent !== true){
22998             this.afterCommit();
22999         }
23000     },
23001
23002     
23003     getChanges : function(){
23004         var m = this.modified, cs = {};
23005         for(var n in m){
23006             if(m.hasOwnProperty(n)){
23007                 cs[n] = this.data[n];
23008             }
23009         }
23010         return cs;
23011     },
23012
23013     
23014     hasError : function(){
23015         return this.error !== null;
23016     },
23017
23018     
23019     clearError : function(){
23020         this.error = null;
23021     },
23022
23023     
23024     copy : function(newId) {
23025         return new this.constructor(Ext.apply({}, this.data), newId || this.id);
23026     },
23027
23028     
23029     isModified : function(fieldName){
23030         return !!(this.modified && this.modified.hasOwnProperty(fieldName));
23031     },
23032
23033     
23034     isValid : function() {
23035         return this.fields.find(function(f) {
23036             return (f.allowBlank === false && Ext.isEmpty(this.data[f.name])) ? true : false;
23037         },this) ? false : true;
23038     },
23039
23040     
23041     markDirty : function(){
23042         this.dirty = true;
23043         if(!this.modified){
23044             this.modified = {};
23045         }
23046         this.fields.each(function(f) {
23047             this.modified[f.name] = this.data[f.name];
23048         },this);
23049     }
23050 };
23051
23052 Ext.StoreMgr = Ext.apply(new Ext.util.MixedCollection(), {
23053     
23054
23055     
23056     register : function(){
23057         for(var i = 0, s; (s = arguments[i]); i++){
23058             this.add(s);
23059         }
23060     },
23061
23062     
23063     unregister : function(){
23064         for(var i = 0, s; (s = arguments[i]); i++){
23065             this.remove(this.lookup(s));
23066         }
23067     },
23068
23069     
23070     lookup : function(id){
23071         if(Ext.isArray(id)){
23072             var fields = ['field1'], expand = !Ext.isArray(id[0]);
23073             if(!expand){
23074                 for(var i = 2, len = id[0].length; i <= len; ++i){
23075                     fields.push('field' + i);
23076                 }
23077             }
23078             return new Ext.data.ArrayStore({
23079                 fields: fields,
23080                 data: id,
23081                 expandData: expand,
23082                 autoDestroy: true,
23083                 autoCreated: true
23084
23085             });
23086         }
23087         return Ext.isObject(id) ? (id.events ? id : Ext.create(id, 'store')) : this.get(id);
23088     },
23089
23090     
23091     getKey : function(o){
23092          return o.storeId;
23093     }
23094 });
23095 Ext.data.Store = Ext.extend(Ext.util.Observable, {
23096     
23097     
23098     
23099     
23100     
23101     
23102     
23103     writer : undefined,
23104     
23105     
23106     
23107     remoteSort : false,
23108
23109     
23110     autoDestroy : false,
23111
23112     
23113     pruneModifiedRecords : false,
23114
23115     
23116     lastOptions : null,
23117
23118     
23119     autoSave : true,
23120
23121     
23122     batch : true,
23123
23124     
23125     restful: false,
23126
23127     
23128     paramNames : undefined,
23129
23130     
23131     defaultParamNames : {
23132         start : 'start',
23133         limit : 'limit',
23134         sort : 'sort',
23135         dir : 'dir'
23136     },
23137
23138     isDestroyed: false,    
23139     hasMultiSort: false,
23140
23141     
23142     batchKey : '_ext_batch_',
23143
23144     constructor : function(config){
23145         
23146         
23147         
23148         
23149         this.data = new Ext.util.MixedCollection(false);
23150         this.data.getKey = function(o){
23151             return o.id;
23152         };
23153         
23154
23155         
23156         this.removed = [];
23157
23158         if(config && config.data){
23159             this.inlineData = config.data;
23160             delete config.data;
23161         }
23162
23163         Ext.apply(this, config);
23164
23165         
23166         this.baseParams = Ext.isObject(this.baseParams) ? this.baseParams : {};
23167
23168         this.paramNames = Ext.applyIf(this.paramNames || {}, this.defaultParamNames);
23169
23170         if((this.url || this.api) && !this.proxy){
23171             this.proxy = new Ext.data.HttpProxy({url: this.url, api: this.api});
23172         }
23173         
23174         if (this.restful === true && this.proxy) {
23175             
23176             
23177             this.batch = false;
23178             Ext.data.Api.restify(this.proxy);
23179         }
23180
23181         if(this.reader){ 
23182             if(!this.recordType){
23183                 this.recordType = this.reader.recordType;
23184             }
23185             if(this.reader.onMetaChange){
23186                 this.reader.onMetaChange = this.reader.onMetaChange.createSequence(this.onMetaChange, this);
23187             }
23188             if (this.writer) { 
23189                 if (this.writer instanceof(Ext.data.DataWriter) === false) {    
23190                     this.writer = this.buildWriter(this.writer);
23191                 }
23192                 this.writer.meta = this.reader.meta;
23193                 this.pruneModifiedRecords = true;
23194             }
23195         }
23196
23197         
23198
23199         if(this.recordType){
23200             
23201             this.fields = this.recordType.prototype.fields;
23202         }
23203         this.modified = [];
23204
23205         this.addEvents(
23206             
23207             'datachanged',
23208             
23209             'metachange',
23210             
23211             'add',
23212             
23213             'remove',
23214             
23215             'update',
23216             
23217             'clear',
23218             
23219             'exception',
23220             
23221             'beforeload',
23222             
23223             'load',
23224             
23225             'loadexception',
23226             
23227             'beforewrite',
23228             
23229             'write',
23230             
23231             'beforesave',
23232             
23233             'save'
23234
23235         );
23236
23237         if(this.proxy){
23238             
23239             this.relayEvents(this.proxy,  ['loadexception', 'exception']);
23240         }
23241         
23242         if (this.writer) {
23243             this.on({
23244                 scope: this,
23245                 add: this.createRecords,
23246                 remove: this.destroyRecord,
23247                 update: this.updateRecord,
23248                 clear: this.onClear
23249             });
23250         }
23251
23252         this.sortToggle = {};
23253         if(this.sortField){
23254             this.setDefaultSort(this.sortField, this.sortDir);
23255         }else if(this.sortInfo){
23256             this.setDefaultSort(this.sortInfo.field, this.sortInfo.direction);
23257         }
23258
23259         Ext.data.Store.superclass.constructor.call(this);
23260
23261         if(this.id){
23262             this.storeId = this.id;
23263             delete this.id;
23264         }
23265         if(this.storeId){
23266             Ext.StoreMgr.register(this);
23267         }
23268         if(this.inlineData){
23269             this.loadData(this.inlineData);
23270             delete this.inlineData;
23271         }else if(this.autoLoad){
23272             this.load.defer(10, this, [
23273                 typeof this.autoLoad == 'object' ?
23274                     this.autoLoad : undefined]);
23275         }
23276         
23277         this.batchCounter = 0;
23278         this.batches = {};
23279     },
23280
23281     
23282     buildWriter : function(config) {
23283         var klass = undefined,
23284             type = (config.format || 'json').toLowerCase();
23285         switch (type) {
23286             case 'json':
23287                 klass = Ext.data.JsonWriter;
23288                 break;
23289             case 'xml':
23290                 klass = Ext.data.XmlWriter;
23291                 break;
23292             default:
23293                 klass = Ext.data.JsonWriter;
23294         }
23295         return new klass(config);
23296     },
23297
23298     
23299     destroy : function(){
23300         if(!this.isDestroyed){
23301             if(this.storeId){
23302                 Ext.StoreMgr.unregister(this);
23303             }
23304             this.clearData();
23305             this.data = null;
23306             Ext.destroy(this.proxy);
23307             this.reader = this.writer = null;
23308             this.purgeListeners();
23309             this.isDestroyed = true;
23310         }
23311     },
23312
23313     
23314     add : function(records) {
23315         var i, record, index;
23316         
23317         records = [].concat(records);
23318         if (records.length < 1) {
23319             return;
23320         }
23321         
23322         for (i = 0, len = records.length; i < len; i++) {
23323             record = records[i];
23324             
23325             record.join(this);
23326             
23327             if (record.dirty || record.phantom) {
23328                 this.modified.push(record);
23329             }
23330         }
23331         
23332         index = this.data.length;
23333         this.data.addAll(records);
23334         
23335         if (this.snapshot) {
23336             this.snapshot.addAll(records);
23337         }
23338         
23339         this.fireEvent('add', this, records, index);
23340     },
23341
23342     
23343     addSorted : function(record){
23344         var index = this.findInsertIndex(record);
23345         this.insert(index, record);
23346     },
23347     
23348     
23349     doUpdate : function(rec){
23350         this.data.replace(rec.id, rec);
23351         if(this.snapshot){
23352             this.snapshot.replace(rec.id, rec);
23353         }
23354         this.fireEvent('update', this, rec, Ext.data.Record.COMMIT);
23355     },
23356
23357     
23358     remove : function(record){
23359         if(Ext.isArray(record)){
23360             Ext.each(record, function(r){
23361                 this.remove(r);
23362             }, this);
23363             return;
23364         }
23365         var index = this.data.indexOf(record);
23366         if(index > -1){
23367             record.join(null);
23368             this.data.removeAt(index);
23369         }
23370         if(this.pruneModifiedRecords){
23371             this.modified.remove(record);
23372         }
23373         if(this.snapshot){
23374             this.snapshot.remove(record);
23375         }
23376         if(index > -1){
23377             this.fireEvent('remove', this, record, index);
23378         }
23379     },
23380
23381     
23382     removeAt : function(index){
23383         this.remove(this.getAt(index));
23384     },
23385
23386     
23387     removeAll : function(silent){
23388         var items = [];
23389         this.each(function(rec){
23390             items.push(rec);
23391         });
23392         this.clearData();
23393         if(this.snapshot){
23394             this.snapshot.clear();
23395         }
23396         if(this.pruneModifiedRecords){
23397             this.modified = [];
23398         }
23399         if (silent !== true) {  
23400             this.fireEvent('clear', this, items);
23401         }
23402     },
23403
23404     
23405     onClear: function(store, records){
23406         Ext.each(records, function(rec, index){
23407             this.destroyRecord(this, rec, index);
23408         }, this);
23409     },
23410
23411     
23412     insert : function(index, records) {
23413         var i, record;
23414         
23415         records = [].concat(records);
23416         for (i = 0, len = records.length; i < len; i++) {
23417             record = records[i];
23418             
23419             this.data.insert(index + i, record);
23420             record.join(this);
23421             
23422             if (record.dirty || record.phantom) {
23423                 this.modified.push(record);
23424             }
23425         }
23426         
23427         if (this.snapshot) {
23428             this.snapshot.addAll(records);
23429         }
23430         
23431         this.fireEvent('add', this, records, index);
23432     },
23433
23434     
23435     indexOf : function(record){
23436         return this.data.indexOf(record);
23437     },
23438
23439     
23440     indexOfId : function(id){
23441         return this.data.indexOfKey(id);
23442     },
23443
23444     
23445     getById : function(id){
23446         return (this.snapshot || this.data).key(id);
23447     },
23448
23449     
23450     getAt : function(index){
23451         return this.data.itemAt(index);
23452     },
23453
23454     
23455     getRange : function(start, end){
23456         return this.data.getRange(start, end);
23457     },
23458
23459     
23460     storeOptions : function(o){
23461         o = Ext.apply({}, o);
23462         delete o.callback;
23463         delete o.scope;
23464         this.lastOptions = o;
23465     },
23466
23467     
23468     clearData: function(){
23469         this.data.each(function(rec) {
23470             rec.join(null);
23471         });
23472         this.data.clear();
23473     },
23474
23475     
23476     load : function(options) {
23477         options = Ext.apply({}, options);
23478         this.storeOptions(options);
23479         if(this.sortInfo && this.remoteSort){
23480             var pn = this.paramNames;
23481             options.params = Ext.apply({}, options.params);
23482             options.params[pn.sort] = this.sortInfo.field;
23483             options.params[pn.dir] = this.sortInfo.direction;
23484         }
23485         try {
23486             return this.execute('read', null, options); 
23487         } catch(e) {
23488             this.handleException(e);
23489             return false;
23490         }
23491     },
23492
23493     
23494     updateRecord : function(store, record, action) {
23495         if (action == Ext.data.Record.EDIT && this.autoSave === true && (!record.phantom || (record.phantom && record.isValid()))) {
23496             this.save();
23497         }
23498     },
23499
23500     
23501     createRecords : function(store, records, index) {
23502         var modified = this.modified,
23503             length   = records.length,
23504             record, i;
23505         
23506         for (i = 0; i < length; i++) {
23507             record = records[i];
23508             
23509             if (record.phantom && record.isValid()) {
23510                 record.markDirty();  
23511                 
23512                 if (modified.indexOf(record) == -1) {
23513                     modified.push(record);
23514                 }
23515             }
23516         }
23517         if (this.autoSave === true) {
23518             this.save();
23519         }
23520     },
23521
23522     
23523     destroyRecord : function(store, record, index) {
23524         if (this.modified.indexOf(record) != -1) {  
23525             this.modified.remove(record);
23526         }
23527         if (!record.phantom) {
23528             this.removed.push(record);
23529
23530             
23531             
23532             
23533             record.lastIndex = index;
23534
23535             if (this.autoSave === true) {
23536                 this.save();
23537             }
23538         }
23539     },
23540
23541     
23542     execute : function(action, rs, options,  batch) {
23543         
23544         if (!Ext.data.Api.isAction(action)) {
23545             throw new Ext.data.Api.Error('execute', action);
23546         }
23547         
23548         options = Ext.applyIf(options||{}, {
23549             params: {}
23550         });
23551         if(batch !== undefined){
23552             this.addToBatch(batch);
23553         }
23554         
23555         
23556         var doRequest = true;
23557
23558         if (action === 'read') {
23559             doRequest = this.fireEvent('beforeload', this, options);
23560             Ext.applyIf(options.params, this.baseParams);
23561         }
23562         else {
23563             
23564             
23565             if (this.writer.listful === true && this.restful !== true) {
23566                 rs = (Ext.isArray(rs)) ? rs : [rs];
23567             }
23568             
23569             else if (Ext.isArray(rs) && rs.length == 1) {
23570                 rs = rs.shift();
23571             }
23572             
23573             if ((doRequest = this.fireEvent('beforewrite', this, action, rs, options)) !== false) {
23574                 this.writer.apply(options.params, this.baseParams, action, rs);
23575             }
23576         }
23577         if (doRequest !== false) {
23578             
23579             if (this.writer && this.proxy.url && !this.proxy.restful && !Ext.data.Api.hasUniqueUrl(this.proxy, action)) {
23580                 options.params.xaction = action;    
23581             }
23582             
23583             
23584             
23585             
23586             
23587             this.proxy.request(Ext.data.Api.actions[action], rs, options.params, this.reader, this.createCallback(action, rs, batch), this, options);
23588         }
23589         return doRequest;
23590     },
23591
23592     
23593     save : function() {
23594         if (!this.writer) {
23595             throw new Ext.data.Store.Error('writer-undefined');
23596         }
23597
23598         var queue = [],
23599             len,
23600             trans,
23601             batch,
23602             data = {},
23603             i;
23604         
23605         if(this.removed.length){
23606             queue.push(['destroy', this.removed]);
23607         }
23608
23609         
23610         var rs = [].concat(this.getModifiedRecords());
23611         if(rs.length){
23612             
23613             var phantoms = [];
23614             for(i = rs.length-1; i >= 0; i--){
23615                 if(rs[i].phantom === true){
23616                     var rec = rs.splice(i, 1).shift();
23617                     if(rec.isValid()){
23618                         phantoms.push(rec);
23619                     }
23620                 }else if(!rs[i].isValid()){ 
23621                     rs.splice(i,1);
23622                 }
23623             }
23624             
23625             if(phantoms.length){
23626                 queue.push(['create', phantoms]);
23627             }
23628
23629             
23630             if(rs.length){
23631                 queue.push(['update', rs]);
23632             }
23633         }
23634         len = queue.length;
23635         if(len){
23636             batch = ++this.batchCounter;
23637             for(i = 0; i < len; ++i){
23638                 trans = queue[i];
23639                 data[trans[0]] = trans[1];
23640             }
23641             if(this.fireEvent('beforesave', this, data) !== false){
23642                 for(i = 0; i < len; ++i){
23643                     trans = queue[i];
23644                     this.doTransaction(trans[0], trans[1], batch);
23645                 }
23646                 return batch;
23647             }
23648         }
23649         return -1;
23650     },
23651
23652     
23653     doTransaction : function(action, rs, batch) {
23654         function transaction(records) {
23655             try{
23656                 this.execute(action, records, undefined, batch);
23657             }catch (e){
23658                 this.handleException(e);
23659             }
23660         }
23661         if(this.batch === false){
23662             for(var i = 0, len = rs.length; i < len; i++){
23663                 transaction.call(this, rs[i]);
23664             }
23665         }else{
23666             transaction.call(this, rs);
23667         }
23668     },
23669
23670     
23671     addToBatch : function(batch){
23672         var b = this.batches,
23673             key = this.batchKey + batch,
23674             o = b[key];
23675
23676         if(!o){
23677             b[key] = o = {
23678                 id: batch,
23679                 count: 0,
23680                 data: {}
23681             };
23682         }
23683         ++o.count;
23684     },
23685
23686     removeFromBatch : function(batch, action, data){
23687         var b = this.batches,
23688             key = this.batchKey + batch,
23689             o = b[key],
23690             arr;
23691
23692
23693         if(o){
23694             arr = o.data[action] || [];
23695             o.data[action] = arr.concat(data);
23696             if(o.count === 1){
23697                 data = o.data;
23698                 delete b[key];
23699                 this.fireEvent('save', this, batch, data);
23700             }else{
23701                 --o.count;
23702             }
23703         }
23704     },
23705
23706     
23707     
23708     createCallback : function(action, rs, batch) {
23709         var actions = Ext.data.Api.actions;
23710         return (action == 'read') ? this.loadRecords : function(data, response, success) {
23711             
23712             this['on' + Ext.util.Format.capitalize(action) + 'Records'](success, rs, [].concat(data));
23713             
23714             if (success === true) {
23715                 this.fireEvent('write', this, action, data, response, rs);
23716             }
23717             this.removeFromBatch(batch, action, data);
23718         };
23719     },
23720
23721     
23722     
23723     
23724     clearModified : function(rs) {
23725         if (Ext.isArray(rs)) {
23726             for (var n=rs.length-1;n>=0;n--) {
23727                 this.modified.splice(this.modified.indexOf(rs[n]), 1);
23728             }
23729         } else {
23730             this.modified.splice(this.modified.indexOf(rs), 1);
23731         }
23732     },
23733
23734     
23735     reMap : function(record) {
23736         if (Ext.isArray(record)) {
23737             for (var i = 0, len = record.length; i < len; i++) {
23738                 this.reMap(record[i]);
23739             }
23740         } else {
23741             delete this.data.map[record._phid];
23742             this.data.map[record.id] = record;
23743             var index = this.data.keys.indexOf(record._phid);
23744             this.data.keys.splice(index, 1, record.id);
23745             delete record._phid;
23746         }
23747     },
23748
23749     
23750     onCreateRecords : function(success, rs, data) {
23751         if (success === true) {
23752             try {
23753                 this.reader.realize(rs, data);
23754                 this.reMap(rs);
23755             }
23756             catch (e) {
23757                 this.handleException(e);
23758                 if (Ext.isArray(rs)) {
23759                     
23760                     this.onCreateRecords(success, rs, data);
23761                 }
23762             }
23763         }
23764     },
23765
23766     
23767     onUpdateRecords : function(success, rs, data) {
23768         if (success === true) {
23769             try {
23770                 this.reader.update(rs, data);
23771             } catch (e) {
23772                 this.handleException(e);
23773                 if (Ext.isArray(rs)) {
23774                     
23775                     this.onUpdateRecords(success, rs, data);
23776                 }
23777             }
23778         }
23779     },
23780
23781     
23782     onDestroyRecords : function(success, rs, data) {
23783         
23784         rs = (rs instanceof Ext.data.Record) ? [rs] : [].concat(rs);
23785         for (var i=0,len=rs.length;i<len;i++) {
23786             this.removed.splice(this.removed.indexOf(rs[i]), 1);
23787         }
23788         if (success === false) {
23789             
23790             
23791             for (i=rs.length-1;i>=0;i--) {
23792                 this.insert(rs[i].lastIndex, rs[i]);    
23793             }
23794         }
23795     },
23796
23797     
23798     handleException : function(e) {
23799         
23800         Ext.handleError(e);
23801     },
23802
23803     
23804     reload : function(options){
23805         this.load(Ext.applyIf(options||{}, this.lastOptions));
23806     },
23807
23808     
23809     
23810     loadRecords : function(o, options, success){
23811         var i;
23812         
23813         if (this.isDestroyed === true) {
23814             return;
23815         }
23816         if(!o || success === false){
23817             if(success !== false){
23818                 this.fireEvent('load', this, [], options);
23819             }
23820             if(options.callback){
23821                 options.callback.call(options.scope || this, [], options, false, o);
23822             }
23823             return;
23824         }
23825         var r = o.records, t = o.totalRecords || r.length;
23826         if(!options || options.add !== true){
23827             if(this.pruneModifiedRecords){
23828                 this.modified = [];
23829             }
23830             for(i = 0, len = r.length; i < len; i++){
23831                 r[i].join(this);
23832             }
23833             if(this.snapshot){
23834                 this.data = this.snapshot;
23835                 delete this.snapshot;
23836             }
23837             this.clearData();
23838             this.data.addAll(r);
23839             this.totalLength = t;
23840             this.applySort();
23841             this.fireEvent('datachanged', this);
23842         }else{
23843             var toAdd = [],
23844                 rec,
23845                 cnt = 0;
23846             for(i = 0, len = r.length; i < len; ++i){
23847                 rec = r[i];
23848                 if(this.indexOfId(rec.id) > -1){
23849                     this.doUpdate(rec);
23850                 }else{
23851                     toAdd.push(rec);
23852                     ++cnt;
23853                 }
23854             }
23855             this.totalLength = Math.max(t, this.data.length + cnt);
23856             this.add(toAdd);
23857         }
23858         this.fireEvent('load', this, r, options);
23859         if(options.callback){
23860             options.callback.call(options.scope || this, r, options, true);
23861         }
23862     },
23863
23864     
23865     loadData : function(o, append){
23866         var r = this.reader.readRecords(o);
23867         this.loadRecords(r, {add: append}, true);
23868     },
23869
23870     
23871     getCount : function(){
23872         return this.data.length || 0;
23873     },
23874
23875     
23876     getTotalCount : function(){
23877         return this.totalLength || 0;
23878     },
23879
23880     
23881     getSortState : function(){
23882         return this.sortInfo;
23883     },
23884
23885     
23886     applySort : function(){
23887         if ((this.sortInfo || this.multiSortInfo) && !this.remoteSort) {
23888             this.sortData();
23889         }
23890     },
23891
23892     
23893     sortData : function() {
23894         var sortInfo  = this.hasMultiSort ? this.multiSortInfo : this.sortInfo,
23895             direction = sortInfo.direction || "ASC",
23896             sorters   = sortInfo.sorters,
23897             sortFns   = [];
23898
23899         
23900         if (!this.hasMultiSort) {
23901             sorters = [{direction: direction, field: sortInfo.field}];
23902         }
23903
23904         
23905         for (var i=0, j = sorters.length; i < j; i++) {
23906             sortFns.push(this.createSortFunction(sorters[i].field, sorters[i].direction));
23907         }
23908         
23909         if (sortFns.length == 0) {
23910             return;
23911         }
23912
23913         
23914         
23915         var directionModifier = direction.toUpperCase() == "DESC" ? -1 : 1;
23916
23917         
23918         var fn = function(r1, r2) {
23919           var result = sortFns[0].call(this, r1, r2);
23920
23921           
23922           if (sortFns.length > 1) {
23923               for (var i=1, j = sortFns.length; i < j; i++) {
23924                   result = result || sortFns[i].call(this, r1, r2);
23925               }
23926           }
23927
23928           return directionModifier * result;
23929         };
23930
23931         
23932         this.data.sort(direction, fn);
23933         if (this.snapshot && this.snapshot != this.data) {
23934             this.snapshot.sort(direction, fn);
23935         }
23936     },
23937
23938     
23939     createSortFunction: function(field, direction) {
23940         direction = direction || "ASC";
23941         var directionModifier = direction.toUpperCase() == "DESC" ? -1 : 1;
23942
23943         var sortType = this.fields.get(field).sortType;
23944
23945         
23946         
23947         return function(r1, r2) {
23948             var v1 = sortType(r1.data[field]),
23949                 v2 = sortType(r2.data[field]);
23950
23951             return directionModifier * (v1 > v2 ? 1 : (v1 < v2 ? -1 : 0));
23952         };
23953     },
23954
23955     
23956     setDefaultSort : function(field, dir) {
23957         dir = dir ? dir.toUpperCase() : 'ASC';
23958         this.sortInfo = {field: field, direction: dir};
23959         this.sortToggle[field] = dir;
23960     },
23961
23962     
23963     sort : function(fieldName, dir) {
23964         if (Ext.isArray(arguments[0])) {
23965             return this.multiSort.call(this, fieldName, dir);
23966         } else {
23967             return this.singleSort(fieldName, dir);
23968         }
23969     },
23970
23971     
23972     singleSort: function(fieldName, dir) {
23973         var field = this.fields.get(fieldName);
23974         if (!field) {
23975             return false;
23976         }
23977
23978         var name       = field.name,
23979             sortInfo   = this.sortInfo || null,
23980             sortToggle = this.sortToggle ? this.sortToggle[name] : null;
23981
23982         if (!dir) {
23983             if (sortInfo && sortInfo.field == name) { 
23984                 dir = (this.sortToggle[name] || 'ASC').toggle('ASC', 'DESC');
23985             } else {
23986                 dir = field.sortDir;
23987             }
23988         }
23989
23990         this.sortToggle[name] = dir;
23991         this.sortInfo = {field: name, direction: dir};
23992         this.hasMultiSort = false;
23993
23994         if (this.remoteSort) {
23995             if (!this.load(this.lastOptions)) {
23996                 if (sortToggle) {
23997                     this.sortToggle[name] = sortToggle;
23998                 }
23999                 if (sortInfo) {
24000                     this.sortInfo = sortInfo;
24001                 }
24002             }
24003         } else {
24004             this.applySort();
24005             this.fireEvent('datachanged', this);
24006         }
24007         return true;
24008     },
24009
24010     
24011     multiSort: function(sorters, direction) {
24012         this.hasMultiSort = true;
24013         direction = direction || "ASC";
24014
24015         
24016         if (this.multiSortInfo && direction == this.multiSortInfo.direction) {
24017             direction = direction.toggle("ASC", "DESC");
24018         }
24019
24020         
24021         this.multiSortInfo = {
24022             sorters  : sorters,
24023             direction: direction
24024         };
24025         
24026         if (this.remoteSort) {
24027             this.singleSort(sorters[0].field, sorters[0].direction);
24028
24029         } else {
24030             this.applySort();
24031             this.fireEvent('datachanged', this);
24032         }
24033     },
24034
24035     
24036     each : function(fn, scope){
24037         this.data.each(fn, scope);
24038     },
24039
24040     
24041     getModifiedRecords : function(){
24042         return this.modified;
24043     },
24044
24045     
24046     sum : function(property, start, end){
24047         var rs = this.data.items, v = 0;
24048         start = start || 0;
24049         end = (end || end === 0) ? end : rs.length-1;
24050
24051         for(var i = start; i <= end; i++){
24052             v += (rs[i].data[property] || 0);
24053         }
24054         return v;
24055     },
24056
24057     
24058     createFilterFn : function(property, value, anyMatch, caseSensitive, exactMatch){
24059         if(Ext.isEmpty(value, false)){
24060             return false;
24061         }
24062         value = this.data.createValueMatcher(value, anyMatch, caseSensitive, exactMatch);
24063         return function(r) {
24064             return value.test(r.data[property]);
24065         };
24066     },
24067
24068     
24069     createMultipleFilterFn: function(filters) {
24070         return function(record) {
24071             var isMatch = true;
24072
24073             for (var i=0, j = filters.length; i < j; i++) {
24074                 var filter = filters[i],
24075                     fn     = filter.fn,
24076                     scope  = filter.scope;
24077
24078                 isMatch = isMatch && fn.call(scope, record);
24079             }
24080
24081             return isMatch;
24082         };
24083     },
24084
24085     
24086     filter : function(property, value, anyMatch, caseSensitive, exactMatch){
24087         var fn;
24088         
24089         if (Ext.isObject(property)) {
24090             property = [property];
24091         }
24092
24093         if (Ext.isArray(property)) {
24094             var filters = [];
24095
24096             
24097             for (var i=0, j = property.length; i < j; i++) {
24098                 var filter = property[i],
24099                     func   = filter.fn,
24100                     scope  = filter.scope || this;
24101
24102                 
24103                 if (!Ext.isFunction(func)) {
24104                     func = this.createFilterFn(filter.property, filter.value, filter.anyMatch, filter.caseSensitive, filter.exactMatch);
24105                 }
24106
24107                 filters.push({fn: func, scope: scope});
24108             }
24109
24110             fn = this.createMultipleFilterFn(filters);
24111         } else {
24112             
24113             fn = this.createFilterFn(property, value, anyMatch, caseSensitive, exactMatch);
24114         }
24115
24116         return fn ? this.filterBy(fn) : this.clearFilter();
24117     },
24118
24119     
24120     filterBy : function(fn, scope){
24121         this.snapshot = this.snapshot || this.data;
24122         this.data = this.queryBy(fn, scope || this);
24123         this.fireEvent('datachanged', this);
24124     },
24125
24126     
24127     clearFilter : function(suppressEvent){
24128         if(this.isFiltered()){
24129             this.data = this.snapshot;
24130             delete this.snapshot;
24131             if(suppressEvent !== true){
24132                 this.fireEvent('datachanged', this);
24133             }
24134         }
24135     },
24136
24137     
24138     isFiltered : function(){
24139         return !!this.snapshot && this.snapshot != this.data;
24140     },
24141
24142     
24143     query : function(property, value, anyMatch, caseSensitive){
24144         var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
24145         return fn ? this.queryBy(fn) : this.data.clone();
24146     },
24147
24148     
24149     queryBy : function(fn, scope){
24150         var data = this.snapshot || this.data;
24151         return data.filterBy(fn, scope||this);
24152     },
24153
24154     
24155     find : function(property, value, start, anyMatch, caseSensitive){
24156         var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
24157         return fn ? this.data.findIndexBy(fn, null, start) : -1;
24158     },
24159
24160     
24161     findExact: function(property, value, start){
24162         return this.data.findIndexBy(function(rec){
24163             return rec.get(property) === value;
24164         }, this, start);
24165     },
24166
24167     
24168     findBy : function(fn, scope, start){
24169         return this.data.findIndexBy(fn, scope, start);
24170     },
24171
24172     
24173     collect : function(dataIndex, allowNull, bypassFilter){
24174         var d = (bypassFilter === true && this.snapshot) ?
24175                 this.snapshot.items : this.data.items;
24176         var v, sv, r = [], l = {};
24177         for(var i = 0, len = d.length; i < len; i++){
24178             v = d[i].data[dataIndex];
24179             sv = String(v);
24180             if((allowNull || !Ext.isEmpty(v)) && !l[sv]){
24181                 l[sv] = true;
24182                 r[r.length] = v;
24183             }
24184         }
24185         return r;
24186     },
24187
24188     
24189     afterEdit : function(record){
24190         if(this.modified.indexOf(record) == -1){
24191             this.modified.push(record);
24192         }
24193         this.fireEvent('update', this, record, Ext.data.Record.EDIT);
24194     },
24195
24196     
24197     afterReject : function(record){
24198         this.modified.remove(record);
24199         this.fireEvent('update', this, record, Ext.data.Record.REJECT);
24200     },
24201
24202     
24203     afterCommit : function(record){
24204         this.modified.remove(record);
24205         this.fireEvent('update', this, record, Ext.data.Record.COMMIT);
24206     },
24207
24208     
24209     commitChanges : function(){
24210         var modified = this.modified.slice(0),
24211             length   = modified.length,
24212             i;
24213             
24214         for (i = 0; i < length; i++){
24215             modified[i].commit();
24216         }
24217         
24218         this.modified = [];
24219         this.removed  = [];
24220     },
24221
24222     
24223     rejectChanges : function() {
24224         var modified = this.modified.slice(0),
24225             removed  = this.removed.slice(0).reverse(),
24226             mLength  = modified.length,
24227             rLength  = removed.length,
24228             i;
24229         
24230         for (i = 0; i < mLength; i++) {
24231             modified[i].reject();
24232         }
24233         
24234         for (i = 0; i < rLength; i++) {
24235             this.insert(removed[i].lastIndex || 0, removed[i]);
24236             removed[i].reject();
24237         }
24238         
24239         this.modified = [];
24240         this.removed  = [];
24241     },
24242
24243     
24244     onMetaChange : function(meta){
24245         this.recordType = this.reader.recordType;
24246         this.fields = this.recordType.prototype.fields;
24247         delete this.snapshot;
24248         if(this.reader.meta.sortInfo){
24249             this.sortInfo = this.reader.meta.sortInfo;
24250         }else if(this.sortInfo  && !this.fields.get(this.sortInfo.field)){
24251             delete this.sortInfo;
24252         }
24253         if(this.writer){
24254             this.writer.meta = this.reader.meta;
24255         }
24256         this.modified = [];
24257         this.fireEvent('metachange', this, this.reader.meta);
24258     },
24259
24260     
24261     findInsertIndex : function(record){
24262         this.suspendEvents();
24263         var data = this.data.clone();
24264         this.data.add(record);
24265         this.applySort();
24266         var index = this.data.indexOf(record);
24267         this.data = data;
24268         this.resumeEvents();
24269         return index;
24270     },
24271
24272     
24273     setBaseParam : function (name, value){
24274         this.baseParams = this.baseParams || {};
24275         this.baseParams[name] = value;
24276     }
24277 });
24278
24279 Ext.reg('store', Ext.data.Store);
24280
24281
24282 Ext.data.Store.Error = Ext.extend(Ext.Error, {
24283     name: 'Ext.data.Store'
24284 });
24285 Ext.apply(Ext.data.Store.Error.prototype, {
24286     lang: {
24287         'writer-undefined' : 'Attempted to execute a write-action without a DataWriter installed.'
24288     }
24289 });
24290
24291 Ext.data.Field = Ext.extend(Object, {
24292     
24293     constructor : function(config){
24294         if(Ext.isString(config)){
24295             config = {name: config};
24296         }
24297         Ext.apply(this, config);
24298         
24299         var types = Ext.data.Types,
24300             st = this.sortType,
24301             t;
24302
24303         if(this.type){
24304             if(Ext.isString(this.type)){
24305                 this.type = Ext.data.Types[this.type.toUpperCase()] || types.AUTO;
24306             }
24307         }else{
24308             this.type = types.AUTO;
24309         }
24310
24311         
24312         if(Ext.isString(st)){
24313             this.sortType = Ext.data.SortTypes[st];
24314         }else if(Ext.isEmpty(st)){
24315             this.sortType = this.type.sortType;
24316         }
24317
24318         if(!this.convert){
24319             this.convert = this.type.convert;
24320         }
24321     },
24322     
24323     
24324     
24325     
24326     
24327     dateFormat: null,
24328     
24329     
24330     useNull: false,
24331     
24332     
24333     defaultValue: "",
24334     
24335     mapping: null,
24336     
24337     sortType : null,
24338     
24339     sortDir : "ASC",
24340     
24341     allowBlank : true
24342 });
24343
24344 Ext.data.DataReader = function(meta, recordType){
24345     
24346     this.meta = meta;
24347     
24348     this.recordType = Ext.isArray(recordType) ?
24349         Ext.data.Record.create(recordType) : recordType;
24350
24351     
24352     if (this.recordType){
24353         this.buildExtractors();
24354     }
24355 };
24356
24357 Ext.data.DataReader.prototype = {
24358     
24359     
24360     getTotal: Ext.emptyFn,
24361     
24362     getRoot: Ext.emptyFn,
24363     
24364     getMessage: Ext.emptyFn,
24365     
24366     getSuccess: Ext.emptyFn,
24367     
24368     getId: Ext.emptyFn,
24369     
24370     buildExtractors : Ext.emptyFn,
24371     
24372     extractValues : Ext.emptyFn,
24373
24374     
24375     realize: function(rs, data){
24376         if (Ext.isArray(rs)) {
24377             for (var i = rs.length - 1; i >= 0; i--) {
24378                 
24379                 if (Ext.isArray(data)) {
24380                     this.realize(rs.splice(i,1).shift(), data.splice(i,1).shift());
24381                 }
24382                 else {
24383                     
24384                     
24385                     this.realize(rs.splice(i,1).shift(), data);
24386                 }
24387             }
24388         }
24389         else {
24390             
24391             if (Ext.isArray(data) && data.length == 1) {
24392                 data = data.shift();
24393             }
24394             if (!this.isData(data)) {
24395                 
24396                 
24397                 throw new Ext.data.DataReader.Error('realize', rs);
24398             }
24399             rs.phantom = false; 
24400             rs._phid = rs.id;  
24401             rs.id = this.getId(data);
24402             rs.data = data;
24403
24404             rs.commit();
24405         }
24406     },
24407
24408     
24409     update : function(rs, data) {
24410         if (Ext.isArray(rs)) {
24411             for (var i=rs.length-1; i >= 0; i--) {
24412                 if (Ext.isArray(data)) {
24413                     this.update(rs.splice(i,1).shift(), data.splice(i,1).shift());
24414                 }
24415                 else {
24416                     
24417                     
24418                     this.update(rs.splice(i,1).shift(), data);
24419                 }
24420             }
24421         }
24422         else {
24423             
24424             if (Ext.isArray(data) && data.length == 1) {
24425                 data = data.shift();
24426             }
24427             if (this.isData(data)) {
24428                 rs.data = Ext.apply(rs.data, data);
24429             }
24430             rs.commit();
24431         }
24432     },
24433
24434     
24435     extractData : function(root, returnRecords) {
24436         
24437         var rawName = (this instanceof Ext.data.JsonReader) ? 'json' : 'node';
24438
24439         var rs = [];
24440
24441         
24442         
24443         if (this.isData(root) && !(this instanceof Ext.data.XmlReader)) {
24444             root = [root];
24445         }
24446         var f       = this.recordType.prototype.fields,
24447             fi      = f.items,
24448             fl      = f.length,
24449             rs      = [];
24450         if (returnRecords === true) {
24451             var Record = this.recordType;
24452             for (var i = 0; i < root.length; i++) {
24453                 var n = root[i];
24454                 var record = new Record(this.extractValues(n, fi, fl), this.getId(n));
24455                 record[rawName] = n;    
24456                 rs.push(record);
24457             }
24458         }
24459         else {
24460             for (var i = 0; i < root.length; i++) {
24461                 var data = this.extractValues(root[i], fi, fl);
24462                 data[this.meta.idProperty] = this.getId(root[i]);
24463                 rs.push(data);
24464             }
24465         }
24466         return rs;
24467     },
24468
24469     
24470     isData : function(data) {
24471         return (data && Ext.isObject(data) && !Ext.isEmpty(this.getId(data))) ? true : false;
24472     },
24473
24474     
24475     onMetaChange : function(meta){
24476         delete this.ef;
24477         this.meta = meta;
24478         this.recordType = Ext.data.Record.create(meta.fields);
24479         this.buildExtractors();
24480     }
24481 };
24482
24483
24484 Ext.data.DataReader.Error = Ext.extend(Ext.Error, {
24485     constructor : function(message, arg) {
24486         this.arg = arg;
24487         Ext.Error.call(this, message);
24488     },
24489     name: 'Ext.data.DataReader'
24490 });
24491 Ext.apply(Ext.data.DataReader.Error.prototype, {
24492     lang : {
24493         'update': "#update received invalid data from server.  Please see docs for DataReader#update and review your DataReader configuration.",
24494         'realize': "#realize was called with invalid remote-data.  Please see the docs for DataReader#realize and review your DataReader configuration.",
24495         'invalid-response': "#readResponse received an invalid response from the server."
24496     }
24497 });
24498
24499 Ext.data.DataWriter = function(config){
24500     Ext.apply(this, config);
24501 };
24502 Ext.data.DataWriter.prototype = {
24503
24504     
24505     writeAllFields : false,
24506     
24507     listful : false,    
24508
24509     
24510     apply : function(params, baseParams, action, rs) {
24511         var data    = [],
24512         renderer    = action + 'Record';
24513         
24514         if (Ext.isArray(rs)) {
24515             Ext.each(rs, function(rec){
24516                 data.push(this[renderer](rec));
24517             }, this);
24518         }
24519         else if (rs instanceof Ext.data.Record) {
24520             data = this[renderer](rs);
24521         }
24522         this.render(params, baseParams, data);
24523     },
24524
24525     
24526     render : Ext.emptyFn,
24527
24528     
24529     updateRecord : Ext.emptyFn,
24530
24531     
24532     createRecord : Ext.emptyFn,
24533
24534     
24535     destroyRecord : Ext.emptyFn,
24536
24537     
24538     toHash : function(rec, config) {
24539         var map = rec.fields.map,
24540             data = {},
24541             raw = (this.writeAllFields === false && rec.phantom === false) ? rec.getChanges() : rec.data,
24542             m;
24543         Ext.iterate(raw, function(prop, value){
24544             if((m = map[prop])){
24545                 data[m.mapping ? m.mapping : m.name] = value;
24546             }
24547         });
24548         
24549         
24550         
24551         if (rec.phantom) {
24552             if (rec.fields.containsKey(this.meta.idProperty) && Ext.isEmpty(rec.data[this.meta.idProperty])) {
24553                 delete data[this.meta.idProperty];
24554             }
24555         } else {
24556             data[this.meta.idProperty] = rec.id;
24557         }
24558         return data;
24559     },
24560
24561     
24562     toArray : function(data) {
24563         var fields = [];
24564         Ext.iterate(data, function(k, v) {fields.push({name: k, value: v});},this);
24565         return fields;
24566     }
24567 };
24568 Ext.data.DataProxy = function(conn){
24569     
24570     
24571     conn = conn || {};
24572
24573     
24574     
24575     
24576
24577     this.api     = conn.api;
24578     this.url     = conn.url;
24579     this.restful = conn.restful;
24580     this.listeners = conn.listeners;
24581
24582     
24583     this.prettyUrls = conn.prettyUrls;
24584
24585     
24586
24587     this.addEvents(
24588         
24589         'exception',
24590         
24591         'beforeload',
24592         
24593         'load',
24594         
24595         'loadexception',
24596         
24597         'beforewrite',
24598         
24599         'write'
24600     );
24601     Ext.data.DataProxy.superclass.constructor.call(this);
24602
24603     
24604     try {
24605         Ext.data.Api.prepare(this);
24606     } catch (e) {
24607         if (e instanceof Ext.data.Api.Error) {
24608             e.toConsole();
24609         }
24610     }
24611     
24612     Ext.data.DataProxy.relayEvents(this, ['beforewrite', 'write', 'exception']);
24613 };
24614
24615 Ext.extend(Ext.data.DataProxy, Ext.util.Observable, {
24616     
24617     restful: false,
24618
24619     
24620     setApi : function() {
24621         if (arguments.length == 1) {
24622             var valid = Ext.data.Api.isValid(arguments[0]);
24623             if (valid === true) {
24624                 this.api = arguments[0];
24625             }
24626             else {
24627                 throw new Ext.data.Api.Error('invalid', valid);
24628             }
24629         }
24630         else if (arguments.length == 2) {
24631             if (!Ext.data.Api.isAction(arguments[0])) {
24632                 throw new Ext.data.Api.Error('invalid', arguments[0]);
24633             }
24634             this.api[arguments[0]] = arguments[1];
24635         }
24636         Ext.data.Api.prepare(this);
24637     },
24638
24639     
24640     isApiAction : function(action) {
24641         return (this.api[action]) ? true : false;
24642     },
24643
24644     
24645     request : function(action, rs, params, reader, callback, scope, options) {
24646         if (!this.api[action] && !this.load) {
24647             throw new Ext.data.DataProxy.Error('action-undefined', action);
24648         }
24649         params = params || {};
24650         if ((action === Ext.data.Api.actions.read) ? this.fireEvent("beforeload", this, params) : this.fireEvent("beforewrite", this, action, rs, params) !== false) {
24651             this.doRequest.apply(this, arguments);
24652         }
24653         else {
24654             callback.call(scope || this, null, options, false);
24655         }
24656     },
24657
24658
24659     
24660     load : null,
24661
24662     
24663     doRequest : function(action, rs, params, reader, callback, scope, options) {
24664         
24665         
24666         
24667         this.load(params, reader, callback, scope, options);
24668     },
24669
24670     
24671     onRead : Ext.emptyFn,
24672     
24673     onWrite : Ext.emptyFn,
24674     
24675     buildUrl : function(action, record) {
24676         record = record || null;
24677
24678         
24679         
24680         
24681         var url = (this.conn && this.conn.url) ? this.conn.url : (this.api[action]) ? this.api[action].url : this.url;
24682         if (!url) {
24683             throw new Ext.data.Api.Error('invalid-url', action);
24684         }
24685
24686         
24687         
24688         
24689         
24690         
24691         
24692         var provides = null;
24693         var m = url.match(/(.*)(\.json|\.xml|\.html)$/);
24694         if (m) {
24695             provides = m[2];    
24696             url      = m[1];    
24697         }
24698         
24699         if ((this.restful === true || this.prettyUrls === true) && record instanceof Ext.data.Record && !record.phantom) {
24700             url += '/' + record.id;
24701         }
24702         return (provides === null) ? url : url + provides;
24703     },
24704
24705     
24706     destroy: function(){
24707         this.purgeListeners();
24708     }
24709 });
24710
24711
24712
24713 Ext.apply(Ext.data.DataProxy, Ext.util.Observable.prototype);
24714 Ext.util.Observable.call(Ext.data.DataProxy);
24715
24716
24717 Ext.data.DataProxy.Error = Ext.extend(Ext.Error, {
24718     constructor : function(message, arg) {
24719         this.arg = arg;
24720         Ext.Error.call(this, message);
24721     },
24722     name: 'Ext.data.DataProxy'
24723 });
24724 Ext.apply(Ext.data.DataProxy.Error.prototype, {
24725     lang: {
24726         'action-undefined': "DataProxy attempted to execute an API-action but found an undefined url / function.  Please review your Proxy url/api-configuration.",
24727         'api-invalid': 'Recieved an invalid API-configuration.  Please ensure your proxy API-configuration contains only the actions from Ext.data.Api.actions.'
24728     }
24729 });
24730
24731
24732
24733 Ext.data.Request = function(params) {
24734     Ext.apply(this, params);
24735 };
24736 Ext.data.Request.prototype = {
24737     
24738     action : undefined,
24739     
24740     rs : undefined,
24741     
24742     params: undefined,
24743     
24744     callback : Ext.emptyFn,
24745     
24746     scope : undefined,
24747     
24748     reader : undefined
24749 };
24750
24751 Ext.data.Response = function(params) {
24752     Ext.apply(this, params);
24753 };
24754 Ext.data.Response.prototype = {
24755     
24756     action: undefined,
24757     
24758     success : undefined,
24759     
24760     message : undefined,
24761     
24762     data: undefined,
24763     
24764     raw: undefined,
24765     
24766     records: undefined
24767 };
24768
24769 Ext.data.ScriptTagProxy = function(config){
24770     Ext.apply(this, config);
24771
24772     Ext.data.ScriptTagProxy.superclass.constructor.call(this, config);
24773
24774     this.head = document.getElementsByTagName("head")[0];
24775
24776     
24777 };
24778
24779 Ext.data.ScriptTagProxy.TRANS_ID = 1000;
24780
24781 Ext.extend(Ext.data.ScriptTagProxy, Ext.data.DataProxy, {
24782     
24783     
24784     timeout : 30000,
24785     
24786     callbackParam : "callback",
24787     
24788     nocache : true,
24789
24790     
24791     doRequest : function(action, rs, params, reader, callback, scope, arg) {
24792         var p = Ext.urlEncode(Ext.apply(params, this.extraParams));
24793
24794         var url = this.buildUrl(action, rs);
24795         if (!url) {
24796             throw new Ext.data.Api.Error('invalid-url', url);
24797         }
24798         url = Ext.urlAppend(url, p);
24799
24800         if(this.nocache){
24801             url = Ext.urlAppend(url, '_dc=' + (new Date().getTime()));
24802         }
24803         var transId = ++Ext.data.ScriptTagProxy.TRANS_ID;
24804         var trans = {
24805             id : transId,
24806             action: action,
24807             cb : "stcCallback"+transId,
24808             scriptId : "stcScript"+transId,
24809             params : params,
24810             arg : arg,
24811             url : url,
24812             callback : callback,
24813             scope : scope,
24814             reader : reader
24815         };
24816         window[trans.cb] = this.createCallback(action, rs, trans);
24817         url += String.format("&{0}={1}", this.callbackParam, trans.cb);
24818         if(this.autoAbort !== false){
24819             this.abort();
24820         }
24821
24822         trans.timeoutId = this.handleFailure.defer(this.timeout, this, [trans]);
24823
24824         var script = document.createElement("script");
24825         script.setAttribute("src", url);
24826         script.setAttribute("type", "text/javascript");
24827         script.setAttribute("id", trans.scriptId);
24828         this.head.appendChild(script);
24829
24830         this.trans = trans;
24831     },
24832
24833     
24834     createCallback : function(action, rs, trans) {
24835         var self = this;
24836         return function(res) {
24837             self.trans = false;
24838             self.destroyTrans(trans, true);
24839             if (action === Ext.data.Api.actions.read) {
24840                 self.onRead.call(self, action, trans, res);
24841             } else {
24842                 self.onWrite.call(self, action, trans, res, rs);
24843             }
24844         };
24845     },
24846     
24847     onRead : function(action, trans, res) {
24848         var result;
24849         try {
24850             result = trans.reader.readRecords(res);
24851         }catch(e){
24852             
24853             this.fireEvent("loadexception", this, trans, res, e);
24854
24855             this.fireEvent('exception', this, 'response', action, trans, res, e);
24856             trans.callback.call(trans.scope||window, null, trans.arg, false);
24857             return;
24858         }
24859         if (result.success === false) {
24860             
24861             this.fireEvent('loadexception', this, trans, res);
24862
24863             this.fireEvent('exception', this, 'remote', action, trans, res, null);
24864         } else {
24865             this.fireEvent("load", this, res, trans.arg);
24866         }
24867         trans.callback.call(trans.scope||window, result, trans.arg, result.success);
24868     },
24869     
24870     onWrite : function(action, trans, response, rs) {
24871         var reader = trans.reader;
24872         try {
24873             
24874             var res = reader.readResponse(action, response);
24875         } catch (e) {
24876             this.fireEvent('exception', this, 'response', action, trans, res, e);
24877             trans.callback.call(trans.scope||window, null, res, false);
24878             return;
24879         }
24880         if(!res.success === true){
24881             this.fireEvent('exception', this, 'remote', action, trans, res, rs);
24882             trans.callback.call(trans.scope||window, null, res, false);
24883             return;
24884         }
24885         this.fireEvent("write", this, action, res.data, res, rs, trans.arg );
24886         trans.callback.call(trans.scope||window, res.data, res, true);
24887     },
24888
24889     
24890     isLoading : function(){
24891         return this.trans ? true : false;
24892     },
24893
24894     
24895     abort : function(){
24896         if(this.isLoading()){
24897             this.destroyTrans(this.trans);
24898         }
24899     },
24900
24901     
24902     destroyTrans : function(trans, isLoaded){
24903         this.head.removeChild(document.getElementById(trans.scriptId));
24904         clearTimeout(trans.timeoutId);
24905         if(isLoaded){
24906             window[trans.cb] = undefined;
24907             try{
24908                 delete window[trans.cb];
24909             }catch(e){}
24910         }else{
24911             
24912             window[trans.cb] = function(){
24913                 window[trans.cb] = undefined;
24914                 try{
24915                     delete window[trans.cb];
24916                 }catch(e){}
24917             };
24918         }
24919     },
24920
24921     
24922     handleFailure : function(trans){
24923         this.trans = false;
24924         this.destroyTrans(trans, false);
24925         if (trans.action === Ext.data.Api.actions.read) {
24926             
24927             this.fireEvent("loadexception", this, null, trans.arg);
24928         }
24929
24930         this.fireEvent('exception', this, 'response', trans.action, {
24931             response: null,
24932             options: trans.arg
24933         });
24934         trans.callback.call(trans.scope||window, null, trans.arg, false);
24935     },
24936
24937     
24938     destroy: function(){
24939         this.abort();
24940         Ext.data.ScriptTagProxy.superclass.destroy.call(this);
24941     }
24942 });
24943 Ext.data.HttpProxy = function(conn){
24944     Ext.data.HttpProxy.superclass.constructor.call(this, conn);
24945
24946     
24947     this.conn = conn;
24948
24949     
24950     
24951     
24952     
24953     this.conn.url = null;
24954
24955     this.useAjax = !conn || !conn.events;
24956
24957     
24958     var actions = Ext.data.Api.actions;
24959     this.activeRequest = {};
24960     for (var verb in actions) {
24961         this.activeRequest[actions[verb]] = undefined;
24962     }
24963 };
24964
24965 Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {
24966     
24967     getConnection : function() {
24968         return this.useAjax ? Ext.Ajax : this.conn;
24969     },
24970
24971     
24972     setUrl : function(url, makePermanent) {
24973         this.conn.url = url;
24974         if (makePermanent === true) {
24975             this.url = url;
24976             this.api = null;
24977             Ext.data.Api.prepare(this);
24978         }
24979     },
24980
24981     
24982     doRequest : function(action, rs, params, reader, cb, scope, arg) {
24983         var  o = {
24984             method: (this.api[action]) ? this.api[action]['method'] : undefined,
24985             request: {
24986                 callback : cb,
24987                 scope : scope,
24988                 arg : arg
24989             },
24990             reader: reader,
24991             callback : this.createCallback(action, rs),
24992             scope: this
24993         };
24994
24995         
24996         
24997         if (params.jsonData) {
24998             o.jsonData = params.jsonData;
24999         } else if (params.xmlData) {
25000             o.xmlData = params.xmlData;
25001         } else {
25002             o.params = params || {};
25003         }
25004         
25005         
25006         
25007         this.conn.url = this.buildUrl(action, rs);
25008
25009         if(this.useAjax){
25010
25011             Ext.applyIf(o, this.conn);
25012
25013             
25014             if (this.activeRequest[action]) {
25015                 
25016                 
25017                 
25018                 
25019                 
25020             }
25021             this.activeRequest[action] = Ext.Ajax.request(o);
25022         }else{
25023             this.conn.request(o);
25024         }
25025         
25026         this.conn.url = null;
25027     },
25028
25029     
25030     createCallback : function(action, rs) {
25031         return function(o, success, response) {
25032             this.activeRequest[action] = undefined;
25033             if (!success) {
25034                 if (action === Ext.data.Api.actions.read) {
25035                     
25036                     
25037                     this.fireEvent('loadexception', this, o, response);
25038                 }
25039                 this.fireEvent('exception', this, 'response', action, o, response);
25040                 o.request.callback.call(o.request.scope, null, o.request.arg, false);
25041                 return;
25042             }
25043             if (action === Ext.data.Api.actions.read) {
25044                 this.onRead(action, o, response);
25045             } else {
25046                 this.onWrite(action, o, response, rs);
25047             }
25048         };
25049     },
25050
25051     
25052     onRead : function(action, o, response) {
25053         var result;
25054         try {
25055             result = o.reader.read(response);
25056         }catch(e){
25057             
25058             
25059             this.fireEvent('loadexception', this, o, response, e);
25060
25061             this.fireEvent('exception', this, 'response', action, o, response, e);
25062             o.request.callback.call(o.request.scope, null, o.request.arg, false);
25063             return;
25064         }
25065         if (result.success === false) {
25066             
25067             
25068             this.fireEvent('loadexception', this, o, response);
25069
25070             
25071             var res = o.reader.readResponse(action, response);
25072             this.fireEvent('exception', this, 'remote', action, o, res, null);
25073         }
25074         else {
25075             this.fireEvent('load', this, o, o.request.arg);
25076         }
25077         
25078         
25079         
25080         o.request.callback.call(o.request.scope, result, o.request.arg, result.success);
25081     },
25082     
25083     onWrite : function(action, o, response, rs) {
25084         var reader = o.reader;
25085         var res;
25086         try {
25087             res = reader.readResponse(action, response);
25088         } catch (e) {
25089             this.fireEvent('exception', this, 'response', action, o, response, e);
25090             o.request.callback.call(o.request.scope, null, o.request.arg, false);
25091             return;
25092         }
25093         if (res.success === true) {
25094             this.fireEvent('write', this, action, res.data, res, rs, o.request.arg);
25095         } else {
25096             this.fireEvent('exception', this, 'remote', action, o, res, rs);
25097         }
25098         
25099         
25100         
25101         o.request.callback.call(o.request.scope, res.data, res, res.success);
25102     },
25103
25104     
25105     destroy: function(){
25106         if(!this.useAjax){
25107             this.conn.abort();
25108         }else if(this.activeRequest){
25109             var actions = Ext.data.Api.actions;
25110             for (var verb in actions) {
25111                 if(this.activeRequest[actions[verb]]){
25112                     Ext.Ajax.abort(this.activeRequest[actions[verb]]);
25113                 }
25114             }
25115         }
25116         Ext.data.HttpProxy.superclass.destroy.call(this);
25117     }
25118 });
25119 Ext.data.MemoryProxy = function(data){
25120     
25121     var api = {};
25122     api[Ext.data.Api.actions.read] = true;
25123     Ext.data.MemoryProxy.superclass.constructor.call(this, {
25124         api: api
25125     });
25126     this.data = data;
25127 };
25128
25129 Ext.extend(Ext.data.MemoryProxy, Ext.data.DataProxy, {
25130     
25131
25132        
25133     doRequest : function(action, rs, params, reader, callback, scope, arg) {
25134         
25135         params = params || {};
25136         var result;
25137         try {
25138             result = reader.readRecords(this.data);
25139         }catch(e){
25140             
25141             this.fireEvent("loadexception", this, null, arg, e);
25142
25143             this.fireEvent('exception', this, 'response', action, arg, null, e);
25144             callback.call(scope, null, arg, false);
25145             return;
25146         }
25147         callback.call(scope, result, arg, true);
25148     }
25149 });
25150 Ext.data.Types = new function(){
25151     var st = Ext.data.SortTypes;
25152     Ext.apply(this, {
25153         
25154         stripRe: /[\$,%]/g,
25155         
25156         
25157         AUTO: {
25158             convert: function(v){ return v; },
25159             sortType: st.none,
25160             type: 'auto'
25161         },
25162
25163         
25164         STRING: {
25165             convert: function(v){ return (v === undefined || v === null) ? '' : String(v); },
25166             sortType: st.asUCString,
25167             type: 'string'
25168         },
25169
25170         
25171         INT: {
25172             convert: function(v){
25173                 return v !== undefined && v !== null && v !== '' ?
25174                     parseInt(String(v).replace(Ext.data.Types.stripRe, ''), 10) : (this.useNull ? null : 0);
25175             },
25176             sortType: st.none,
25177             type: 'int'
25178         },
25179         
25180         
25181         FLOAT: {
25182             convert: function(v){
25183                 return v !== undefined && v !== null && v !== '' ?
25184                     parseFloat(String(v).replace(Ext.data.Types.stripRe, ''), 10) : (this.useNull ? null : 0);
25185             },
25186             sortType: st.none,
25187             type: 'float'
25188         },
25189         
25190         
25191         BOOL: {
25192             convert: function(v){ return v === true || v === 'true' || v == 1; },
25193             sortType: st.none,
25194             type: 'bool'
25195         },
25196         
25197         
25198         DATE: {
25199             convert: function(v){
25200                 var df = this.dateFormat;
25201                 if(!v){
25202                     return null;
25203                 }
25204                 if(Ext.isDate(v)){
25205                     return v;
25206                 }
25207                 if(df){
25208                     if(df == 'timestamp'){
25209                         return new Date(v*1000);
25210                     }
25211                     if(df == 'time'){
25212                         return new Date(parseInt(v, 10));
25213                     }
25214                     return Date.parseDate(v, df);
25215                 }
25216                 var parsed = Date.parse(v);
25217                 return parsed ? new Date(parsed) : null;
25218             },
25219             sortType: st.asDate,
25220             type: 'date'
25221         }
25222     });
25223     
25224     Ext.apply(this, {
25225         
25226         BOOLEAN: this.BOOL,
25227         
25228         INTEGER: this.INT,
25229         
25230         NUMBER: this.FLOAT    
25231     });
25232 };
25233 Ext.data.JsonWriter = Ext.extend(Ext.data.DataWriter, {
25234     
25235     encode : true,
25236     
25237     encodeDelete: false,
25238     
25239     constructor : function(config){
25240         Ext.data.JsonWriter.superclass.constructor.call(this, config);    
25241     },
25242
25243     
25244     render : function(params, baseParams, data) {
25245         if (this.encode === true) {
25246             
25247             Ext.apply(params, baseParams);
25248             params[this.meta.root] = Ext.encode(data);
25249         } else {
25250             
25251             var jdata = Ext.apply({}, baseParams);
25252             jdata[this.meta.root] = data;
25253             params.jsonData = jdata;
25254         }
25255     },
25256     
25257     createRecord : function(rec) {
25258        return this.toHash(rec);
25259     },
25260     
25261     updateRecord : function(rec) {
25262         return this.toHash(rec);
25263
25264     },
25265     
25266     destroyRecord : function(rec){
25267         if(this.encodeDelete){
25268             var data = {};
25269             data[this.meta.idProperty] = rec.id;
25270             return data;
25271         }else{
25272             return rec.id;
25273         }
25274     }
25275 });
25276 Ext.data.JsonReader = function(meta, recordType){
25277     meta = meta || {};
25278     
25279     
25280     
25281     
25282     Ext.applyIf(meta, {
25283         idProperty: 'id',
25284         successProperty: 'success',
25285         totalProperty: 'total'
25286     });
25287
25288     Ext.data.JsonReader.superclass.constructor.call(this, meta, recordType || meta.fields);
25289 };
25290 Ext.extend(Ext.data.JsonReader, Ext.data.DataReader, {
25291     
25292     
25293     read : function(response){
25294         var json = response.responseText;
25295         var o = Ext.decode(json);
25296         if(!o) {
25297             throw {message: 'JsonReader.read: Json object not found'};
25298         }
25299         return this.readRecords(o);
25300     },
25301
25302     
25303     
25304     readResponse : function(action, response) {
25305         var o = (response.responseText !== undefined) ? Ext.decode(response.responseText) : response;
25306         if(!o) {
25307             throw new Ext.data.JsonReader.Error('response');
25308         }
25309
25310         var root = this.getRoot(o);
25311         if (action === Ext.data.Api.actions.create) {
25312             var def = Ext.isDefined(root);
25313             if (def && Ext.isEmpty(root)) {
25314                 throw new Ext.data.JsonReader.Error('root-empty', this.meta.root);
25315             }
25316             else if (!def) {
25317                 throw new Ext.data.JsonReader.Error('root-undefined-response', this.meta.root);
25318             }
25319         }
25320
25321         
25322         var res = new Ext.data.Response({
25323             action: action,
25324             success: this.getSuccess(o),
25325             data: (root) ? this.extractData(root, false) : [],
25326             message: this.getMessage(o),
25327             raw: o
25328         });
25329
25330         
25331         if (Ext.isEmpty(res.success)) {
25332             throw new Ext.data.JsonReader.Error('successProperty-response', this.meta.successProperty);
25333         }
25334         return res;
25335     },
25336
25337     
25338     readRecords : function(o){
25339         
25340         this.jsonData = o;
25341         if(o.metaData){
25342             this.onMetaChange(o.metaData);
25343         }
25344         var s = this.meta, Record = this.recordType,
25345             f = Record.prototype.fields, fi = f.items, fl = f.length, v;
25346
25347         var root = this.getRoot(o), c = root.length, totalRecords = c, success = true;
25348         if(s.totalProperty){
25349             v = parseInt(this.getTotal(o), 10);
25350             if(!isNaN(v)){
25351                 totalRecords = v;
25352             }
25353         }
25354         if(s.successProperty){
25355             v = this.getSuccess(o);
25356             if(v === false || v === 'false'){
25357                 success = false;
25358             }
25359         }
25360
25361         
25362         return {
25363             success : success,
25364             records : this.extractData(root, true), 
25365             totalRecords : totalRecords
25366         };
25367     },
25368
25369     
25370     buildExtractors : function() {
25371         if(this.ef){
25372             return;
25373         }
25374         var s = this.meta, Record = this.recordType,
25375             f = Record.prototype.fields, fi = f.items, fl = f.length;
25376
25377         if(s.totalProperty) {
25378             this.getTotal = this.createAccessor(s.totalProperty);
25379         }
25380         if(s.successProperty) {
25381             this.getSuccess = this.createAccessor(s.successProperty);
25382         }
25383         if (s.messageProperty) {
25384             this.getMessage = this.createAccessor(s.messageProperty);
25385         }
25386         this.getRoot = s.root ? this.createAccessor(s.root) : function(p){return p;};
25387         if (s.id || s.idProperty) {
25388             var g = this.createAccessor(s.id || s.idProperty);
25389             this.getId = function(rec) {
25390                 var r = g(rec);
25391                 return (r === undefined || r === '') ? null : r;
25392             };
25393         } else {
25394             this.getId = function(){return null;};
25395         }
25396         var ef = [];
25397         for(var i = 0; i < fl; i++){
25398             f = fi[i];
25399             var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;
25400             ef.push(this.createAccessor(map));
25401         }
25402         this.ef = ef;
25403     },
25404
25405     
25406     simpleAccess : function(obj, subsc) {
25407         return obj[subsc];
25408     },
25409
25410     
25411     createAccessor : function(){
25412         var re = /[\[\.]/;
25413         return function(expr) {
25414             if(Ext.isEmpty(expr)){
25415                 return Ext.emptyFn;
25416             }
25417             if(Ext.isFunction(expr)){
25418                 return expr;
25419             }
25420             var i = String(expr).search(re);
25421             if(i >= 0){
25422                 return new Function('obj', 'return obj' + (i > 0 ? '.' : '') + expr);
25423             }
25424             return function(obj){
25425                 return obj[expr];
25426             };
25427
25428         };
25429     }(),
25430
25431     
25432     extractValues : function(data, items, len) {
25433         var f, values = {};
25434         for(var j = 0; j < len; j++){
25435             f = items[j];
25436             var v = this.ef[j](data);
25437             values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue, data);
25438         }
25439         return values;
25440     }
25441 });
25442
25443
25444 Ext.data.JsonReader.Error = Ext.extend(Ext.Error, {
25445     constructor : function(message, arg) {
25446         this.arg = arg;
25447         Ext.Error.call(this, message);
25448     },
25449     name : 'Ext.data.JsonReader'
25450 });
25451 Ext.apply(Ext.data.JsonReader.Error.prototype, {
25452     lang: {
25453         'response': 'An error occurred while json-decoding your server response',
25454         '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.',
25455         '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.',
25456         '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.',
25457         '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.'
25458     }
25459 });
25460
25461 Ext.data.ArrayReader = Ext.extend(Ext.data.JsonReader, {
25462     
25463     
25464     
25465     
25466     readRecords : function(o){
25467         this.arrayData = o;
25468         var s = this.meta,
25469             sid = s ? Ext.num(s.idIndex, s.id) : null,
25470             recordType = this.recordType,
25471             fields = recordType.prototype.fields,
25472             records = [],
25473             success = true,
25474             v;
25475
25476         var root = this.getRoot(o);
25477
25478         for(var i = 0, len = root.length; i < len; i++) {
25479             var n = root[i],
25480                 values = {},
25481                 id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null);
25482             for(var j = 0, jlen = fields.length; j < jlen; j++) {
25483                 var f = fields.items[j],
25484                     k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j;
25485                 v = n[k] !== undefined ? n[k] : f.defaultValue;
25486                 v = f.convert(v, n);
25487                 values[f.name] = v;
25488             }
25489             var record = new recordType(values, id);
25490             record.json = n;
25491             records[records.length] = record;
25492         }
25493
25494         var totalRecords = records.length;
25495
25496         if(s.totalProperty) {
25497             v = parseInt(this.getTotal(o), 10);
25498             if(!isNaN(v)) {
25499                 totalRecords = v;
25500             }
25501         }
25502         if(s.successProperty){
25503             v = this.getSuccess(o);
25504             if(v === false || v === 'false'){
25505                 success = false;
25506             }
25507         }
25508
25509         return {
25510             success : success,
25511             records : records,
25512             totalRecords : totalRecords
25513         };
25514     }
25515 });
25516 Ext.data.ArrayStore = Ext.extend(Ext.data.Store, {
25517     
25518     constructor: function(config){
25519         Ext.data.ArrayStore.superclass.constructor.call(this, Ext.apply(config, {
25520             reader: new Ext.data.ArrayReader(config)
25521         }));
25522     },
25523
25524     loadData : function(data, append){
25525         if(this.expandData === true){
25526             var r = [];
25527             for(var i = 0, len = data.length; i < len; i++){
25528                 r[r.length] = [data[i]];
25529             }
25530             data = r;
25531         }
25532         Ext.data.ArrayStore.superclass.loadData.call(this, data, append);
25533     }
25534 });
25535 Ext.reg('arraystore', Ext.data.ArrayStore);
25536
25537
25538 Ext.data.SimpleStore = Ext.data.ArrayStore;
25539 Ext.reg('simplestore', Ext.data.SimpleStore);
25540 Ext.data.JsonStore = Ext.extend(Ext.data.Store, {
25541     
25542     constructor: function(config){
25543         Ext.data.JsonStore.superclass.constructor.call(this, Ext.apply(config, {
25544             reader: new Ext.data.JsonReader(config)
25545         }));
25546     }
25547 });
25548 Ext.reg('jsonstore', Ext.data.JsonStore);
25549 Ext.data.XmlWriter = function(params) {
25550     Ext.data.XmlWriter.superclass.constructor.apply(this, arguments);
25551     
25552     this.tpl = (typeof(this.tpl) === 'string') ? new Ext.XTemplate(this.tpl).compile() : this.tpl.compile();
25553 };
25554 Ext.extend(Ext.data.XmlWriter, Ext.data.DataWriter, {
25555     
25556     documentRoot: 'xrequest',
25557     
25558     forceDocumentRoot: false,
25559     
25560     root: 'records',
25561     
25562     xmlVersion : '1.0',
25563     
25564     xmlEncoding: 'ISO-8859-15',
25565     
25566     
25567     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>',
25568
25569
25570     
25571     render : function(params, baseParams, data) {
25572         baseParams = this.toArray(baseParams);
25573         params.xmlData = this.tpl.applyTemplate({
25574             version: this.xmlVersion,
25575             encoding: this.xmlEncoding,
25576             documentRoot: (baseParams.length > 0 || this.forceDocumentRoot === true) ? this.documentRoot : false,
25577             record: this.meta.record,
25578             root: this.root,
25579             baseParams: baseParams,
25580             records: (Ext.isArray(data[0])) ? data : [data]
25581         });
25582     },
25583
25584     
25585     createRecord : function(rec) {
25586         return this.toArray(this.toHash(rec));
25587     },
25588
25589     
25590     updateRecord : function(rec) {
25591         return this.toArray(this.toHash(rec));
25592
25593     },
25594     
25595     destroyRecord : function(rec) {
25596         var data = {};
25597         data[this.meta.idProperty] = rec.id;
25598         return this.toArray(data);
25599     }
25600 });
25601
25602 Ext.data.XmlReader = function(meta, recordType){
25603     meta = meta || {};
25604
25605     
25606     Ext.applyIf(meta, {
25607         idProperty: meta.idProperty || meta.idPath || meta.id,
25608         successProperty: meta.successProperty || meta.success
25609     });
25610
25611     Ext.data.XmlReader.superclass.constructor.call(this, meta, recordType || meta.fields);
25612 };
25613 Ext.extend(Ext.data.XmlReader, Ext.data.DataReader, {
25614     
25615     read : function(response){
25616         var doc = response.responseXML;
25617         if(!doc) {
25618             throw {message: "XmlReader.read: XML Document not available"};
25619         }
25620         return this.readRecords(doc);
25621     },
25622
25623     
25624     readRecords : function(doc){
25625         
25626         this.xmlData = doc;
25627
25628         var root    = doc.documentElement || doc,
25629             q       = Ext.DomQuery,
25630             totalRecords = 0,
25631             success = true;
25632
25633         if(this.meta.totalProperty){
25634             totalRecords = this.getTotal(root, 0);
25635         }
25636         if(this.meta.successProperty){
25637             success = this.getSuccess(root);
25638         }
25639
25640         var records = this.extractData(q.select(this.meta.record, root), true); 
25641
25642         
25643         return {
25644             success : success,
25645             records : records,
25646             totalRecords : totalRecords || records.length
25647         };
25648     },
25649
25650     
25651     readResponse : function(action, response) {
25652         var q = Ext.DomQuery,
25653             doc = response.responseXML,
25654             root = doc.documentElement || doc;
25655
25656         
25657         var res = new Ext.data.Response({
25658             action: action,
25659             success : this.getSuccess(root),
25660             message: this.getMessage(root),
25661             data: this.extractData(q.select(this.meta.record, root) || q.select(this.meta.root, root), false),
25662             raw: doc
25663         });
25664
25665         if (Ext.isEmpty(res.success)) {
25666             throw new Ext.data.DataReader.Error('successProperty-response', this.meta.successProperty);
25667         }
25668
25669         
25670         if (action === Ext.data.Api.actions.create) {
25671             var def = Ext.isDefined(res.data);
25672             if (def && Ext.isEmpty(res.data)) {
25673                 throw new Ext.data.JsonReader.Error('root-empty', this.meta.root);
25674             }
25675             else if (!def) {
25676                 throw new Ext.data.JsonReader.Error('root-undefined-response', this.meta.root);
25677             }
25678         }
25679         return res;
25680     },
25681
25682     getSuccess : function() {
25683         return true;
25684     },
25685
25686     
25687     buildExtractors : function() {
25688         if(this.ef){
25689             return;
25690         }
25691         var s       = this.meta,
25692             Record  = this.recordType,
25693             f       = Record.prototype.fields,
25694             fi      = f.items,
25695             fl      = f.length;
25696
25697         if(s.totalProperty) {
25698             this.getTotal = this.createAccessor(s.totalProperty);
25699         }
25700         if(s.successProperty) {
25701             this.getSuccess = this.createAccessor(s.successProperty);
25702         }
25703         if (s.messageProperty) {
25704             this.getMessage = this.createAccessor(s.messageProperty);
25705         }
25706         this.getRoot = function(res) {
25707             return (!Ext.isEmpty(res[this.meta.record])) ? res[this.meta.record] : res[this.meta.root];
25708         };
25709         if (s.idPath || s.idProperty) {
25710             var g = this.createAccessor(s.idPath || s.idProperty);
25711             this.getId = function(rec) {
25712                 var id = g(rec) || rec.id;
25713                 return (id === undefined || id === '') ? null : id;
25714             };
25715         } else {
25716             this.getId = function(){return null;};
25717         }
25718         var ef = [];
25719         for(var i = 0; i < fl; i++){
25720             f = fi[i];
25721             var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;
25722             ef.push(this.createAccessor(map));
25723         }
25724         this.ef = ef;
25725     },
25726
25727     
25728     createAccessor : function(){
25729         var q = Ext.DomQuery;
25730         return function(key) {
25731             switch(key) {
25732                 case this.meta.totalProperty:
25733                     return function(root, def){
25734                         return q.selectNumber(key, root, def);
25735                     };
25736                     break;
25737                 case this.meta.successProperty:
25738                     return function(root, def) {
25739                         var sv = q.selectValue(key, root, true);
25740                         var success = sv !== false && sv !== 'false';
25741                         return success;
25742                     };
25743                     break;
25744                 default:
25745                     return function(root, def) {
25746                         return q.selectValue(key, root, def);
25747                     };
25748                     break;
25749             }
25750         };
25751     }(),
25752
25753     
25754     extractValues : function(data, items, len) {
25755         var f, values = {};
25756         for(var j = 0; j < len; j++){
25757             f = items[j];
25758             var v = this.ef[j](data);
25759             values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue, data);
25760         }
25761         return values;
25762     }
25763 });
25764 Ext.data.XmlStore = Ext.extend(Ext.data.Store, {
25765     
25766     constructor: function(config){
25767         Ext.data.XmlStore.superclass.constructor.call(this, Ext.apply(config, {
25768             reader: new Ext.data.XmlReader(config)
25769         }));
25770     }
25771 });
25772 Ext.reg('xmlstore', Ext.data.XmlStore);
25773 Ext.data.GroupingStore = Ext.extend(Ext.data.Store, {
25774
25775     
25776     constructor: function(config) {
25777         config = config || {};
25778
25779         
25780         
25781         
25782         
25783         this.hasMultiSort  = true;
25784         this.multiSortInfo = this.multiSortInfo || {sorters: []};
25785
25786         var sorters    = this.multiSortInfo.sorters,
25787             groupField = config.groupField || this.groupField,
25788             sortInfo   = config.sortInfo || this.sortInfo,
25789             groupDir   = config.groupDir || this.groupDir;
25790
25791         
25792         if(groupField){
25793             sorters.push({
25794                 field    : groupField,
25795                 direction: groupDir
25796             });
25797         }
25798
25799         
25800         if (sortInfo) {
25801             sorters.push(sortInfo);
25802         }
25803
25804         Ext.data.GroupingStore.superclass.constructor.call(this, config);
25805
25806         this.addEvents(
25807           
25808           'groupchange'
25809         );
25810
25811         this.applyGroupField();
25812     },
25813
25814     
25815     
25816     remoteGroup : false,
25817     
25818     groupOnSort:false,
25819
25820     groupDir : 'ASC',
25821
25822     
25823     clearGrouping : function(){
25824         this.groupField = false;
25825
25826         if(this.remoteGroup){
25827             if(this.baseParams){
25828                 delete this.baseParams.groupBy;
25829                 delete this.baseParams.groupDir;
25830             }
25831             var lo = this.lastOptions;
25832             if(lo && lo.params){
25833                 delete lo.params.groupBy;
25834                 delete lo.params.groupDir;
25835             }
25836
25837             this.reload();
25838         }else{
25839             this.sort();
25840             this.fireEvent('datachanged', this);
25841         }
25842     },
25843
25844     
25845     groupBy : function(field, forceRegroup, direction) {
25846         direction = direction ? (String(direction).toUpperCase() == 'DESC' ? 'DESC' : 'ASC') : this.groupDir;
25847
25848         if (this.groupField == field && this.groupDir == direction && !forceRegroup) {
25849             return; 
25850         }
25851
25852         
25853         
25854         var sorters = this.multiSortInfo.sorters;
25855         if (sorters.length > 0 && sorters[0].field == this.groupField) {
25856             sorters.shift();
25857         }
25858
25859         this.groupField = field;
25860         this.groupDir = direction;
25861         this.applyGroupField();
25862
25863         var fireGroupEvent = function() {
25864             this.fireEvent('groupchange', this, this.getGroupState());
25865         };
25866
25867         if (this.groupOnSort) {
25868             this.sort(field, direction);
25869             fireGroupEvent.call(this);
25870             return;
25871         }
25872
25873         if (this.remoteGroup) {
25874             this.on('load', fireGroupEvent, this, {single: true});
25875             this.reload();
25876         } else {
25877             this.sort(sorters);
25878             fireGroupEvent.call(this);
25879         }
25880     },
25881
25882     
25883     
25884     sort : function(fieldName, dir) {
25885         if (this.remoteSort) {
25886             return Ext.data.GroupingStore.superclass.sort.call(this, fieldName, dir);
25887         }
25888
25889         var sorters = [];
25890
25891         
25892         if (Ext.isArray(arguments[0])) {
25893             sorters = arguments[0];
25894         } else if (fieldName == undefined) {
25895             
25896             
25897             sorters = this.sortInfo ? [this.sortInfo] : [];
25898         } else {
25899             
25900             
25901             var field = this.fields.get(fieldName);
25902             if (!field) return false;
25903
25904             var name       = field.name,
25905                 sortInfo   = this.sortInfo || null,
25906                 sortToggle = this.sortToggle ? this.sortToggle[name] : null;
25907
25908             if (!dir) {
25909                 if (sortInfo && sortInfo.field == name) { 
25910                     dir = (this.sortToggle[name] || 'ASC').toggle('ASC', 'DESC');
25911                 } else {
25912                     dir = field.sortDir;
25913                 }
25914             }
25915
25916             this.sortToggle[name] = dir;
25917             this.sortInfo = {field: name, direction: dir};
25918
25919             sorters = [this.sortInfo];
25920         }
25921
25922         
25923         if (this.groupField) {
25924             sorters.unshift({direction: this.groupDir, field: this.groupField});
25925         }
25926
25927         return this.multiSort.call(this, sorters, dir);
25928     },
25929
25930     
25931     applyGroupField: function(){
25932         if (this.remoteGroup) {
25933             if(!this.baseParams){
25934                 this.baseParams = {};
25935             }
25936
25937             Ext.apply(this.baseParams, {
25938                 groupBy : this.groupField,
25939                 groupDir: this.groupDir
25940             });
25941
25942             var lo = this.lastOptions;
25943             if (lo && lo.params) {
25944                 lo.params.groupDir = this.groupDir;
25945
25946                 
25947                 delete lo.params.groupBy;
25948             }
25949         }
25950     },
25951
25952     
25953     applyGrouping : function(alwaysFireChange){
25954         if(this.groupField !== false){
25955             this.groupBy(this.groupField, true, this.groupDir);
25956             return true;
25957         }else{
25958             if(alwaysFireChange === true){
25959                 this.fireEvent('datachanged', this);
25960             }
25961             return false;
25962         }
25963     },
25964
25965     
25966     getGroupState : function(){
25967         return this.groupOnSort && this.groupField !== false ?
25968                (this.sortInfo ? this.sortInfo.field : undefined) : this.groupField;
25969     }
25970 });
25971 Ext.reg('groupingstore', Ext.data.GroupingStore);
25972
25973 Ext.data.DirectProxy = function(config){
25974     Ext.apply(this, config);
25975     if(typeof this.paramOrder == 'string'){
25976         this.paramOrder = this.paramOrder.split(/[\s,|]/);
25977     }
25978     Ext.data.DirectProxy.superclass.constructor.call(this, config);
25979 };
25980
25981 Ext.extend(Ext.data.DirectProxy, Ext.data.DataProxy, {
25982     
25983     paramOrder: undefined,
25984
25985     
25986     paramsAsHash: true,
25987
25988     
25989     directFn : undefined,
25990
25991     
25992     doRequest : function(action, rs, params, reader, callback, scope, options) {
25993         var args = [],
25994             directFn = this.api[action] || this.directFn;
25995
25996         switch (action) {
25997             case Ext.data.Api.actions.create:
25998                 args.push(params.jsonData);             
25999                 break;
26000             case Ext.data.Api.actions.read:
26001                 
26002                 if(directFn.directCfg.method.len > 0){
26003                     if(this.paramOrder){
26004                         for(var i = 0, len = this.paramOrder.length; i < len; i++){
26005                             args.push(params[this.paramOrder[i]]);
26006                         }
26007                     }else if(this.paramsAsHash){
26008                         args.push(params);
26009                     }
26010                 }
26011                 break;
26012             case Ext.data.Api.actions.update:
26013                 args.push(params.jsonData);        
26014                 break;
26015             case Ext.data.Api.actions.destroy:
26016                 args.push(params.jsonData);        
26017                 break;
26018         }
26019
26020         var trans = {
26021             params : params || {},
26022             request: {
26023                 callback : callback,
26024                 scope : scope,
26025                 arg : options
26026             },
26027             reader: reader
26028         };
26029
26030         args.push(this.createCallback(action, rs, trans), this);
26031         directFn.apply(window, args);
26032     },
26033
26034     
26035     createCallback : function(action, rs, trans) {
26036         var me = this;
26037         return function(result, res) {
26038             if (!res.status) {
26039                 
26040                 if (action === Ext.data.Api.actions.read) {
26041                     me.fireEvent("loadexception", me, trans, res, null);
26042                 }
26043                 me.fireEvent('exception', me, 'remote', action, trans, res, null);
26044                 trans.request.callback.call(trans.request.scope, null, trans.request.arg, false);
26045                 return;
26046             }
26047             if (action === Ext.data.Api.actions.read) {
26048                 me.onRead(action, trans, result, res);
26049             } else {
26050                 me.onWrite(action, trans, result, res, rs);
26051             }
26052         };
26053     },
26054
26055     
26056     onRead : function(action, trans, result, res) {
26057         var records;
26058         try {
26059             records = trans.reader.readRecords(result);
26060         }
26061         catch (ex) {
26062             
26063             this.fireEvent("loadexception", this, trans, res, ex);
26064
26065             this.fireEvent('exception', this, 'response', action, trans, res, ex);
26066             trans.request.callback.call(trans.request.scope, null, trans.request.arg, false);
26067             return;
26068         }
26069         this.fireEvent("load", this, res, trans.request.arg);
26070         trans.request.callback.call(trans.request.scope, records, trans.request.arg, true);
26071     },
26072     
26073     onWrite : function(action, trans, result, res, rs) {
26074         var data = trans.reader.extractData(trans.reader.getRoot(result), false);
26075         var success = trans.reader.getSuccess(result);
26076         success = (success !== false);
26077         if (success){
26078             this.fireEvent("write", this, action, data, res, rs, trans.request.arg);
26079         }else{
26080             this.fireEvent('exception', this, 'remote', action, trans, result, rs);
26081         }
26082         trans.request.callback.call(trans.request.scope, data, res, success);
26083     }
26084 });
26085
26086 Ext.data.DirectStore = Ext.extend(Ext.data.Store, {
26087     constructor : function(config){
26088         
26089         var c = Ext.apply({}, {
26090             batchTransactions: false
26091         }, config);
26092         Ext.data.DirectStore.superclass.constructor.call(this, Ext.apply(c, {
26093             proxy: Ext.isDefined(c.proxy) ? c.proxy : new Ext.data.DirectProxy(Ext.copyTo({}, c, 'paramOrder,paramsAsHash,directFn,api')),
26094             reader: (!Ext.isDefined(c.reader) && c.fields) ? new Ext.data.JsonReader(Ext.copyTo({}, c, 'totalProperty,root,idProperty'), c.fields) : c.reader
26095         }));
26096     }
26097 });
26098 Ext.reg('directstore', Ext.data.DirectStore);
26099
26100 Ext.Direct = Ext.extend(Ext.util.Observable, {
26101     
26102
26103     
26104     exceptions: {
26105         TRANSPORT: 'xhr',
26106         PARSE: 'parse',
26107         LOGIN: 'login',
26108         SERVER: 'exception'
26109     },
26110
26111     
26112     constructor: function(){
26113         this.addEvents(
26114             
26115             'event',
26116             
26117             'exception'
26118         );
26119         this.transactions = {};
26120         this.providers = {};
26121     },
26122
26123     
26124     addProvider : function(provider){
26125         var a = arguments;
26126         if(a.length > 1){
26127             for(var i = 0, len = a.length; i < len; i++){
26128                 this.addProvider(a[i]);
26129             }
26130             return;
26131         }
26132
26133         
26134         if(!provider.events){
26135             provider = new Ext.Direct.PROVIDERS[provider.type](provider);
26136         }
26137         provider.id = provider.id || Ext.id();
26138         this.providers[provider.id] = provider;
26139
26140         provider.on('data', this.onProviderData, this);
26141         provider.on('exception', this.onProviderException, this);
26142
26143
26144         if(!provider.isConnected()){
26145             provider.connect();
26146         }
26147
26148         return provider;
26149     },
26150
26151     
26152     getProvider : function(id){
26153         return this.providers[id];
26154     },
26155
26156     removeProvider : function(id){
26157         var provider = id.id ? id : this.providers[id];
26158         provider.un('data', this.onProviderData, this);
26159         provider.un('exception', this.onProviderException, this);
26160         delete this.providers[provider.id];
26161         return provider;
26162     },
26163
26164     addTransaction: function(t){
26165         this.transactions[t.tid] = t;
26166         return t;
26167     },
26168
26169     removeTransaction: function(t){
26170         delete this.transactions[t.tid || t];
26171         return t;
26172     },
26173
26174     getTransaction: function(tid){
26175         return this.transactions[tid.tid || tid];
26176     },
26177
26178     onProviderData : function(provider, e){
26179         if(Ext.isArray(e)){
26180             for(var i = 0, len = e.length; i < len; i++){
26181                 this.onProviderData(provider, e[i]);
26182             }
26183             return;
26184         }
26185         if(e.name && e.name != 'event' && e.name != 'exception'){
26186             this.fireEvent(e.name, e);
26187         }else if(e.type == 'exception'){
26188             this.fireEvent('exception', e);
26189         }
26190         this.fireEvent('event', e, provider);
26191     },
26192
26193     createEvent : function(response, extraProps){
26194         return new Ext.Direct.eventTypes[response.type](Ext.apply(response, extraProps));
26195     }
26196 });
26197
26198 Ext.Direct = new Ext.Direct();
26199
26200 Ext.Direct.TID = 1;
26201 Ext.Direct.PROVIDERS = {};
26202 Ext.Direct.Transaction = function(config){
26203     Ext.apply(this, config);
26204     this.tid = ++Ext.Direct.TID;
26205     this.retryCount = 0;
26206 };
26207 Ext.Direct.Transaction.prototype = {
26208     send: function(){
26209         this.provider.queueTransaction(this);
26210     },
26211
26212     retry: function(){
26213         this.retryCount++;
26214         this.send();
26215     },
26216
26217     getProvider: function(){
26218         return this.provider;
26219     }
26220 };Ext.Direct.Event = function(config){
26221     Ext.apply(this, config);
26222 };
26223
26224 Ext.Direct.Event.prototype = {
26225     status: true,
26226     getData: function(){
26227         return this.data;
26228     }
26229 };
26230
26231 Ext.Direct.RemotingEvent = Ext.extend(Ext.Direct.Event, {
26232     type: 'rpc',
26233     getTransaction: function(){
26234         return this.transaction || Ext.Direct.getTransaction(this.tid);
26235     }
26236 });
26237
26238 Ext.Direct.ExceptionEvent = Ext.extend(Ext.Direct.RemotingEvent, {
26239     status: false,
26240     type: 'exception'
26241 });
26242
26243 Ext.Direct.eventTypes = {
26244     'rpc':  Ext.Direct.RemotingEvent,
26245     'event':  Ext.Direct.Event,
26246     'exception':  Ext.Direct.ExceptionEvent
26247 };
26248
26249 Ext.direct.Provider = Ext.extend(Ext.util.Observable, {    
26250     
26251         
26252         
26253     priority: 1,
26254
26255         
26256  
26257     
26258     constructor : function(config){
26259         Ext.apply(this, config);
26260         this.addEvents(
26261                         
26262             'connect',
26263                         
26264             'disconnect',
26265                         
26266             'data',
26267                                     
26268             'exception'
26269         );
26270         Ext.direct.Provider.superclass.constructor.call(this, config);
26271     },
26272
26273     
26274     isConnected: function(){
26275         return false;
26276     },
26277
26278     
26279     connect: Ext.emptyFn,
26280     
26281     
26282     disconnect: Ext.emptyFn
26283 });
26284
26285 Ext.direct.JsonProvider = Ext.extend(Ext.direct.Provider, {
26286     parseResponse: function(xhr){
26287         if(!Ext.isEmpty(xhr.responseText)){
26288             if(typeof xhr.responseText == 'object'){
26289                 return xhr.responseText;
26290             }
26291             return Ext.decode(xhr.responseText);
26292         }
26293         return null;
26294     },
26295
26296     getEvents: function(xhr){
26297         var data = null;
26298         try{
26299             data = this.parseResponse(xhr);
26300         }catch(e){
26301             var event = new Ext.Direct.ExceptionEvent({
26302                 data: e,
26303                 xhr: xhr,
26304                 code: Ext.Direct.exceptions.PARSE,
26305                 message: 'Error parsing json response: \n\n ' + data
26306             });
26307             return [event];
26308         }
26309         var events = [];
26310         if(Ext.isArray(data)){
26311             for(var i = 0, len = data.length; i < len; i++){
26312                 events.push(Ext.Direct.createEvent(data[i]));
26313             }
26314         }else{
26315             events.push(Ext.Direct.createEvent(data));
26316         }
26317         return events;
26318     }
26319 });
26320 Ext.direct.PollingProvider = Ext.extend(Ext.direct.JsonProvider, {
26321     
26322     
26323     priority: 3,
26324     
26325     
26326     interval: 3000,
26327
26328     
26329     
26330     
26331
26332     
26333     constructor : function(config){
26334         Ext.direct.PollingProvider.superclass.constructor.call(this, config);
26335         this.addEvents(
26336             
26337             'beforepoll',            
26338             
26339             'poll'
26340         );
26341     },
26342
26343     
26344     isConnected: function(){
26345         return !!this.pollTask;
26346     },
26347
26348     
26349     connect: function(){
26350         if(this.url && !this.pollTask){
26351             this.pollTask = Ext.TaskMgr.start({
26352                 run: function(){
26353                     if(this.fireEvent('beforepoll', this) !== false){
26354                         if(typeof this.url == 'function'){
26355                             this.url(this.baseParams);
26356                         }else{
26357                             Ext.Ajax.request({
26358                                 url: this.url,
26359                                 callback: this.onData,
26360                                 scope: this,
26361                                 params: this.baseParams
26362                             });
26363                         }
26364                     }
26365                 },
26366                 interval: this.interval,
26367                 scope: this
26368             });
26369             this.fireEvent('connect', this);
26370         }else if(!this.url){
26371             throw 'Error initializing PollingProvider, no url configured.';
26372         }
26373     },
26374
26375     
26376     disconnect: function(){
26377         if(this.pollTask){
26378             Ext.TaskMgr.stop(this.pollTask);
26379             delete this.pollTask;
26380             this.fireEvent('disconnect', this);
26381         }
26382     },
26383
26384     
26385     onData: function(opt, success, xhr){
26386         if(success){
26387             var events = this.getEvents(xhr);
26388             for(var i = 0, len = events.length; i < len; i++){
26389                 var e = events[i];
26390                 this.fireEvent('data', this, e);
26391             }
26392         }else{
26393             var e = new Ext.Direct.ExceptionEvent({
26394                 data: e,
26395                 code: Ext.Direct.exceptions.TRANSPORT,
26396                 message: 'Unable to connect to the server.',
26397                 xhr: xhr
26398             });
26399             this.fireEvent('data', this, e);
26400         }
26401     }
26402 });
26403
26404 Ext.Direct.PROVIDERS['polling'] = Ext.direct.PollingProvider;
26405 Ext.direct.RemotingProvider = Ext.extend(Ext.direct.JsonProvider, {       
26406     
26407     
26408     
26409     
26410     
26411     
26412     
26413     
26414     
26415     enableBuffer: 10,
26416     
26417     
26418     maxRetries: 1,
26419     
26420     
26421     timeout: undefined,
26422
26423     constructor : function(config){
26424         Ext.direct.RemotingProvider.superclass.constructor.call(this, config);
26425         this.addEvents(
26426                         
26427             'beforecall',            
26428                         
26429             'call'
26430         );
26431         this.namespace = (Ext.isString(this.namespace)) ? Ext.ns(this.namespace) : this.namespace || window;
26432         this.transactions = {};
26433         this.callBuffer = [];
26434     },
26435
26436     
26437     initAPI : function(){
26438         var o = this.actions;
26439         for(var c in o){
26440             var cls = this.namespace[c] || (this.namespace[c] = {}),
26441                 ms = o[c];
26442             for(var i = 0, len = ms.length; i < len; i++){
26443                 var m = ms[i];
26444                 cls[m.name] = this.createMethod(c, m);
26445             }
26446         }
26447     },
26448
26449     
26450     isConnected: function(){
26451         return !!this.connected;
26452     },
26453
26454     connect: function(){
26455         if(this.url){
26456             this.initAPI();
26457             this.connected = true;
26458             this.fireEvent('connect', this);
26459         }else if(!this.url){
26460             throw 'Error initializing RemotingProvider, no url configured.';
26461         }
26462     },
26463
26464     disconnect: function(){
26465         if(this.connected){
26466             this.connected = false;
26467             this.fireEvent('disconnect', this);
26468         }
26469     },
26470
26471     onData: function(opt, success, xhr){
26472         if(success){
26473             var events = this.getEvents(xhr);
26474             for(var i = 0, len = events.length; i < len; i++){
26475                 var e = events[i],
26476                     t = this.getTransaction(e);
26477                 this.fireEvent('data', this, e);
26478                 if(t){
26479                     this.doCallback(t, e, true);
26480                     Ext.Direct.removeTransaction(t);
26481                 }
26482             }
26483         }else{
26484             var ts = [].concat(opt.ts);
26485             for(var i = 0, len = ts.length; i < len; i++){
26486                 var t = this.getTransaction(ts[i]);
26487                 if(t && t.retryCount < this.maxRetries){
26488                     t.retry();
26489                 }else{
26490                     var e = new Ext.Direct.ExceptionEvent({
26491                         data: e,
26492                         transaction: t,
26493                         code: Ext.Direct.exceptions.TRANSPORT,
26494                         message: 'Unable to connect to the server.',
26495                         xhr: xhr
26496                     });
26497                     this.fireEvent('data', this, e);
26498                     if(t){
26499                         this.doCallback(t, e, false);
26500                         Ext.Direct.removeTransaction(t);
26501                     }
26502                 }
26503             }
26504         }
26505     },
26506
26507     getCallData: function(t){
26508         return {
26509             action: t.action,
26510             method: t.method,
26511             data: t.data,
26512             type: 'rpc',
26513             tid: t.tid
26514         };
26515     },
26516
26517     doSend : function(data){
26518         var o = {
26519             url: this.url,
26520             callback: this.onData,
26521             scope: this,
26522             ts: data,
26523             timeout: this.timeout
26524         }, callData;
26525
26526         if(Ext.isArray(data)){
26527             callData = [];
26528             for(var i = 0, len = data.length; i < len; i++){
26529                 callData.push(this.getCallData(data[i]));
26530             }
26531         }else{
26532             callData = this.getCallData(data);
26533         }
26534
26535         if(this.enableUrlEncode){
26536             var params = {};
26537             params[Ext.isString(this.enableUrlEncode) ? this.enableUrlEncode : 'data'] = Ext.encode(callData);
26538             o.params = params;
26539         }else{
26540             o.jsonData = callData;
26541         }
26542         Ext.Ajax.request(o);
26543     },
26544
26545     combineAndSend : function(){
26546         var len = this.callBuffer.length;
26547         if(len > 0){
26548             this.doSend(len == 1 ? this.callBuffer[0] : this.callBuffer);
26549             this.callBuffer = [];
26550         }
26551     },
26552
26553     queueTransaction: function(t){
26554         if(t.form){
26555             this.processForm(t);
26556             return;
26557         }
26558         this.callBuffer.push(t);
26559         if(this.enableBuffer){
26560             if(!this.callTask){
26561                 this.callTask = new Ext.util.DelayedTask(this.combineAndSend, this);
26562             }
26563             this.callTask.delay(Ext.isNumber(this.enableBuffer) ? this.enableBuffer : 10);
26564         }else{
26565             this.combineAndSend();
26566         }
26567     },
26568
26569     doCall : function(c, m, args){
26570         var data = null, hs = args[m.len], scope = args[m.len+1];
26571
26572         if(m.len !== 0){
26573             data = args.slice(0, m.len);
26574         }
26575
26576         var t = new Ext.Direct.Transaction({
26577             provider: this,
26578             args: args,
26579             action: c,
26580             method: m.name,
26581             data: data,
26582             cb: scope && Ext.isFunction(hs) ? hs.createDelegate(scope) : hs
26583         });
26584
26585         if(this.fireEvent('beforecall', this, t, m) !== false){
26586             Ext.Direct.addTransaction(t);
26587             this.queueTransaction(t);
26588             this.fireEvent('call', this, t, m);
26589         }
26590     },
26591
26592     doForm : function(c, m, form, callback, scope){
26593         var t = new Ext.Direct.Transaction({
26594             provider: this,
26595             action: c,
26596             method: m.name,
26597             args:[form, callback, scope],
26598             cb: scope && Ext.isFunction(callback) ? callback.createDelegate(scope) : callback,
26599             isForm: true
26600         });
26601
26602         if(this.fireEvent('beforecall', this, t, m) !== false){
26603             Ext.Direct.addTransaction(t);
26604             var isUpload = String(form.getAttribute("enctype")).toLowerCase() == 'multipart/form-data',
26605                 params = {
26606                     extTID: t.tid,
26607                     extAction: c,
26608                     extMethod: m.name,
26609                     extType: 'rpc',
26610                     extUpload: String(isUpload)
26611                 };
26612             
26613             
26614             
26615             Ext.apply(t, {
26616                 form: Ext.getDom(form),
26617                 isUpload: isUpload,
26618                 params: callback && Ext.isObject(callback.params) ? Ext.apply(params, callback.params) : params
26619             });
26620             this.fireEvent('call', this, t, m);
26621             this.processForm(t);
26622         }
26623     },
26624     
26625     processForm: function(t){
26626         Ext.Ajax.request({
26627             url: this.url,
26628             params: t.params,
26629             callback: this.onData,
26630             scope: this,
26631             form: t.form,
26632             isUpload: t.isUpload,
26633             ts: t
26634         });
26635     },
26636
26637     createMethod : function(c, m){
26638         var f;
26639         if(!m.formHandler){
26640             f = function(){
26641                 this.doCall(c, m, Array.prototype.slice.call(arguments, 0));
26642             }.createDelegate(this);
26643         }else{
26644             f = function(form, callback, scope){
26645                 this.doForm(c, m, form, callback, scope);
26646             }.createDelegate(this);
26647         }
26648         f.directCfg = {
26649             action: c,
26650             method: m
26651         };
26652         return f;
26653     },
26654
26655     getTransaction: function(opt){
26656         return opt && opt.tid ? Ext.Direct.getTransaction(opt.tid) : null;
26657     },
26658
26659     doCallback: function(t, e){
26660         var fn = e.status ? 'success' : 'failure';
26661         if(t && t.cb){
26662             var hs = t.cb,
26663                 result = Ext.isDefined(e.result) ? e.result : e.data;
26664             if(Ext.isFunction(hs)){
26665                 hs(result, e);
26666             } else{
26667                 Ext.callback(hs[fn], hs.scope, [result, e]);
26668                 Ext.callback(hs.callback, hs.scope, [result, e]);
26669             }
26670         }
26671     }
26672 });
26673 Ext.Direct.PROVIDERS['remoting'] = Ext.direct.RemotingProvider;
26674 Ext.Resizable = Ext.extend(Ext.util.Observable, {
26675
26676     constructor: function(el, config){
26677         this.el = Ext.get(el);
26678         if(config && config.wrap){
26679             config.resizeChild = this.el;
26680             this.el = this.el.wrap(typeof config.wrap == 'object' ? config.wrap : {cls:'xresizable-wrap'});
26681             this.el.id = this.el.dom.id = config.resizeChild.id + '-rzwrap';
26682             this.el.setStyle('overflow', 'hidden');
26683             this.el.setPositioning(config.resizeChild.getPositioning());
26684             config.resizeChild.clearPositioning();
26685             if(!config.width || !config.height){
26686                 var csize = config.resizeChild.getSize();
26687                 this.el.setSize(csize.width, csize.height);
26688             }
26689             if(config.pinned && !config.adjustments){
26690                 config.adjustments = 'auto';
26691             }
26692         }
26693
26694         
26695         this.proxy = this.el.createProxy({tag: 'div', cls: 'x-resizable-proxy', id: this.el.id + '-rzproxy'}, Ext.getBody());
26696         this.proxy.unselectable();
26697         this.proxy.enableDisplayMode('block');
26698
26699         Ext.apply(this, config);
26700
26701         if(this.pinned){
26702             this.disableTrackOver = true;
26703             this.el.addClass('x-resizable-pinned');
26704         }
26705         
26706         var position = this.el.getStyle('position');
26707         if(position != 'absolute' && position != 'fixed'){
26708             this.el.setStyle('position', 'relative');
26709         }
26710         if(!this.handles){ 
26711             this.handles = 's,e,se';
26712             if(this.multiDirectional){
26713                 this.handles += ',n,w';
26714             }
26715         }
26716         if(this.handles == 'all'){
26717             this.handles = 'n s e w ne nw se sw';
26718         }
26719         var hs = this.handles.split(/\s*?[,;]\s*?| /);
26720         var ps = Ext.Resizable.positions;
26721         for(var i = 0, len = hs.length; i < len; i++){
26722             if(hs[i] && ps[hs[i]]){
26723                 var pos = ps[hs[i]];
26724                 this[pos] = new Ext.Resizable.Handle(this, pos, this.disableTrackOver, this.transparent, this.handleCls);
26725             }
26726         }
26727         
26728         this.corner = this.southeast;
26729
26730         if(this.handles.indexOf('n') != -1 || this.handles.indexOf('w') != -1){
26731             this.updateBox = true;
26732         }
26733
26734         this.activeHandle = null;
26735
26736         if(this.resizeChild){
26737             if(typeof this.resizeChild == 'boolean'){
26738                 this.resizeChild = Ext.get(this.el.dom.firstChild, true);
26739             }else{
26740                 this.resizeChild = Ext.get(this.resizeChild, true);
26741             }
26742         }
26743
26744         if(this.adjustments == 'auto'){
26745             var rc = this.resizeChild;
26746             var hw = this.west, he = this.east, hn = this.north, hs = this.south;
26747             if(rc && (hw || hn)){
26748                 rc.position('relative');
26749                 rc.setLeft(hw ? hw.el.getWidth() : 0);
26750                 rc.setTop(hn ? hn.el.getHeight() : 0);
26751             }
26752             this.adjustments = [
26753                 (he ? -he.el.getWidth() : 0) + (hw ? -hw.el.getWidth() : 0),
26754                 (hn ? -hn.el.getHeight() : 0) + (hs ? -hs.el.getHeight() : 0) -1
26755             ];
26756         }
26757
26758         if(this.draggable){
26759             this.dd = this.dynamic ?
26760                 this.el.initDD(null) : this.el.initDDProxy(null, {dragElId: this.proxy.id});
26761             this.dd.setHandleElId(this.resizeChild ? this.resizeChild.id : this.el.id);
26762             if(this.constrainTo){
26763                 this.dd.constrainTo(this.constrainTo);
26764             }
26765         }
26766
26767         this.addEvents(
26768             
26769             'beforeresize',
26770             
26771             'resize'
26772         );
26773
26774         if(this.width !== null && this.height !== null){
26775             this.resizeTo(this.width, this.height);
26776         }else{
26777             this.updateChildSize();
26778         }
26779         if(Ext.isIE){
26780             this.el.dom.style.zoom = 1;
26781         }
26782         Ext.Resizable.superclass.constructor.call(this);
26783     },
26784
26785     
26786     adjustments : [0, 0],
26787     
26788     animate : false,
26789     
26790     
26791     disableTrackOver : false,
26792     
26793     draggable: false,
26794     
26795     duration : 0.35,
26796     
26797     dynamic : false,
26798     
26799     easing : 'easeOutStrong',
26800     
26801     enabled : true,
26802     
26803     
26804     handles : false,
26805     
26806     multiDirectional : false,
26807     
26808     height : null,
26809     
26810     width : null,
26811     
26812     heightIncrement : 0,
26813     
26814     widthIncrement : 0,
26815     
26816     minHeight : 5,
26817     
26818     minWidth : 5,
26819     
26820     maxHeight : 10000,
26821     
26822     maxWidth : 10000,
26823     
26824     minX: 0,
26825     
26826     minY: 0,
26827     
26828     pinned : false,
26829     
26830     preserveRatio : false,
26831     
26832     resizeChild : false,
26833     
26834     transparent: false,
26835     
26836     
26837     
26838
26839
26840     
26841     resizeTo : function(width, height){
26842         this.el.setSize(width, height);
26843         this.updateChildSize();
26844         this.fireEvent('resize', this, width, height, null);
26845     },
26846
26847     
26848     startSizing : function(e, handle){
26849         this.fireEvent('beforeresize', this, e);
26850         if(this.enabled){ 
26851
26852             if(!this.overlay){
26853                 this.overlay = this.el.createProxy({tag: 'div', cls: 'x-resizable-overlay', html: '&#160;'}, Ext.getBody());
26854                 this.overlay.unselectable();
26855                 this.overlay.enableDisplayMode('block');
26856                 this.overlay.on({
26857                     scope: this,
26858                     mousemove: this.onMouseMove,
26859                     mouseup: this.onMouseUp
26860                 });
26861             }
26862             this.overlay.setStyle('cursor', handle.el.getStyle('cursor'));
26863
26864             this.resizing = true;
26865             this.startBox = this.el.getBox();
26866             this.startPoint = e.getXY();
26867             this.offsets = [(this.startBox.x + this.startBox.width) - this.startPoint[0],
26868                             (this.startBox.y + this.startBox.height) - this.startPoint[1]];
26869
26870             this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
26871             this.overlay.show();
26872
26873             if(this.constrainTo) {
26874                 var ct = Ext.get(this.constrainTo);
26875                 this.resizeRegion = ct.getRegion().adjust(
26876                     ct.getFrameWidth('t'),
26877                     ct.getFrameWidth('l'),
26878                     -ct.getFrameWidth('b'),
26879                     -ct.getFrameWidth('r')
26880                 );
26881             }
26882
26883             this.proxy.setStyle('visibility', 'hidden'); 
26884             this.proxy.show();
26885             this.proxy.setBox(this.startBox);
26886             if(!this.dynamic){
26887                 this.proxy.setStyle('visibility', 'visible');
26888             }
26889         }
26890     },
26891
26892     
26893     onMouseDown : function(handle, e){
26894         if(this.enabled){
26895             e.stopEvent();
26896             this.activeHandle = handle;
26897             this.startSizing(e, handle);
26898         }
26899     },
26900
26901     
26902     onMouseUp : function(e){
26903         this.activeHandle = null;
26904         var size = this.resizeElement();
26905         this.resizing = false;
26906         this.handleOut();
26907         this.overlay.hide();
26908         this.proxy.hide();
26909         this.fireEvent('resize', this, size.width, size.height, e);
26910     },
26911
26912     
26913     updateChildSize : function(){
26914         if(this.resizeChild){
26915             var el = this.el;
26916             var child = this.resizeChild;
26917             var adj = this.adjustments;
26918             if(el.dom.offsetWidth){
26919                 var b = el.getSize(true);
26920                 child.setSize(b.width+adj[0], b.height+adj[1]);
26921             }
26922             
26923             
26924             
26925             
26926             if(Ext.isIE){
26927                 setTimeout(function(){
26928                     if(el.dom.offsetWidth){
26929                         var b = el.getSize(true);
26930                         child.setSize(b.width+adj[0], b.height+adj[1]);
26931                     }
26932                 }, 10);
26933             }
26934         }
26935     },
26936
26937     
26938     snap : function(value, inc, min){
26939         if(!inc || !value){
26940             return value;
26941         }
26942         var newValue = value;
26943         var m = value % inc;
26944         if(m > 0){
26945             if(m > (inc/2)){
26946                 newValue = value + (inc-m);
26947             }else{
26948                 newValue = value - m;
26949             }
26950         }
26951         return Math.max(min, newValue);
26952     },
26953
26954     
26955     resizeElement : function(){
26956         var box = this.proxy.getBox();
26957         if(this.updateBox){
26958             this.el.setBox(box, false, this.animate, this.duration, null, this.easing);
26959         }else{
26960             this.el.setSize(box.width, box.height, this.animate, this.duration, null, this.easing);
26961         }
26962         this.updateChildSize();
26963         if(!this.dynamic){
26964             this.proxy.hide();
26965         }
26966         if(this.draggable && this.constrainTo){
26967             this.dd.resetConstraints();
26968             this.dd.constrainTo(this.constrainTo);
26969         }
26970         return box;
26971     },
26972
26973     
26974     constrain : function(v, diff, m, mx){
26975         if(v - diff < m){
26976             diff = v - m;
26977         }else if(v - diff > mx){
26978             diff = v - mx;
26979         }
26980         return diff;
26981     },
26982
26983     
26984     onMouseMove : function(e){
26985         if(this.enabled && this.activeHandle){
26986             try{
26987
26988             if(this.resizeRegion && !this.resizeRegion.contains(e.getPoint())) {
26989                 return;
26990             }
26991
26992             
26993             var curSize = this.curSize || this.startBox,
26994                 x = this.startBox.x, y = this.startBox.y,
26995                 ox = x,
26996                 oy = y,
26997                 w = curSize.width,
26998                 h = curSize.height,
26999                 ow = w,
27000                 oh = h,
27001                 mw = this.minWidth,
27002                 mh = this.minHeight,
27003                 mxw = this.maxWidth,
27004                 mxh = this.maxHeight,
27005                 wi = this.widthIncrement,
27006                 hi = this.heightIncrement,
27007                 eventXY = e.getXY(),
27008                 diffX = -(this.startPoint[0] - Math.max(this.minX, eventXY[0])),
27009                 diffY = -(this.startPoint[1] - Math.max(this.minY, eventXY[1])),
27010                 pos = this.activeHandle.position,
27011                 tw,
27012                 th;
27013
27014             switch(pos){
27015                 case 'east':
27016                     w += diffX;
27017                     w = Math.min(Math.max(mw, w), mxw);
27018                     break;
27019                 case 'south':
27020                     h += diffY;
27021                     h = Math.min(Math.max(mh, h), mxh);
27022                     break;
27023                 case 'southeast':
27024                     w += diffX;
27025                     h += diffY;
27026                     w = Math.min(Math.max(mw, w), mxw);
27027                     h = Math.min(Math.max(mh, h), mxh);
27028                     break;
27029                 case 'north':
27030                     diffY = this.constrain(h, diffY, mh, mxh);
27031                     y += diffY;
27032                     h -= diffY;
27033                     break;
27034                 case 'west':
27035                     diffX = this.constrain(w, diffX, mw, mxw);
27036                     x += diffX;
27037                     w -= diffX;
27038                     break;
27039                 case 'northeast':
27040                     w += diffX;
27041                     w = Math.min(Math.max(mw, w), mxw);
27042                     diffY = this.constrain(h, diffY, mh, mxh);
27043                     y += diffY;
27044                     h -= diffY;
27045                     break;
27046                 case 'northwest':
27047                     diffX = this.constrain(w, diffX, mw, mxw);
27048                     diffY = this.constrain(h, diffY, mh, mxh);
27049                     y += diffY;
27050                     h -= diffY;
27051                     x += diffX;
27052                     w -= diffX;
27053                     break;
27054                case 'southwest':
27055                     diffX = this.constrain(w, diffX, mw, mxw);
27056                     h += diffY;
27057                     h = Math.min(Math.max(mh, h), mxh);
27058                     x += diffX;
27059                     w -= diffX;
27060                     break;
27061             }
27062
27063             var sw = this.snap(w, wi, mw);
27064             var sh = this.snap(h, hi, mh);
27065             if(sw != w || sh != h){
27066                 switch(pos){
27067                     case 'northeast':
27068                         y -= sh - h;
27069                     break;
27070                     case 'north':
27071                         y -= sh - h;
27072                         break;
27073                     case 'southwest':
27074                         x -= sw - w;
27075                     break;
27076                     case 'west':
27077                         x -= sw - w;
27078                         break;
27079                     case 'northwest':
27080                         x -= sw - w;
27081                         y -= sh - h;
27082                     break;
27083                 }
27084                 w = sw;
27085                 h = sh;
27086             }
27087
27088             if(this.preserveRatio){
27089                 switch(pos){
27090                     case 'southeast':
27091                     case 'east':
27092                         h = oh * (w/ow);
27093                         h = Math.min(Math.max(mh, h), mxh);
27094                         w = ow * (h/oh);
27095                        break;
27096                     case 'south':
27097                         w = ow * (h/oh);
27098                         w = Math.min(Math.max(mw, w), mxw);
27099                         h = oh * (w/ow);
27100                         break;
27101                     case 'northeast':
27102                         w = ow * (h/oh);
27103                         w = Math.min(Math.max(mw, w), mxw);
27104                         h = oh * (w/ow);
27105                     break;
27106                     case 'north':
27107                         tw = w;
27108                         w = ow * (h/oh);
27109                         w = Math.min(Math.max(mw, w), mxw);
27110                         h = oh * (w/ow);
27111                         x += (tw - w) / 2;
27112                         break;
27113                     case 'southwest':
27114                         h = oh * (w/ow);
27115                         h = Math.min(Math.max(mh, h), mxh);
27116                         tw = w;
27117                         w = ow * (h/oh);
27118                         x += tw - w;
27119                         break;
27120                     case 'west':
27121                         th = h;
27122                         h = oh * (w/ow);
27123                         h = Math.min(Math.max(mh, h), mxh);
27124                         y += (th - h) / 2;
27125                         tw = w;
27126                         w = ow * (h/oh);
27127                         x += tw - w;
27128                        break;
27129                     case 'northwest':
27130                         tw = w;
27131                         th = h;
27132                         h = oh * (w/ow);
27133                         h = Math.min(Math.max(mh, h), mxh);
27134                         w = ow * (h/oh);
27135                         y += th - h;
27136                         x += tw - w;
27137                         break;
27138
27139                 }
27140             }
27141             this.proxy.setBounds(x, y, w, h);
27142             if(this.dynamic){
27143                 this.resizeElement();
27144             }
27145             }catch(ex){}
27146         }
27147     },
27148
27149     
27150     handleOver : function(){
27151         if(this.enabled){
27152             this.el.addClass('x-resizable-over');
27153         }
27154     },
27155
27156     
27157     handleOut : function(){
27158         if(!this.resizing){
27159             this.el.removeClass('x-resizable-over');
27160         }
27161     },
27162
27163     
27164     getEl : function(){
27165         return this.el;
27166     },
27167
27168     
27169     getResizeChild : function(){
27170         return this.resizeChild;
27171     },
27172
27173     
27174     destroy : function(removeEl){
27175         Ext.destroy(this.dd, this.overlay, this.proxy);
27176         this.overlay = null;
27177         this.proxy = null;
27178
27179         var ps = Ext.Resizable.positions;
27180         for(var k in ps){
27181             if(typeof ps[k] != 'function' && this[ps[k]]){
27182                 this[ps[k]].destroy();
27183             }
27184         }
27185         if(removeEl){
27186             this.el.update('');
27187             Ext.destroy(this.el);
27188             this.el = null;
27189         }
27190         this.purgeListeners();
27191     },
27192
27193     syncHandleHeight : function(){
27194         var h = this.el.getHeight(true);
27195         if(this.west){
27196             this.west.el.setHeight(h);
27197         }
27198         if(this.east){
27199             this.east.el.setHeight(h);
27200         }
27201     }
27202 });
27203
27204
27205
27206 Ext.Resizable.positions = {
27207     n: 'north', s: 'south', e: 'east', w: 'west', se: 'southeast', sw: 'southwest', nw: 'northwest', ne: 'northeast'
27208 };
27209
27210 Ext.Resizable.Handle = Ext.extend(Object, {
27211     constructor : function(rz, pos, disableTrackOver, transparent, cls){
27212        if(!this.tpl){
27213             
27214             var tpl = Ext.DomHelper.createTemplate(
27215                 {tag: 'div', cls: 'x-resizable-handle x-resizable-handle-{0}'}
27216             );
27217             tpl.compile();
27218             Ext.Resizable.Handle.prototype.tpl = tpl;
27219         }
27220         this.position = pos;
27221         this.rz = rz;
27222         this.el = this.tpl.append(rz.el.dom, [this.position], true);
27223         this.el.unselectable();
27224         if(transparent){
27225             this.el.setOpacity(0);
27226         }
27227         if(!Ext.isEmpty(cls)){
27228             this.el.addClass(cls);
27229         }
27230         this.el.on('mousedown', this.onMouseDown, this);
27231         if(!disableTrackOver){
27232             this.el.on({
27233                 scope: this,
27234                 mouseover: this.onMouseOver,
27235                 mouseout: this.onMouseOut
27236             });
27237         }
27238     },
27239
27240     
27241     afterResize : function(rz){
27242         
27243     },
27244     
27245     onMouseDown : function(e){
27246         this.rz.onMouseDown(this, e);
27247     },
27248     
27249     onMouseOver : function(e){
27250         this.rz.handleOver(this, e);
27251     },
27252     
27253     onMouseOut : function(e){
27254         this.rz.handleOut(this, e);
27255     },
27256     
27257     destroy : function(){
27258         Ext.destroy(this.el);
27259         this.el = null;
27260     }
27261 });
27262
27263 Ext.Window = Ext.extend(Ext.Panel, {
27264     
27265     
27266     
27267     
27268     
27269     
27270     
27271     
27272     
27273     
27274
27275     
27276     baseCls : 'x-window',
27277     
27278     resizable : true,
27279     
27280     draggable : true,
27281     
27282     closable : true,
27283     
27284     closeAction : 'close',
27285     
27286     constrain : false,
27287     
27288     constrainHeader : false,
27289     
27290     plain : false,
27291     
27292     minimizable : false,
27293     
27294     maximizable : false,
27295     
27296     minHeight : 100,
27297     
27298     minWidth : 200,
27299     
27300     expandOnShow : true,
27301     
27302     
27303     showAnimDuration: 0.25,
27304     
27305     
27306     hideAnimDuration: 0.25,
27307
27308     
27309     collapsible : false,
27310
27311     
27312     initHidden : undefined,
27313
27314     
27315     hidden : true,
27316
27317     
27318     
27319     
27320     
27321     
27322     elements : 'header,body',
27323     
27324     frame : true,
27325     
27326     floating : true,
27327
27328     
27329     initComponent : function(){
27330         this.initTools();
27331         Ext.Window.superclass.initComponent.call(this);
27332         this.addEvents(
27333             
27334             
27335             
27336             'resize',
27337             
27338             'maximize',
27339             
27340             'minimize',
27341             
27342             'restore'
27343         );
27344         
27345         if(Ext.isDefined(this.initHidden)){
27346             this.hidden = this.initHidden;
27347         }
27348         if(this.hidden === false){
27349             this.hidden = true;
27350             this.show();
27351         }
27352     },
27353
27354     
27355     getState : function(){
27356         return Ext.apply(Ext.Window.superclass.getState.call(this) || {}, this.getBox(true));
27357     },
27358
27359     
27360     onRender : function(ct, position){
27361         Ext.Window.superclass.onRender.call(this, ct, position);
27362
27363         if(this.plain){
27364             this.el.addClass('x-window-plain');
27365         }
27366
27367         
27368         this.focusEl = this.el.createChild({
27369                     tag: 'a', href:'#', cls:'x-dlg-focus',
27370                     tabIndex:'-1', html: '&#160;'});
27371         this.focusEl.swallowEvent('click', true);
27372
27373         this.proxy = this.el.createProxy('x-window-proxy');
27374         this.proxy.enableDisplayMode('block');
27375
27376         if(this.modal){
27377             this.mask = this.container.createChild({cls:'ext-el-mask'}, this.el.dom);
27378             this.mask.enableDisplayMode('block');
27379             this.mask.hide();
27380             this.mon(this.mask, 'click', this.focus, this);
27381         }
27382         if(this.maximizable){
27383             this.mon(this.header, 'dblclick', this.toggleMaximize, this);
27384         }
27385     },
27386
27387     
27388     initEvents : function(){
27389         Ext.Window.superclass.initEvents.call(this);
27390         if(this.animateTarget){
27391             this.setAnimateTarget(this.animateTarget);
27392         }
27393
27394         if(this.resizable){
27395             this.resizer = new Ext.Resizable(this.el, {
27396                 minWidth: this.minWidth,
27397                 minHeight:this.minHeight,
27398                 handles: this.resizeHandles || 'all',
27399                 pinned: true,
27400                 resizeElement : this.resizerAction,
27401                 handleCls: 'x-window-handle'
27402             });
27403             this.resizer.window = this;
27404             this.mon(this.resizer, 'beforeresize', this.beforeResize, this);
27405         }
27406
27407         if(this.draggable){
27408             this.header.addClass('x-window-draggable');
27409         }
27410         this.mon(this.el, 'mousedown', this.toFront, this);
27411         this.manager = this.manager || Ext.WindowMgr;
27412         this.manager.register(this);
27413         if(this.maximized){
27414             this.maximized = false;
27415             this.maximize();
27416         }
27417         if(this.closable){
27418             var km = this.getKeyMap();
27419             km.on(27, this.onEsc, this);
27420             km.disable();
27421         }
27422     },
27423
27424     initDraggable : function(){
27425         
27426         this.dd = new Ext.Window.DD(this);
27427     },
27428
27429    
27430     onEsc : function(k, e){
27431         e.stopEvent();
27432         this[this.closeAction]();
27433     },
27434
27435     
27436     beforeDestroy : function(){
27437         if(this.rendered){
27438             this.hide();
27439             this.clearAnchor();
27440             Ext.destroy(
27441                 this.focusEl,
27442                 this.resizer,
27443                 this.dd,
27444                 this.proxy,
27445                 this.mask
27446             );
27447         }
27448         Ext.Window.superclass.beforeDestroy.call(this);
27449     },
27450
27451     
27452     onDestroy : function(){
27453         if(this.manager){
27454             this.manager.unregister(this);
27455         }
27456         Ext.Window.superclass.onDestroy.call(this);
27457     },
27458
27459     
27460     initTools : function(){
27461         if(this.minimizable){
27462             this.addTool({
27463                 id: 'minimize',
27464                 handler: this.minimize.createDelegate(this, [])
27465             });
27466         }
27467         if(this.maximizable){
27468             this.addTool({
27469                 id: 'maximize',
27470                 handler: this.maximize.createDelegate(this, [])
27471             });
27472             this.addTool({
27473                 id: 'restore',
27474                 handler: this.restore.createDelegate(this, []),
27475                 hidden:true
27476             });
27477         }
27478         if(this.closable){
27479             this.addTool({
27480                 id: 'close',
27481                 handler: this[this.closeAction].createDelegate(this, [])
27482             });
27483         }
27484     },
27485
27486     
27487     resizerAction : function(){
27488         var box = this.proxy.getBox();
27489         this.proxy.hide();
27490         this.window.handleResize(box);
27491         return box;
27492     },
27493
27494     
27495     beforeResize : function(){
27496         this.resizer.minHeight = Math.max(this.minHeight, this.getFrameHeight() + 40); 
27497         this.resizer.minWidth = Math.max(this.minWidth, this.getFrameWidth() + 40);
27498         this.resizeBox = this.el.getBox();
27499     },
27500
27501     
27502     updateHandles : function(){
27503         if(Ext.isIE && this.resizer){
27504             this.resizer.syncHandleHeight();
27505             this.el.repaint();
27506         }
27507     },
27508
27509     
27510     handleResize : function(box){
27511         var rz = this.resizeBox;
27512         if(rz.x != box.x || rz.y != box.y){
27513             this.updateBox(box);
27514         }else{
27515             this.setSize(box);
27516             if (Ext.isIE6 && Ext.isStrict) {
27517                 this.doLayout();
27518             }
27519         }
27520         this.focus();
27521         this.updateHandles();
27522         this.saveState();
27523     },
27524
27525     
27526     focus : function(){
27527         var f = this.focusEl,
27528             db = this.defaultButton,
27529             t = typeof db,
27530             el,
27531             ct;
27532         if(Ext.isDefined(db)){
27533             if(Ext.isNumber(db) && this.fbar){
27534                 f = this.fbar.items.get(db);
27535             }else if(Ext.isString(db)){
27536                 f = Ext.getCmp(db);
27537             }else{
27538                 f = db;
27539             }
27540             el = f.getEl();
27541             ct = Ext.getDom(this.container);
27542             if (el && ct) {
27543                 if (ct != document.body && !Ext.lib.Region.getRegion(ct).contains(Ext.lib.Region.getRegion(el.dom))){
27544                     return;
27545                 }
27546             }
27547         }
27548         f = f || this.focusEl;
27549         f.focus.defer(10, f);
27550     },
27551
27552     
27553     setAnimateTarget : function(el){
27554         el = Ext.get(el);
27555         this.animateTarget = el;
27556     },
27557
27558     
27559     beforeShow : function(){
27560         delete this.el.lastXY;
27561         delete this.el.lastLT;
27562         if(this.x === undefined || this.y === undefined){
27563             var xy = this.el.getAlignToXY(this.container, 'c-c');
27564             var pos = this.el.translatePoints(xy[0], xy[1]);
27565             this.x = this.x === undefined? pos.left : this.x;
27566             this.y = this.y === undefined? pos.top : this.y;
27567         }
27568         this.el.setLeftTop(this.x, this.y);
27569
27570         if(this.expandOnShow){
27571             this.expand(false);
27572         }
27573
27574         if(this.modal){
27575             Ext.getBody().addClass('x-body-masked');
27576             this.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
27577             this.mask.show();
27578         }
27579     },
27580
27581     
27582     show : function(animateTarget, cb, scope){
27583         if(!this.rendered){
27584             this.render(Ext.getBody());
27585         }
27586         if(this.hidden === false){
27587             this.toFront();
27588             return this;
27589         }
27590         if(this.fireEvent('beforeshow', this) === false){
27591             return this;
27592         }
27593         if(cb){
27594             this.on('show', cb, scope, {single:true});
27595         }
27596         this.hidden = false;
27597         if(Ext.isDefined(animateTarget)){
27598             this.setAnimateTarget(animateTarget);
27599         }
27600         this.beforeShow();
27601         if(this.animateTarget){
27602             this.animShow();
27603         }else{
27604             this.afterShow();
27605         }
27606         return this;
27607     },
27608
27609     
27610     afterShow : function(isAnim){
27611         if (this.isDestroyed){
27612             return false;
27613         }
27614         this.proxy.hide();
27615         this.el.setStyle('display', 'block');
27616         this.el.show();
27617         if(this.maximized){
27618             this.fitContainer();
27619         }
27620         if(Ext.isMac && Ext.isGecko2){ 
27621             this.cascade(this.setAutoScroll);
27622         }
27623
27624         if(this.monitorResize || this.modal || this.constrain || this.constrainHeader){
27625             Ext.EventManager.onWindowResize(this.onWindowResize, this);
27626         }
27627         this.doConstrain();
27628         this.doLayout();
27629         if(this.keyMap){
27630             this.keyMap.enable();
27631         }
27632         this.toFront();
27633         this.updateHandles();
27634         if(isAnim && (Ext.isIE || Ext.isWebKit)){
27635             var sz = this.getSize();
27636             this.onResize(sz.width, sz.height);
27637         }
27638         this.onShow();
27639         this.fireEvent('show', this);
27640     },
27641
27642     
27643     animShow : function(){
27644         this.proxy.show();
27645         this.proxy.setBox(this.animateTarget.getBox());
27646         this.proxy.setOpacity(0);
27647         var b = this.getBox();
27648         this.el.setStyle('display', 'none');
27649         this.proxy.shift(Ext.apply(b, {
27650             callback: this.afterShow.createDelegate(this, [true], false),
27651             scope: this,
27652             easing: 'easeNone',
27653             duration: this.showAnimDuration,
27654             opacity: 0.5
27655         }));
27656     },
27657
27658     
27659     hide : function(animateTarget, cb, scope){
27660         if(this.hidden || this.fireEvent('beforehide', this) === false){
27661             return this;
27662         }
27663         if(cb){
27664             this.on('hide', cb, scope, {single:true});
27665         }
27666         this.hidden = true;
27667         if(animateTarget !== undefined){
27668             this.setAnimateTarget(animateTarget);
27669         }
27670         if(this.modal){
27671             this.mask.hide();
27672             Ext.getBody().removeClass('x-body-masked');
27673         }
27674         if(this.animateTarget){
27675             this.animHide();
27676         }else{
27677             this.el.hide();
27678             this.afterHide();
27679         }
27680         return this;
27681     },
27682
27683     
27684     afterHide : function(){
27685         this.proxy.hide();
27686         if(this.monitorResize || this.modal || this.constrain || this.constrainHeader){
27687             Ext.EventManager.removeResizeListener(this.onWindowResize, this);
27688         }
27689         if(this.keyMap){
27690             this.keyMap.disable();
27691         }
27692         this.onHide();
27693         this.fireEvent('hide', this);
27694     },
27695
27696     
27697     animHide : function(){
27698         this.proxy.setOpacity(0.5);
27699         this.proxy.show();
27700         var tb = this.getBox(false);
27701         this.proxy.setBox(tb);
27702         this.el.hide();
27703         this.proxy.shift(Ext.apply(this.animateTarget.getBox(), {
27704             callback: this.afterHide,
27705             scope: this,
27706             duration: this.hideAnimDuration,
27707             easing: 'easeNone',
27708             opacity: 0
27709         }));
27710     },
27711
27712     
27713     onShow : Ext.emptyFn,
27714
27715     
27716     onHide : Ext.emptyFn,
27717
27718     
27719     onWindowResize : function(){
27720         if(this.maximized){
27721             this.fitContainer();
27722         }
27723         if(this.modal){
27724             this.mask.setSize('100%', '100%');
27725             var force = this.mask.dom.offsetHeight;
27726             this.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
27727         }
27728         this.doConstrain();
27729     },
27730
27731     
27732     doConstrain : function(){
27733         if(this.constrain || this.constrainHeader){
27734             var offsets;
27735             if(this.constrain){
27736                 offsets = {
27737                     right:this.el.shadowOffset,
27738                     left:this.el.shadowOffset,
27739                     bottom:this.el.shadowOffset
27740                 };
27741             }else {
27742                 var s = this.getSize();
27743                 offsets = {
27744                     right:-(s.width - 100),
27745                     bottom:-(s.height - 25)
27746                 };
27747             }
27748
27749             var xy = this.el.getConstrainToXY(this.container, true, offsets);
27750             if(xy){
27751                 this.setPosition(xy[0], xy[1]);
27752             }
27753         }
27754     },
27755
27756     
27757     ghost : function(cls){
27758         var ghost = this.createGhost(cls);
27759         var box = this.getBox(true);
27760         ghost.setLeftTop(box.x, box.y);
27761         ghost.setWidth(box.width);
27762         this.el.hide();
27763         this.activeGhost = ghost;
27764         return ghost;
27765     },
27766
27767     
27768     unghost : function(show, matchPosition){
27769         if(!this.activeGhost) {
27770             return;
27771         }
27772         if(show !== false){
27773             this.el.show();
27774             this.focus.defer(10, this);
27775             if(Ext.isMac && Ext.isGecko2){ 
27776                 this.cascade(this.setAutoScroll);
27777             }
27778         }
27779         if(matchPosition !== false){
27780             this.setPosition(this.activeGhost.getLeft(true), this.activeGhost.getTop(true));
27781         }
27782         this.activeGhost.hide();
27783         this.activeGhost.remove();
27784         delete this.activeGhost;
27785     },
27786
27787     
27788     minimize : function(){
27789         this.fireEvent('minimize', this);
27790         return this;
27791     },
27792
27793     
27794     close : function(){
27795         if(this.fireEvent('beforeclose', this) !== false){
27796             if(this.hidden){
27797                 this.doClose();
27798             }else{
27799                 this.hide(null, this.doClose, this);
27800             }
27801         }
27802     },
27803
27804     
27805     doClose : function(){
27806         this.fireEvent('close', this);
27807         this.destroy();
27808     },
27809
27810     
27811     maximize : function(){
27812         if(!this.maximized){
27813             this.expand(false);
27814             this.restoreSize = this.getSize();
27815             this.restorePos = this.getPosition(true);
27816             if (this.maximizable){
27817                 this.tools.maximize.hide();
27818                 this.tools.restore.show();
27819             }
27820             this.maximized = true;
27821             this.el.disableShadow();
27822
27823             if(this.dd){
27824                 this.dd.lock();
27825             }
27826             if(this.collapsible){
27827                 this.tools.toggle.hide();
27828             }
27829             this.el.addClass('x-window-maximized');
27830             this.container.addClass('x-window-maximized-ct');
27831
27832             this.setPosition(0, 0);
27833             this.fitContainer();
27834             this.fireEvent('maximize', this);
27835         }
27836         return this;
27837     },
27838
27839     
27840     restore : function(){
27841         if(this.maximized){
27842             var t = this.tools;
27843             this.el.removeClass('x-window-maximized');
27844             if(t.restore){
27845                 t.restore.hide();
27846             }
27847             if(t.maximize){
27848                 t.maximize.show();
27849             }
27850             this.setPosition(this.restorePos[0], this.restorePos[1]);
27851             this.setSize(this.restoreSize.width, this.restoreSize.height);
27852             delete this.restorePos;
27853             delete this.restoreSize;
27854             this.maximized = false;
27855             this.el.enableShadow(true);
27856
27857             if(this.dd){
27858                 this.dd.unlock();
27859             }
27860             if(this.collapsible && t.toggle){
27861                 t.toggle.show();
27862             }
27863             this.container.removeClass('x-window-maximized-ct');
27864
27865             this.doConstrain();
27866             this.fireEvent('restore', this);
27867         }
27868         return this;
27869     },
27870
27871     
27872     toggleMaximize : function(){
27873         return this[this.maximized ? 'restore' : 'maximize']();
27874     },
27875
27876     
27877     fitContainer : function(){
27878         var vs = this.container.getViewSize(false);
27879         this.setSize(vs.width, vs.height);
27880     },
27881
27882     
27883     
27884     setZIndex : function(index){
27885         if(this.modal){
27886             this.mask.setStyle('z-index', index);
27887         }
27888         this.el.setZIndex(++index);
27889         index += 5;
27890
27891         if(this.resizer){
27892             this.resizer.proxy.setStyle('z-index', ++index);
27893         }
27894
27895         this.lastZIndex = index;
27896     },
27897
27898     
27899     alignTo : function(element, position, offsets){
27900         var xy = this.el.getAlignToXY(element, position, offsets);
27901         this.setPagePosition(xy[0], xy[1]);
27902         return this;
27903     },
27904
27905     
27906     anchorTo : function(el, alignment, offsets, monitorScroll){
27907         this.clearAnchor();
27908         this.anchorTarget = {
27909             el: el,
27910             alignment: alignment,
27911             offsets: offsets
27912         };
27913
27914         Ext.EventManager.onWindowResize(this.doAnchor, this);
27915         var tm = typeof monitorScroll;
27916         if(tm != 'undefined'){
27917             Ext.EventManager.on(window, 'scroll', this.doAnchor, this,
27918                 {buffer: tm == 'number' ? monitorScroll : 50});
27919         }
27920         return this.doAnchor();
27921     },
27922
27923     
27924     doAnchor : function(){
27925         var o = this.anchorTarget;
27926         this.alignTo(o.el, o.alignment, o.offsets);
27927         return this;
27928     },
27929
27930     
27931     clearAnchor : function(){
27932         if(this.anchorTarget){
27933             Ext.EventManager.removeResizeListener(this.doAnchor, this);
27934             Ext.EventManager.un(window, 'scroll', this.doAnchor, this);
27935             delete this.anchorTarget;
27936         }
27937         return this;
27938     },
27939
27940     
27941     toFront : function(e){
27942         if(this.manager.bringToFront(this)){
27943             if(!e || !e.getTarget().focus){
27944                 this.focus();
27945             }
27946         }
27947         return this;
27948     },
27949
27950     
27951     setActive : function(active){
27952         if(active){
27953             if(!this.maximized){
27954                 this.el.enableShadow(true);
27955             }
27956             this.fireEvent('activate', this);
27957         }else{
27958             this.el.disableShadow();
27959             this.fireEvent('deactivate', this);
27960         }
27961     },
27962
27963     
27964     toBack : function(){
27965         this.manager.sendToBack(this);
27966         return this;
27967     },
27968
27969     
27970     center : function(){
27971         var xy = this.el.getAlignToXY(this.container, 'c-c');
27972         this.setPagePosition(xy[0], xy[1]);
27973         return this;
27974     }
27975
27976     
27977 });
27978 Ext.reg('window', Ext.Window);
27979
27980
27981 Ext.Window.DD = Ext.extend(Ext.dd.DD, {
27982     
27983     constructor : function(win){
27984         this.win = win;
27985         Ext.Window.DD.superclass.constructor.call(this, win.el.id, 'WindowDD-'+win.id);
27986         this.setHandleElId(win.header.id);
27987         this.scroll = false;        
27988     },
27989     
27990     moveOnly:true,
27991     headerOffsets:[100, 25],
27992     startDrag : function(){
27993         var w = this.win;
27994         this.proxy = w.ghost(w.initialConfig.cls);
27995         if(w.constrain !== false){
27996             var so = w.el.shadowOffset;
27997             this.constrainTo(w.container, {right: so, left: so, bottom: so});
27998         }else if(w.constrainHeader !== false){
27999             var s = this.proxy.getSize();
28000             this.constrainTo(w.container, {right: -(s.width-this.headerOffsets[0]), bottom: -(s.height-this.headerOffsets[1])});
28001         }
28002     },
28003     b4Drag : Ext.emptyFn,
28004
28005     onDrag : function(e){
28006         this.alignElWithMouse(this.proxy, e.getPageX(), e.getPageY());
28007     },
28008
28009     endDrag : function(e){
28010         this.win.unghost();
28011         this.win.saveState();
28012     }
28013 });
28014
28015 Ext.WindowGroup = function(){
28016     var list = {};
28017     var accessList = [];
28018     var front = null;
28019
28020     
28021     var sortWindows = function(d1, d2){
28022         return (!d1._lastAccess || d1._lastAccess < d2._lastAccess) ? -1 : 1;
28023     };
28024
28025     
28026     var orderWindows = function(){
28027         var a = accessList, len = a.length;
28028         if(len > 0){
28029             a.sort(sortWindows);
28030             var seed = a[0].manager.zseed;
28031             for(var i = 0; i < len; i++){
28032                 var win = a[i];
28033                 if(win && !win.hidden){
28034                     win.setZIndex(seed + (i*10));
28035                 }
28036             }
28037         }
28038         activateLast();
28039     };
28040
28041     
28042     var setActiveWin = function(win){
28043         if(win != front){
28044             if(front){
28045                 front.setActive(false);
28046             }
28047             front = win;
28048             if(win){
28049                 win.setActive(true);
28050             }
28051         }
28052     };
28053
28054     
28055     var activateLast = function(){
28056         for(var i = accessList.length-1; i >=0; --i) {
28057             if(!accessList[i].hidden){
28058                 setActiveWin(accessList[i]);
28059                 return;
28060             }
28061         }
28062         
28063         setActiveWin(null);
28064     };
28065
28066     return {
28067         
28068         zseed : 9000,
28069
28070         
28071         register : function(win){
28072             if(win.manager){
28073                 win.manager.unregister(win);
28074             }
28075             win.manager = this;
28076
28077             list[win.id] = win;
28078             accessList.push(win);
28079             win.on('hide', activateLast);
28080         },
28081
28082         
28083         unregister : function(win){
28084             delete win.manager;
28085             delete list[win.id];
28086             win.un('hide', activateLast);
28087             accessList.remove(win);
28088         },
28089
28090         
28091         get : function(id){
28092             return typeof id == "object" ? id : list[id];
28093         },
28094
28095         
28096         bringToFront : function(win){
28097             win = this.get(win);
28098             if(win != front){
28099                 win._lastAccess = new Date().getTime();
28100                 orderWindows();
28101                 return true;
28102             }
28103             return false;
28104         },
28105
28106         
28107         sendToBack : function(win){
28108             win = this.get(win);
28109             win._lastAccess = -(new Date().getTime());
28110             orderWindows();
28111             return win;
28112         },
28113
28114         
28115         hideAll : function(){
28116             for(var id in list){
28117                 if(list[id] && typeof list[id] != "function" && list[id].isVisible()){
28118                     list[id].hide();
28119                 }
28120             }
28121         },
28122
28123         
28124         getActive : function(){
28125             return front;
28126         },
28127
28128         
28129         getBy : function(fn, scope){
28130             var r = [];
28131             for(var i = accessList.length-1; i >=0; --i) {
28132                 var win = accessList[i];
28133                 if(fn.call(scope||win, win) !== false){
28134                     r.push(win);
28135                 }
28136             }
28137             return r;
28138         },
28139
28140         
28141         each : function(fn, scope){
28142             for(var id in list){
28143                 if(list[id] && typeof list[id] != "function"){
28144                     if(fn.call(scope || list[id], list[id]) === false){
28145                         return;
28146                     }
28147                 }
28148             }
28149         }
28150     };
28151 };
28152
28153
28154
28155 Ext.WindowMgr = new Ext.WindowGroup();
28156 Ext.MessageBox = function(){
28157     var dlg, opt, mask, waitTimer,
28158         bodyEl, msgEl, textboxEl, textareaEl, progressBar, pp, iconEl, spacerEl,
28159         buttons, activeTextEl, bwidth, bufferIcon = '', iconCls = '',
28160         buttonNames = ['ok', 'yes', 'no', 'cancel'];
28161
28162     
28163     var handleButton = function(button){
28164         buttons[button].blur();
28165         if(dlg.isVisible()){
28166             dlg.hide();
28167             handleHide();
28168             Ext.callback(opt.fn, opt.scope||window, [button, activeTextEl.dom.value, opt], 1);
28169         }
28170     };
28171
28172     
28173     var handleHide = function(){
28174         if(opt && opt.cls){
28175             dlg.el.removeClass(opt.cls);
28176         }
28177         progressBar.reset();        
28178     };
28179
28180     
28181     var handleEsc = function(d, k, e){
28182         if(opt && opt.closable !== false){
28183             dlg.hide();
28184             handleHide();
28185         }
28186         if(e){
28187             e.stopEvent();
28188         }
28189     };
28190
28191     
28192     var updateButtons = function(b){
28193         var width = 0,
28194             cfg;
28195         if(!b){
28196             Ext.each(buttonNames, function(name){
28197                 buttons[name].hide();
28198             });
28199             return width;
28200         }
28201         dlg.footer.dom.style.display = '';
28202         Ext.iterate(buttons, function(name, btn){
28203             cfg = b[name];
28204             if(cfg){
28205                 btn.show();
28206                 btn.setText(Ext.isString(cfg) ? cfg : Ext.MessageBox.buttonText[name]);
28207                 width += btn.getEl().getWidth() + 15;
28208             }else{
28209                 btn.hide();
28210             }
28211         });
28212         return width;
28213     };
28214
28215     return {
28216         
28217         getDialog : function(titleText){
28218            if(!dlg){
28219                 var btns = [];
28220                 
28221                 buttons = {};
28222                 Ext.each(buttonNames, function(name){
28223                     btns.push(buttons[name] = new Ext.Button({
28224                         text: this.buttonText[name],
28225                         handler: handleButton.createCallback(name),
28226                         hideMode: 'offsets'
28227                     }));
28228                 }, this);
28229                 dlg = new Ext.Window({
28230                     autoCreate : true,
28231                     title:titleText,
28232                     resizable:false,
28233                     constrain:true,
28234                     constrainHeader:true,
28235                     minimizable : false,
28236                     maximizable : false,
28237                     stateful: false,
28238                     modal: true,
28239                     shim:true,
28240                     buttonAlign:"center",
28241                     width:400,
28242                     height:100,
28243                     minHeight: 80,
28244                     plain:true,
28245                     footer:true,
28246                     closable:true,
28247                     close : function(){
28248                         if(opt && opt.buttons && opt.buttons.no && !opt.buttons.cancel){
28249                             handleButton("no");
28250                         }else{
28251                             handleButton("cancel");
28252                         }
28253                     },
28254                     fbar: new Ext.Toolbar({
28255                         items: btns,
28256                         enableOverflow: false
28257                     })
28258                 });
28259                 dlg.render(document.body);
28260                 dlg.getEl().addClass('x-window-dlg');
28261                 mask = dlg.mask;
28262                 bodyEl = dlg.body.createChild({
28263                     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>'
28264                 });
28265                 iconEl = Ext.get(bodyEl.dom.firstChild);
28266                 var contentEl = bodyEl.dom.childNodes[1];
28267                 msgEl = Ext.get(contentEl.firstChild);
28268                 textboxEl = Ext.get(contentEl.childNodes[2].firstChild);
28269                 textboxEl.enableDisplayMode();
28270                 textboxEl.addKeyListener([10,13], function(){
28271                     if(dlg.isVisible() && opt && opt.buttons){
28272                         if(opt.buttons.ok){
28273                             handleButton("ok");
28274                         }else if(opt.buttons.yes){
28275                             handleButton("yes");
28276                         }
28277                     }
28278                 });
28279                 textareaEl = Ext.get(contentEl.childNodes[2].childNodes[1]);
28280                 textareaEl.enableDisplayMode();
28281                 progressBar = new Ext.ProgressBar({
28282                     renderTo:bodyEl
28283                 });
28284                bodyEl.createChild({cls:'x-clear'});
28285             }
28286             return dlg;
28287         },
28288
28289         
28290         updateText : function(text){
28291             if(!dlg.isVisible() && !opt.width){
28292                 dlg.setSize(this.maxWidth, 100); 
28293             }
28294             
28295             msgEl.update(text ? text + ' ' : '&#160;');
28296
28297             var iw = iconCls != '' ? (iconEl.getWidth() + iconEl.getMargins('lr')) : 0,
28298                 mw = msgEl.getWidth() + msgEl.getMargins('lr'),
28299                 fw = dlg.getFrameWidth('lr'),
28300                 bw = dlg.body.getFrameWidth('lr'),
28301                 w;
28302                 
28303             w = Math.max(Math.min(opt.width || iw+mw+fw+bw, opt.maxWidth || this.maxWidth),
28304                     Math.max(opt.minWidth || this.minWidth, bwidth || 0));
28305
28306             if(opt.prompt === true){
28307                 activeTextEl.setWidth(w-iw-fw-bw);
28308             }
28309             if(opt.progress === true || opt.wait === true){
28310                 progressBar.setSize(w-iw-fw-bw);
28311             }
28312             if(Ext.isIE && w == bwidth){
28313                 w += 4; 
28314             }
28315             msgEl.update(text || '&#160;');
28316             dlg.setSize(w, 'auto').center();
28317             return this;
28318         },
28319
28320         
28321         updateProgress : function(value, progressText, msg){
28322             progressBar.updateProgress(value, progressText);
28323             if(msg){
28324                 this.updateText(msg);
28325             }
28326             return this;
28327         },
28328
28329         
28330         isVisible : function(){
28331             return dlg && dlg.isVisible();
28332         },
28333
28334         
28335         hide : function(){
28336             var proxy = dlg ? dlg.activeGhost : null;
28337             if(this.isVisible() || proxy){
28338                 dlg.hide();
28339                 handleHide();
28340                 if (proxy){
28341                     
28342                     
28343                     dlg.unghost(false, false);
28344                 } 
28345             }
28346             return this;
28347         },
28348
28349         
28350         show : function(options){
28351             if(this.isVisible()){
28352                 this.hide();
28353             }
28354             opt = options;
28355             var d = this.getDialog(opt.title || "&#160;");
28356
28357             d.setTitle(opt.title || "&#160;");
28358             var allowClose = (opt.closable !== false && opt.progress !== true && opt.wait !== true);
28359             d.tools.close.setDisplayed(allowClose);
28360             activeTextEl = textboxEl;
28361             opt.prompt = opt.prompt || (opt.multiline ? true : false);
28362             if(opt.prompt){
28363                 if(opt.multiline){
28364                     textboxEl.hide();
28365                     textareaEl.show();
28366                     textareaEl.setHeight(Ext.isNumber(opt.multiline) ? opt.multiline : this.defaultTextHeight);
28367                     activeTextEl = textareaEl;
28368                 }else{
28369                     textboxEl.show();
28370                     textareaEl.hide();
28371                 }
28372             }else{
28373                 textboxEl.hide();
28374                 textareaEl.hide();
28375             }
28376             activeTextEl.dom.value = opt.value || "";
28377             if(opt.prompt){
28378                 d.focusEl = activeTextEl;
28379             }else{
28380                 var bs = opt.buttons;
28381                 var db = null;
28382                 if(bs && bs.ok){
28383                     db = buttons["ok"];
28384                 }else if(bs && bs.yes){
28385                     db = buttons["yes"];
28386                 }
28387                 if (db){
28388                     d.focusEl = db;
28389                 }
28390             }
28391             if(Ext.isDefined(opt.iconCls)){
28392               d.setIconClass(opt.iconCls);
28393             }
28394             this.setIcon(Ext.isDefined(opt.icon) ? opt.icon : bufferIcon);
28395             bwidth = updateButtons(opt.buttons);
28396             progressBar.setVisible(opt.progress === true || opt.wait === true);
28397             this.updateProgress(0, opt.progressText);
28398             this.updateText(opt.msg);
28399             if(opt.cls){
28400                 d.el.addClass(opt.cls);
28401             }
28402             d.proxyDrag = opt.proxyDrag === true;
28403             d.modal = opt.modal !== false;
28404             d.mask = opt.modal !== false ? mask : false;
28405             if(!d.isVisible()){
28406                 
28407                 document.body.appendChild(dlg.el.dom);
28408                 d.setAnimateTarget(opt.animEl);
28409                 
28410                 d.on('show', function(){
28411                     if(allowClose === true){
28412                         d.keyMap.enable();
28413                     }else{
28414                         d.keyMap.disable();
28415                     }
28416                 }, this, {single:true});
28417                 d.show(opt.animEl);
28418             }
28419             if(opt.wait === true){
28420                 progressBar.wait(opt.waitConfig);
28421             }
28422             return this;
28423         },
28424
28425         
28426         setIcon : function(icon){
28427             if(!dlg){
28428                 bufferIcon = icon;
28429                 return;
28430             }
28431             bufferIcon = undefined;
28432             if(icon && icon != ''){
28433                 iconEl.removeClass('x-hidden');
28434                 iconEl.replaceClass(iconCls, icon);
28435                 bodyEl.addClass('x-dlg-icon');
28436                 iconCls = icon;
28437             }else{
28438                 iconEl.replaceClass(iconCls, 'x-hidden');
28439                 bodyEl.removeClass('x-dlg-icon');
28440                 iconCls = '';
28441             }
28442             return this;
28443         },
28444
28445         
28446         progress : function(title, msg, progressText){
28447             this.show({
28448                 title : title,
28449                 msg : msg,
28450                 buttons: false,
28451                 progress:true,
28452                 closable:false,
28453                 minWidth: this.minProgressWidth,
28454                 progressText: progressText
28455             });
28456             return this;
28457         },
28458
28459         
28460         wait : function(msg, title, config){
28461             this.show({
28462                 title : title,
28463                 msg : msg,
28464                 buttons: false,
28465                 closable:false,
28466                 wait:true,
28467                 modal:true,
28468                 minWidth: this.minProgressWidth,
28469                 waitConfig: config
28470             });
28471             return this;
28472         },
28473
28474         
28475         alert : function(title, msg, fn, scope){
28476             this.show({
28477                 title : title,
28478                 msg : msg,
28479                 buttons: this.OK,
28480                 fn: fn,
28481                 scope : scope,
28482                 minWidth: this.minWidth
28483             });
28484             return this;
28485         },
28486
28487         
28488         confirm : function(title, msg, fn, scope){
28489             this.show({
28490                 title : title,
28491                 msg : msg,
28492                 buttons: this.YESNO,
28493                 fn: fn,
28494                 scope : scope,
28495                 icon: this.QUESTION,
28496                 minWidth: this.minWidth
28497             });
28498             return this;
28499         },
28500
28501         
28502         prompt : function(title, msg, fn, scope, multiline, value){
28503             this.show({
28504                 title : title,
28505                 msg : msg,
28506                 buttons: this.OKCANCEL,
28507                 fn: fn,
28508                 minWidth: this.minPromptWidth,
28509                 scope : scope,
28510                 prompt:true,
28511                 multiline: multiline,
28512                 value: value
28513             });
28514             return this;
28515         },
28516
28517         
28518         OK : {ok:true},
28519         
28520         CANCEL : {cancel:true},
28521         
28522         OKCANCEL : {ok:true, cancel:true},
28523         
28524         YESNO : {yes:true, no:true},
28525         
28526         YESNOCANCEL : {yes:true, no:true, cancel:true},
28527         
28528         INFO : 'ext-mb-info',
28529         
28530         WARNING : 'ext-mb-warning',
28531         
28532         QUESTION : 'ext-mb-question',
28533         
28534         ERROR : 'ext-mb-error',
28535
28536         
28537         defaultTextHeight : 75,
28538         
28539         maxWidth : 600,
28540         
28541         minWidth : 100,
28542         
28543         minProgressWidth : 250,
28544         
28545         minPromptWidth: 250,
28546         
28547         buttonText : {
28548             ok : "OK",
28549             cancel : "Cancel",
28550             yes : "Yes",
28551             no : "No"
28552         }
28553     };
28554 }();
28555
28556
28557 Ext.Msg = Ext.MessageBox;
28558 Ext.dd.PanelProxy  = Ext.extend(Object, {
28559     
28560     constructor : function(panel, config){
28561         this.panel = panel;
28562         this.id = this.panel.id +'-ddproxy';
28563         Ext.apply(this, config);        
28564     },
28565     
28566     
28567     insertProxy : true,
28568
28569     
28570     setStatus : Ext.emptyFn,
28571     reset : Ext.emptyFn,
28572     update : Ext.emptyFn,
28573     stop : Ext.emptyFn,
28574     sync: Ext.emptyFn,
28575
28576     
28577     getEl : function(){
28578         return this.ghost;
28579     },
28580
28581     
28582     getGhost : function(){
28583         return this.ghost;
28584     },
28585
28586     
28587     getProxy : function(){
28588         return this.proxy;
28589     },
28590
28591     
28592     hide : function(){
28593         if(this.ghost){
28594             if(this.proxy){
28595                 this.proxy.remove();
28596                 delete this.proxy;
28597             }
28598             this.panel.el.dom.style.display = '';
28599             this.ghost.remove();
28600             delete this.ghost;
28601         }
28602     },
28603
28604     
28605     show : function(){
28606         if(!this.ghost){
28607             this.ghost = this.panel.createGhost(this.panel.initialConfig.cls, undefined, Ext.getBody());
28608             this.ghost.setXY(this.panel.el.getXY());
28609             if(this.insertProxy){
28610                 this.proxy = this.panel.el.insertSibling({cls:'x-panel-dd-spacer'});
28611                 this.proxy.setSize(this.panel.getSize());
28612             }
28613             this.panel.el.dom.style.display = 'none';
28614         }
28615     },
28616
28617     
28618     repair : function(xy, callback, scope){
28619         this.hide();
28620         if(typeof callback == "function"){
28621             callback.call(scope || this);
28622         }
28623     },
28624
28625     
28626     moveProxy : function(parentNode, before){
28627         if(this.proxy){
28628             parentNode.insertBefore(this.proxy.dom, before);
28629         }
28630     }
28631 });
28632
28633
28634 Ext.Panel.DD = Ext.extend(Ext.dd.DragSource, {
28635     
28636     constructor : function(panel, cfg){
28637         this.panel = panel;
28638         this.dragData = {panel: panel};
28639         this.proxy = new Ext.dd.PanelProxy(panel, cfg);
28640         Ext.Panel.DD.superclass.constructor.call(this, panel.el, cfg);
28641         var h = panel.header,
28642             el = panel.body;
28643         if(h){
28644             this.setHandleElId(h.id);
28645             el = panel.header;
28646         }
28647         el.setStyle('cursor', 'move');
28648         this.scroll = false;        
28649     },
28650     
28651     showFrame: Ext.emptyFn,
28652     startDrag: Ext.emptyFn,
28653     b4StartDrag: function(x, y) {
28654         this.proxy.show();
28655     },
28656     b4MouseDown: function(e) {
28657         var x = e.getPageX(),
28658             y = e.getPageY();
28659         this.autoOffset(x, y);
28660     },
28661     onInitDrag : function(x, y){
28662         this.onStartDrag(x, y);
28663         return true;
28664     },
28665     createFrame : Ext.emptyFn,
28666     getDragEl : function(e){
28667         return this.proxy.ghost.dom;
28668     },
28669     endDrag : function(e){
28670         this.proxy.hide();
28671         this.panel.saveState();
28672     },
28673
28674     autoOffset : function(x, y) {
28675         x -= this.startPageX;
28676         y -= this.startPageY;
28677         this.setDelta(x, y);
28678     }
28679 });
28680 Ext.state.Provider = Ext.extend(Ext.util.Observable, {
28681     
28682     constructor : function(){
28683         
28684         this.addEvents("statechange");
28685         this.state = {};
28686         Ext.state.Provider.superclass.constructor.call(this);
28687     },
28688     
28689     
28690     get : function(name, defaultValue){
28691         return typeof this.state[name] == "undefined" ?
28692             defaultValue : this.state[name];
28693     },
28694
28695     
28696     clear : function(name){
28697         delete this.state[name];
28698         this.fireEvent("statechange", this, name, null);
28699     },
28700
28701     
28702     set : function(name, value){
28703         this.state[name] = value;
28704         this.fireEvent("statechange", this, name, value);
28705     },
28706
28707     
28708     decodeValue : function(cookie){
28709         
28710         var re = /^(a|n|d|b|s|o|e)\:(.*)$/,
28711             matches = re.exec(unescape(cookie)),
28712             all,
28713             type,
28714             v,
28715             kv;
28716         if(!matches || !matches[1]){
28717             return; 
28718         }
28719         type = matches[1];
28720         v = matches[2];
28721         switch(type){
28722             case 'e':
28723                 return null;
28724             case 'n':
28725                 return parseFloat(v);
28726             case 'd':
28727                 return new Date(Date.parse(v));
28728             case 'b':
28729                 return (v == '1');
28730             case 'a':
28731                 all = [];
28732                 if(v != ''){
28733                     Ext.each(v.split('^'), function(val){
28734                         all.push(this.decodeValue(val));
28735                     }, this);
28736                 }
28737                 return all;
28738            case 'o':
28739                 all = {};
28740                 if(v != ''){
28741                     Ext.each(v.split('^'), function(val){
28742                         kv = val.split('=');
28743                         all[kv[0]] = this.decodeValue(kv[1]);
28744                     }, this);
28745                 }
28746                 return all;
28747            default:
28748                 return v;
28749         }
28750     },
28751
28752     
28753     encodeValue : function(v){
28754         var enc,
28755             flat = '',
28756             i = 0,
28757             len,
28758             key;
28759         if(v == null){
28760             return 'e:1';    
28761         }else if(typeof v == 'number'){
28762             enc = 'n:' + v;
28763         }else if(typeof v == 'boolean'){
28764             enc = 'b:' + (v ? '1' : '0');
28765         }else if(Ext.isDate(v)){
28766             enc = 'd:' + v.toGMTString();
28767         }else if(Ext.isArray(v)){
28768             for(len = v.length; i < len; i++){
28769                 flat += this.encodeValue(v[i]);
28770                 if(i != len - 1){
28771                     flat += '^';
28772                 }
28773             }
28774             enc = 'a:' + flat;
28775         }else if(typeof v == 'object'){
28776             for(key in v){
28777                 if(typeof v[key] != 'function' && v[key] !== undefined){
28778                     flat += key + '=' + this.encodeValue(v[key]) + '^';
28779                 }
28780             }
28781             enc = 'o:' + flat.substring(0, flat.length-1);
28782         }else{
28783             enc = 's:' + v;
28784         }
28785         return escape(enc);
28786     }
28787 });
28788
28789 Ext.state.Manager = function(){
28790     var provider = new Ext.state.Provider();
28791
28792     return {
28793         
28794         setProvider : function(stateProvider){
28795             provider = stateProvider;
28796         },
28797
28798         
28799         get : function(key, defaultValue){
28800             return provider.get(key, defaultValue);
28801         },
28802
28803         
28804          set : function(key, value){
28805             provider.set(key, value);
28806         },
28807
28808         
28809         clear : function(key){
28810             provider.clear(key);
28811         },
28812
28813         
28814         getProvider : function(){
28815             return provider;
28816         }
28817     };
28818 }();
28819
28820 Ext.state.CookieProvider = Ext.extend(Ext.state.Provider, {
28821     
28822     constructor : function(config){
28823         Ext.state.CookieProvider.superclass.constructor.call(this);
28824         this.path = "/";
28825         this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); 
28826         this.domain = null;
28827         this.secure = false;
28828         Ext.apply(this, config);
28829         this.state = this.readCookies();
28830     },
28831     
28832     
28833     set : function(name, value){
28834         if(typeof value == "undefined" || value === null){
28835             this.clear(name);
28836             return;
28837         }
28838         this.setCookie(name, value);
28839         Ext.state.CookieProvider.superclass.set.call(this, name, value);
28840     },
28841
28842     
28843     clear : function(name){
28844         this.clearCookie(name);
28845         Ext.state.CookieProvider.superclass.clear.call(this, name);
28846     },
28847
28848     
28849     readCookies : function(){
28850         var cookies = {},
28851             c = document.cookie + ";",
28852             re = /\s?(.*?)=(.*?);/g,
28853             matches,
28854             name,
28855             value;
28856         while((matches = re.exec(c)) != null){
28857             name = matches[1];
28858             value = matches[2];
28859             if(name && name.substring(0,3) == "ys-"){
28860                 cookies[name.substr(3)] = this.decodeValue(value);
28861             }
28862         }
28863         return cookies;
28864     },
28865
28866     
28867     setCookie : function(name, value){
28868         document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
28869            ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
28870            ((this.path == null) ? "" : ("; path=" + this.path)) +
28871            ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
28872            ((this.secure == true) ? "; secure" : "");
28873     },
28874
28875     
28876     clearCookie : function(name){
28877         document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
28878            ((this.path == null) ? "" : ("; path=" + this.path)) +
28879            ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
28880            ((this.secure == true) ? "; secure" : "");
28881     }
28882 });
28883 Ext.DataView = Ext.extend(Ext.BoxComponent, {
28884     
28885     
28886     
28887     
28888     
28889     
28890     
28891     
28892     
28893     selectedClass : "x-view-selected",
28894     
28895     emptyText : "",
28896
28897     
28898     deferEmptyText: true,
28899     
28900     trackOver: false,
28901     
28902     
28903     blockRefresh: false,
28904
28905     
28906     last: false,
28907
28908     
28909     initComponent : function(){
28910         Ext.DataView.superclass.initComponent.call(this);
28911         if(Ext.isString(this.tpl) || Ext.isArray(this.tpl)){
28912             this.tpl = new Ext.XTemplate(this.tpl);
28913         }
28914
28915         this.addEvents(
28916             
28917             "beforeclick",
28918             
28919             "click",
28920             
28921             "mouseenter",
28922             
28923             "mouseleave",
28924             
28925             "containerclick",
28926             
28927             "dblclick",
28928             
28929             "contextmenu",
28930             
28931             "containercontextmenu",
28932             
28933             "selectionchange",
28934
28935             
28936             "beforeselect"
28937         );
28938
28939         this.store = Ext.StoreMgr.lookup(this.store);
28940         this.all = new Ext.CompositeElementLite();
28941         this.selected = new Ext.CompositeElementLite();
28942     },
28943
28944     
28945     afterRender : function(){
28946         Ext.DataView.superclass.afterRender.call(this);
28947
28948                 this.mon(this.getTemplateTarget(), {
28949             "click": this.onClick,
28950             "dblclick": this.onDblClick,
28951             "contextmenu": this.onContextMenu,
28952             scope:this
28953         });
28954
28955         if(this.overClass || this.trackOver){
28956             this.mon(this.getTemplateTarget(), {
28957                 "mouseover": this.onMouseOver,
28958                 "mouseout": this.onMouseOut,
28959                 scope:this
28960             });
28961         }
28962
28963         if(this.store){
28964             this.bindStore(this.store, true);
28965         }
28966     },
28967
28968     
28969     refresh : function() {
28970         this.clearSelections(false, true);
28971         var el = this.getTemplateTarget(),
28972             records = this.store.getRange();
28973             
28974         el.update('');
28975         if(records.length < 1){
28976             if(!this.deferEmptyText || this.hasSkippedEmptyText){
28977                 el.update(this.emptyText);
28978             }
28979             this.all.clear();
28980         }else{
28981             this.tpl.overwrite(el, this.collectData(records, 0));
28982             this.all.fill(Ext.query(this.itemSelector, el.dom));
28983             this.updateIndexes(0);
28984         }
28985         this.hasSkippedEmptyText = true;
28986     },
28987
28988     getTemplateTarget: function(){
28989         return this.el;
28990     },
28991
28992     
28993     prepareData : function(data){
28994         return data;
28995     },
28996
28997     
28998     collectData : function(records, startIndex){
28999         var r = [],
29000             i = 0,
29001             len = records.length;
29002         for(; i < len; i++){
29003             r[r.length] = this.prepareData(records[i].data, startIndex + i, records[i]);
29004         }
29005         return r;
29006     },
29007
29008     
29009     bufferRender : function(records, index){
29010         var div = document.createElement('div');
29011         this.tpl.overwrite(div, this.collectData(records, index));
29012         return Ext.query(this.itemSelector, div);
29013     },
29014
29015     
29016     onUpdate : function(ds, record){
29017         var index = this.store.indexOf(record);
29018         if(index > -1){
29019             var sel = this.isSelected(index),
29020                 original = this.all.elements[index],
29021                 node = this.bufferRender([record], index)[0];
29022
29023             this.all.replaceElement(index, node, true);
29024             if(sel){
29025                 this.selected.replaceElement(original, node);
29026                 this.all.item(index).addClass(this.selectedClass);
29027             }
29028             this.updateIndexes(index, index);
29029         }
29030     },
29031
29032     
29033     onAdd : function(ds, records, index){
29034         if(this.all.getCount() === 0){
29035             this.refresh();
29036             return;
29037         }
29038         var nodes = this.bufferRender(records, index), n, a = this.all.elements;
29039         if(index < this.all.getCount()){
29040             n = this.all.item(index).insertSibling(nodes, 'before', true);
29041             a.splice.apply(a, [index, 0].concat(nodes));
29042         }else{
29043             n = this.all.last().insertSibling(nodes, 'after', true);
29044             a.push.apply(a, nodes);
29045         }
29046         this.updateIndexes(index);
29047     },
29048
29049     
29050     onRemove : function(ds, record, index){
29051         this.deselect(index);
29052         this.all.removeElement(index, true);
29053         this.updateIndexes(index);
29054         if (this.store.getCount() === 0){
29055             this.refresh();
29056         }
29057     },
29058
29059     
29060     refreshNode : function(index){
29061         this.onUpdate(this.store, this.store.getAt(index));
29062     },
29063
29064     
29065     updateIndexes : function(startIndex, endIndex){
29066         var ns = this.all.elements;
29067         startIndex = startIndex || 0;
29068         endIndex = endIndex || ((endIndex === 0) ? 0 : (ns.length - 1));
29069         for(var i = startIndex; i <= endIndex; i++){
29070             ns[i].viewIndex = i;
29071         }
29072     },
29073     
29074     
29075     getStore : function(){
29076         return this.store;
29077     },
29078
29079     
29080     bindStore : function(store, initial){
29081         if(!initial && this.store){
29082             if(store !== this.store && this.store.autoDestroy){
29083                 this.store.destroy();
29084             }else{
29085                 this.store.un("beforeload", this.onBeforeLoad, this);
29086                 this.store.un("datachanged", this.onDataChanged, this);
29087                 this.store.un("add", this.onAdd, this);
29088                 this.store.un("remove", this.onRemove, this);
29089                 this.store.un("update", this.onUpdate, this);
29090                 this.store.un("clear", this.refresh, this);
29091             }
29092             if(!store){
29093                 this.store = null;
29094             }
29095         }
29096         if(store){
29097             store = Ext.StoreMgr.lookup(store);
29098             store.on({
29099                 scope: this,
29100                 beforeload: this.onBeforeLoad,
29101                 datachanged: this.onDataChanged,
29102                 add: this.onAdd,
29103                 remove: this.onRemove,
29104                 update: this.onUpdate,
29105                 clear: this.refresh
29106             });
29107         }
29108         this.store = store;
29109         if(store){
29110             this.refresh();
29111         }
29112     },
29113     
29114     
29115     onDataChanged: function() {
29116         if (this.blockRefresh !== true) {
29117             this.refresh.apply(this, arguments);
29118         }
29119     },
29120
29121     
29122     findItemFromChild : function(node){
29123         return Ext.fly(node).findParent(this.itemSelector, this.getTemplateTarget());
29124     },
29125
29126     
29127     onClick : function(e){
29128         var item = e.getTarget(this.itemSelector, this.getTemplateTarget()),
29129             index;
29130         if(item){
29131             index = this.indexOf(item);
29132             if(this.onItemClick(item, index, e) !== false){
29133                 this.fireEvent("click", this, index, item, e);
29134             }
29135         }else{
29136             if(this.fireEvent("containerclick", this, e) !== false){
29137                 this.onContainerClick(e);
29138             }
29139         }
29140     },
29141
29142     onContainerClick : function(e){
29143         this.clearSelections();
29144     },
29145
29146     
29147     onContextMenu : function(e){
29148         var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
29149         if(item){
29150             this.fireEvent("contextmenu", this, this.indexOf(item), item, e);
29151         }else{
29152             this.fireEvent("containercontextmenu", this, e);
29153         }
29154     },
29155
29156     
29157     onDblClick : function(e){
29158         var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
29159         if(item){
29160             this.fireEvent("dblclick", this, this.indexOf(item), item, e);
29161         }
29162     },
29163
29164     
29165     onMouseOver : function(e){
29166         var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
29167         if(item && item !== this.lastItem){
29168             this.lastItem = item;
29169             Ext.fly(item).addClass(this.overClass);
29170             this.fireEvent("mouseenter", this, this.indexOf(item), item, e);
29171         }
29172     },
29173
29174     
29175     onMouseOut : function(e){
29176         if(this.lastItem){
29177             if(!e.within(this.lastItem, true, true)){
29178                 Ext.fly(this.lastItem).removeClass(this.overClass);
29179                 this.fireEvent("mouseleave", this, this.indexOf(this.lastItem), this.lastItem, e);
29180                 delete this.lastItem;
29181             }
29182         }
29183     },
29184
29185     
29186     onItemClick : function(item, index, e){
29187         if(this.fireEvent("beforeclick", this, index, item, e) === false){
29188             return false;
29189         }
29190         if(this.multiSelect){
29191             this.doMultiSelection(item, index, e);
29192             e.preventDefault();
29193         }else if(this.singleSelect){
29194             this.doSingleSelection(item, index, e);
29195             e.preventDefault();
29196         }
29197         return true;
29198     },
29199
29200     
29201     doSingleSelection : function(item, index, e){
29202         if(e.ctrlKey && this.isSelected(index)){
29203             this.deselect(index);
29204         }else{
29205             this.select(index, false);
29206         }
29207     },
29208
29209     
29210     doMultiSelection : function(item, index, e){
29211         if(e.shiftKey && this.last !== false){
29212             var last = this.last;
29213             this.selectRange(last, index, e.ctrlKey);
29214             this.last = last; 
29215         }else{
29216             if((e.ctrlKey||this.simpleSelect) && this.isSelected(index)){
29217                 this.deselect(index);
29218             }else{
29219                 this.select(index, e.ctrlKey || e.shiftKey || this.simpleSelect);
29220             }
29221         }
29222     },
29223
29224     
29225     getSelectionCount : function(){
29226         return this.selected.getCount();
29227     },
29228
29229     
29230     getSelectedNodes : function(){
29231         return this.selected.elements;
29232     },
29233
29234     
29235     getSelectedIndexes : function(){
29236         var indexes = [], 
29237             selected = this.selected.elements,
29238             i = 0,
29239             len = selected.length;
29240             
29241         for(; i < len; i++){
29242             indexes.push(selected[i].viewIndex);
29243         }
29244         return indexes;
29245     },
29246
29247     
29248     getSelectedRecords : function(){
29249         return this.getRecords(this.selected.elements);
29250     },
29251
29252     
29253     getRecords : function(nodes){
29254         var records = [], 
29255             i = 0,
29256             len = nodes.length;
29257             
29258         for(; i < len; i++){
29259             records[records.length] = this.store.getAt(nodes[i].viewIndex);
29260         }
29261         return records;
29262     },
29263
29264     
29265     getRecord : function(node){
29266         return this.store.getAt(node.viewIndex);
29267     },
29268
29269     
29270     clearSelections : function(suppressEvent, skipUpdate){
29271         if((this.multiSelect || this.singleSelect) && this.selected.getCount() > 0){
29272             if(!skipUpdate){
29273                 this.selected.removeClass(this.selectedClass);
29274             }
29275             this.selected.clear();
29276             this.last = false;
29277             if(!suppressEvent){
29278                 this.fireEvent("selectionchange", this, this.selected.elements);
29279             }
29280         }
29281     },
29282
29283     
29284     isSelected : function(node){
29285         return this.selected.contains(this.getNode(node));
29286     },
29287
29288     
29289     deselect : function(node){
29290         if(this.isSelected(node)){
29291             node = this.getNode(node);
29292             this.selected.removeElement(node);
29293             if(this.last == node.viewIndex){
29294                 this.last = false;
29295             }
29296             Ext.fly(node).removeClass(this.selectedClass);
29297             this.fireEvent("selectionchange", this, this.selected.elements);
29298         }
29299     },
29300
29301     
29302     select : function(nodeInfo, keepExisting, suppressEvent){
29303         if(Ext.isArray(nodeInfo)){
29304             if(!keepExisting){
29305                 this.clearSelections(true);
29306             }
29307             for(var i = 0, len = nodeInfo.length; i < len; i++){
29308                 this.select(nodeInfo[i], true, true);
29309             }
29310             if(!suppressEvent){
29311                 this.fireEvent("selectionchange", this, this.selected.elements);
29312             }
29313         } else{
29314             var node = this.getNode(nodeInfo);
29315             if(!keepExisting){
29316                 this.clearSelections(true);
29317             }
29318             if(node && !this.isSelected(node)){
29319                 if(this.fireEvent("beforeselect", this, node, this.selected.elements) !== false){
29320                     Ext.fly(node).addClass(this.selectedClass);
29321                     this.selected.add(node);
29322                     this.last = node.viewIndex;
29323                     if(!suppressEvent){
29324                         this.fireEvent("selectionchange", this, this.selected.elements);
29325                     }
29326                 }
29327             }
29328         }
29329     },
29330
29331     
29332     selectRange : function(start, end, keepExisting){
29333         if(!keepExisting){
29334             this.clearSelections(true);
29335         }
29336         this.select(this.getNodes(start, end), true);
29337     },
29338
29339     
29340     getNode : function(nodeInfo){
29341         if(Ext.isString(nodeInfo)){
29342             return document.getElementById(nodeInfo);
29343         }else if(Ext.isNumber(nodeInfo)){
29344             return this.all.elements[nodeInfo];
29345         }else if(nodeInfo instanceof Ext.data.Record){
29346             var idx = this.store.indexOf(nodeInfo);
29347             return this.all.elements[idx];
29348         }
29349         return nodeInfo;
29350     },
29351
29352     
29353     getNodes : function(start, end){
29354         var ns = this.all.elements,
29355             nodes = [],
29356             i;
29357             
29358         start = start || 0;
29359         end = !Ext.isDefined(end) ? Math.max(ns.length - 1, 0) : end;
29360         if(start <= end){
29361             for(i = start; i <= end && ns[i]; i++){
29362                 nodes.push(ns[i]);
29363             }
29364         } else{
29365             for(i = start; i >= end && ns[i]; i--){
29366                 nodes.push(ns[i]);
29367             }
29368         }
29369         return nodes;
29370     },
29371
29372     
29373     indexOf : function(node){
29374         node = this.getNode(node);
29375         if(Ext.isNumber(node.viewIndex)){
29376             return node.viewIndex;
29377         }
29378         return this.all.indexOf(node);
29379     },
29380
29381     
29382     onBeforeLoad : function(){
29383         if(this.loadingText){
29384             this.clearSelections(false, true);
29385             this.getTemplateTarget().update('<div class="loading-indicator">'+this.loadingText+'</div>');
29386             this.all.clear();
29387         }
29388     },
29389
29390     onDestroy : function(){
29391         this.all.clear();
29392         this.selected.clear();
29393         Ext.DataView.superclass.onDestroy.call(this);
29394         this.bindStore(null);
29395     }
29396 });
29397
29398
29399 Ext.DataView.prototype.setStore = Ext.DataView.prototype.bindStore;
29400
29401 Ext.reg('dataview', Ext.DataView);
29402
29403 Ext.list.ListView = Ext.extend(Ext.DataView, {
29404     
29405     
29406     
29407     itemSelector: 'dl',
29408     
29409     selectedClass:'x-list-selected',
29410     
29411     overClass:'x-list-over',
29412     
29413     
29414     scrollOffset : undefined,
29415     
29416     columnResize: true,
29417     
29418     
29419     columnSort: true,
29420     
29421
29422     
29423     maxColumnWidth: Ext.isIE ? 99 : 100,
29424
29425     initComponent : function(){
29426         if(this.columnResize){
29427             this.colResizer = new Ext.list.ColumnResizer(this.colResizer);
29428             this.colResizer.init(this);
29429         }
29430         if(this.columnSort){
29431             this.colSorter = new Ext.list.Sorter(this.columnSort);
29432             this.colSorter.init(this);
29433         }
29434         if(!this.internalTpl){
29435             this.internalTpl = new Ext.XTemplate(
29436                 '<div class="x-list-header"><div class="x-list-header-inner">',
29437                     '<tpl for="columns">',
29438                     '<div style="width:{[values.width*100]}%;text-align:{align};"><em unselectable="on" id="',this.id, '-xlhd-{#}">',
29439                         '{header}',
29440                     '</em></div>',
29441                     '</tpl>',
29442                     '<div class="x-clear"></div>',
29443                 '</div></div>',
29444                 '<div class="x-list-body"><div class="x-list-body-inner">',
29445                 '</div></div>'
29446             );
29447         }
29448         if(!this.tpl){
29449             this.tpl = new Ext.XTemplate(
29450                 '<tpl for="rows">',
29451                     '<dl>',
29452                         '<tpl for="parent.columns">',
29453                         '<dt style="width:{[values.width*100]}%;text-align:{align};">',
29454                         '<em unselectable="on"<tpl if="cls"> class="{cls}</tpl>">',
29455                             '{[values.tpl.apply(parent)]}',
29456                         '</em></dt>',
29457                         '</tpl>',
29458                         '<div class="x-clear"></div>',
29459                     '</dl>',
29460                 '</tpl>'
29461             );
29462         };
29463
29464         var cs = this.columns,
29465             allocatedWidth = 0,
29466             colsWithWidth = 0,
29467             len = cs.length,
29468             columns = [];
29469
29470         for(var i = 0; i < len; i++){
29471             var c = cs[i];
29472             if(!c.isColumn) {
29473                 c.xtype = c.xtype ? (/^lv/.test(c.xtype) ? c.xtype : 'lv' + c.xtype) : 'lvcolumn';
29474                 c = Ext.create(c);
29475             }
29476             if(c.width) {
29477                 allocatedWidth += c.width*100;
29478                 if(allocatedWidth > this.maxColumnWidth){
29479                     c.width -= (allocatedWidth - this.maxColumnWidth) / 100;
29480                 }
29481                 colsWithWidth++;
29482             }
29483             columns.push(c);
29484         }
29485
29486         cs = this.columns = columns;
29487
29488         
29489         if(colsWithWidth < len){
29490             var remaining = len - colsWithWidth;
29491             if(allocatedWidth < this.maxColumnWidth){
29492                 var perCol = ((this.maxColumnWidth-allocatedWidth) / remaining)/100;
29493                 for(var j = 0; j < len; j++){
29494                     var c = cs[j];
29495                     if(!c.width){
29496                         c.width = perCol;
29497                     }
29498                 }
29499             }
29500         }
29501         Ext.list.ListView.superclass.initComponent.call(this);
29502     },
29503
29504     onRender : function(){
29505         this.autoEl = {
29506             cls: 'x-list-wrap'
29507         };
29508         Ext.list.ListView.superclass.onRender.apply(this, arguments);
29509
29510         this.internalTpl.overwrite(this.el, {columns: this.columns});
29511
29512         this.innerBody = Ext.get(this.el.dom.childNodes[1].firstChild);
29513         this.innerHd = Ext.get(this.el.dom.firstChild.firstChild);
29514
29515         if(this.hideHeaders){
29516             this.el.dom.firstChild.style.display = 'none';
29517         }
29518     },
29519
29520     getTemplateTarget : function(){
29521         return this.innerBody;
29522     },
29523
29524     
29525     collectData : function(){
29526         var rs = Ext.list.ListView.superclass.collectData.apply(this, arguments);
29527         return {
29528             columns: this.columns,
29529             rows: rs
29530         };
29531     },
29532
29533     verifyInternalSize : function(){
29534         if(this.lastSize){
29535             this.onResize(this.lastSize.width, this.lastSize.height);
29536         }
29537     },
29538
29539     
29540     onResize : function(w, h){
29541         var body = this.innerBody.dom,
29542             header = this.innerHd.dom,
29543             scrollWidth = w - Ext.num(this.scrollOffset, Ext.getScrollBarWidth()) + 'px',
29544             parentNode;
29545             
29546         if(!body){
29547             return;
29548         }
29549         parentNode = body.parentNode;
29550         if(Ext.isNumber(w)){
29551             if(this.reserveScrollOffset || ((parentNode.offsetWidth - parentNode.clientWidth) > 10)){
29552                 body.style.width = scrollWidth;
29553                 header.style.width = scrollWidth;
29554             }else{
29555                 body.style.width = w + 'px';
29556                 header.style.width = w + 'px';
29557                 setTimeout(function(){
29558                     if((parentNode.offsetWidth - parentNode.clientWidth) > 10){
29559                         body.style.width = scrollWidth;
29560                         header.style.width = scrollWidth;
29561                     }
29562                 }, 10);
29563             }
29564         }
29565         if(Ext.isNumber(h)){
29566             parentNode.style.height = Math.max(0, h - header.parentNode.offsetHeight) + 'px';
29567         }
29568     },
29569
29570     updateIndexes : function(){
29571         Ext.list.ListView.superclass.updateIndexes.apply(this, arguments);
29572         this.verifyInternalSize();
29573     },
29574
29575     findHeaderIndex : function(header){
29576         header = header.dom || header;
29577         var parentNode = header.parentNode, 
29578             children = parentNode.parentNode.childNodes,
29579             i = 0,
29580             c;
29581         for(; c = children[i]; i++){
29582             if(c == parentNode){
29583                 return i;
29584             }
29585         }
29586         return -1;
29587     },
29588
29589     setHdWidths : function(){
29590         var els = this.innerHd.dom.getElementsByTagName('div'),
29591             i = 0,
29592             columns = this.columns,
29593             len = columns.length;
29594             
29595         for(; i < len; i++){
29596             els[i].style.width = (columns[i].width*100) + '%';
29597         }
29598     }
29599 });
29600
29601 Ext.reg('listview', Ext.list.ListView);
29602
29603
29604 Ext.ListView = Ext.list.ListView;
29605 Ext.list.Column = Ext.extend(Object, {
29606     
29607     isColumn: true,
29608     
29609             
29610     align: 'left',
29611         
29612     header: '',
29613     
29614         
29615     width: null,
29616
29617     
29618     cls: '',
29619     
29620     
29621
29622     
29623     
29624     constructor : function(c){
29625         if(!c.tpl){
29626             c.tpl = new Ext.XTemplate('{' + c.dataIndex + '}');
29627         }
29628         else if(Ext.isString(c.tpl)){
29629             c.tpl = new Ext.XTemplate(c.tpl);
29630         }
29631         
29632         Ext.apply(this, c);
29633     }
29634 });
29635
29636 Ext.reg('lvcolumn', Ext.list.Column);
29637
29638
29639 Ext.list.NumberColumn = Ext.extend(Ext.list.Column, {
29640         
29641     format: '0,000.00',
29642     
29643     constructor : function(c) {
29644         c.tpl = c.tpl || new Ext.XTemplate('{' + c.dataIndex + ':number("' + (c.format || this.format) + '")}');       
29645         Ext.list.NumberColumn.superclass.constructor.call(this, c);
29646     }
29647 });
29648
29649 Ext.reg('lvnumbercolumn', Ext.list.NumberColumn);
29650
29651
29652 Ext.list.DateColumn = Ext.extend(Ext.list.Column, {
29653     format: 'm/d/Y',
29654     constructor : function(c) {
29655         c.tpl = c.tpl || new Ext.XTemplate('{' + c.dataIndex + ':date("' + (c.format || this.format) + '")}');      
29656         Ext.list.DateColumn.superclass.constructor.call(this, c);
29657     }
29658 });
29659 Ext.reg('lvdatecolumn', Ext.list.DateColumn);
29660
29661
29662 Ext.list.BooleanColumn = Ext.extend(Ext.list.Column, {
29663     
29664     trueText: 'true',
29665     
29666     falseText: 'false',
29667     
29668     undefinedText: '&#160;',
29669     
29670     constructor : function(c) {
29671         c.tpl = c.tpl || new Ext.XTemplate('{' + c.dataIndex + ':this.format}');
29672         
29673         var t = this.trueText, f = this.falseText, u = this.undefinedText;
29674         c.tpl.format = function(v){
29675             if(v === undefined){
29676                 return u;
29677             }
29678             if(!v || v === 'false'){
29679                 return f;
29680             }
29681             return t;
29682         };
29683         
29684         Ext.list.DateColumn.superclass.constructor.call(this, c);
29685     }
29686 });
29687
29688 Ext.reg('lvbooleancolumn', Ext.list.BooleanColumn);
29689 Ext.list.ColumnResizer = Ext.extend(Ext.util.Observable, {
29690     
29691     minPct: .05,
29692
29693     constructor: function(config){
29694         Ext.apply(this, config);
29695         Ext.list.ColumnResizer.superclass.constructor.call(this);
29696     },
29697     init : function(listView){
29698         this.view = listView;
29699         listView.on('render', this.initEvents, this);
29700     },
29701
29702     initEvents : function(view){
29703         view.mon(view.innerHd, 'mousemove', this.handleHdMove, this);
29704         this.tracker = new Ext.dd.DragTracker({
29705             onBeforeStart: this.onBeforeStart.createDelegate(this),
29706             onStart: this.onStart.createDelegate(this),
29707             onDrag: this.onDrag.createDelegate(this),
29708             onEnd: this.onEnd.createDelegate(this),
29709             tolerance: 3,
29710             autoStart: 300
29711         });
29712         this.tracker.initEl(view.innerHd);
29713         view.on('beforedestroy', this.tracker.destroy, this.tracker);
29714     },
29715
29716     handleHdMove : function(e, t){
29717         var handleWidth = 5,
29718             x = e.getPageX(),
29719             header = e.getTarget('em', 3, true);
29720         if(header){
29721             var region = header.getRegion(),
29722                 style = header.dom.style,
29723                 parentNode = header.dom.parentNode;
29724
29725             if(x - region.left <= handleWidth && parentNode != parentNode.parentNode.firstChild){
29726                 this.activeHd = Ext.get(parentNode.previousSibling.firstChild);
29727                 style.cursor = Ext.isWebKit ? 'e-resize' : 'col-resize';
29728             } else if(region.right - x <= handleWidth && parentNode != parentNode.parentNode.lastChild.previousSibling){
29729                 this.activeHd = header;
29730                 style.cursor = Ext.isWebKit ? 'w-resize' : 'col-resize';
29731             } else{
29732                 delete this.activeHd;
29733                 style.cursor = '';
29734             }
29735         }
29736     },
29737
29738     onBeforeStart : function(e){
29739         this.dragHd = this.activeHd;
29740         return !!this.dragHd;
29741     },
29742
29743     onStart: function(e){
29744         
29745         var me = this,
29746             view = me.view,
29747             dragHeader = me.dragHd,
29748             x = me.tracker.getXY()[0];            
29749         
29750         me.proxy = view.el.createChild({cls:'x-list-resizer'});
29751         me.dragX = dragHeader.getX();
29752         me.headerIndex = view.findHeaderIndex(dragHeader);
29753         
29754         me.headersDisabled = view.disableHeaders;
29755         view.disableHeaders = true;
29756         
29757         me.proxy.setHeight(view.el.getHeight());
29758         me.proxy.setX(me.dragX);
29759         me.proxy.setWidth(x - me.dragX);
29760         
29761         this.setBoundaries();
29762         
29763     },
29764     
29765     
29766     setBoundaries: function(relativeX){
29767         var view = this.view,
29768             headerIndex = this.headerIndex,
29769             width = view.innerHd.getWidth(),
29770             relativeX = view.innerHd.getX(),
29771             minWidth = Math.ceil(width * this.minPct),
29772             maxWidth = width - minWidth,
29773             numColumns = view.columns.length,
29774             headers = view.innerHd.select('em', true),
29775             minX = minWidth + relativeX,
29776             maxX = maxWidth + relativeX,
29777             header;
29778           
29779         if (numColumns == 2) {
29780             this.minX = minX;
29781             this.maxX = maxX;
29782         }else{
29783             header = headers.item(headerIndex + 2);
29784             this.minX = headers.item(headerIndex).getX() + minWidth;
29785             this.maxX = header ? header.getX() - minWidth : maxX;
29786             if (headerIndex == 0) {
29787                 
29788                 this.minX = minX;
29789             } else if (headerIndex == numColumns - 2) {
29790                 
29791                 this.maxX = maxX;
29792             }
29793         }
29794     },
29795
29796     onDrag: function(e){
29797         var me = this,
29798             cursorX = me.tracker.getXY()[0].constrain(me.minX, me.maxX);
29799             
29800         me.proxy.setWidth(cursorX - this.dragX);
29801     },
29802
29803     onEnd: function(e){
29804         
29805         var newWidth = this.proxy.getWidth(),
29806             index = this.headerIndex,
29807             view = this.view,
29808             columns = view.columns,
29809             width = view.innerHd.getWidth(),
29810             newPercent = Math.ceil(newWidth * view.maxColumnWidth / width) / 100,
29811             disabled = this.headersDisabled,
29812             headerCol = columns[index],
29813             otherCol = columns[index + 1],
29814             totalPercent = headerCol.width + otherCol.width;
29815
29816         this.proxy.remove();
29817
29818         headerCol.width = newPercent;
29819         otherCol.width = totalPercent - newPercent;
29820       
29821         delete this.dragHd;
29822         view.setHdWidths();
29823         view.refresh();
29824         
29825         setTimeout(function(){
29826             view.disableHeaders = disabled;
29827         }, 100);
29828     }
29829 });
29830
29831
29832 Ext.ListView.ColumnResizer = Ext.list.ColumnResizer;
29833 Ext.list.Sorter = Ext.extend(Ext.util.Observable, {
29834     
29835     sortClasses : ["sort-asc", "sort-desc"],
29836
29837     constructor: function(config){
29838         Ext.apply(this, config);
29839         Ext.list.Sorter.superclass.constructor.call(this);
29840     },
29841
29842     init : function(listView){
29843         this.view = listView;
29844         listView.on('render', this.initEvents, this);
29845     },
29846
29847     initEvents : function(view){
29848         view.mon(view.innerHd, 'click', this.onHdClick, this);
29849         view.innerHd.setStyle('cursor', 'pointer');
29850         view.mon(view.store, 'datachanged', this.updateSortState, this);
29851         this.updateSortState.defer(10, this, [view.store]);
29852     },
29853
29854     updateSortState : function(store){
29855         var state = store.getSortState();
29856         if(!state){
29857             return;
29858         }
29859         this.sortState = state;
29860         var cs = this.view.columns, sortColumn = -1;
29861         for(var i = 0, len = cs.length; i < len; i++){
29862             if(cs[i].dataIndex == state.field){
29863                 sortColumn = i;
29864                 break;
29865             }
29866         }
29867         if(sortColumn != -1){
29868             var sortDir = state.direction;
29869             this.updateSortIcon(sortColumn, sortDir);
29870         }
29871     },
29872
29873     updateSortIcon : function(col, dir){
29874         var sc = this.sortClasses;
29875         var hds = this.view.innerHd.select('em').removeClass(sc);
29876         hds.item(col).addClass(sc[dir == "DESC" ? 1 : 0]);
29877     },
29878
29879     onHdClick : function(e){
29880         var hd = e.getTarget('em', 3);
29881         if(hd && !this.view.disableHeaders){
29882             var index = this.view.findHeaderIndex(hd);
29883             this.view.store.sort(this.view.columns[index].dataIndex);
29884         }
29885     }
29886 });
29887
29888
29889 Ext.ListView.Sorter = Ext.list.Sorter;
29890 Ext.TabPanel = Ext.extend(Ext.Panel,  {
29891     
29892     
29893     
29894     deferredRender : true,
29895     
29896     tabWidth : 120,
29897     
29898     minTabWidth : 30,
29899     
29900     resizeTabs : false,
29901     
29902     enableTabScroll : false,
29903     
29904     scrollIncrement : 0,
29905     
29906     scrollRepeatInterval : 400,
29907     
29908     scrollDuration : 0.35,
29909     
29910     animScroll : true,
29911     
29912     tabPosition : 'top',
29913     
29914     baseCls : 'x-tab-panel',
29915     
29916     autoTabs : false,
29917     
29918     autoTabSelector : 'div.x-tab',
29919     
29920     activeTab : undefined,
29921     
29922     tabMargin : 2,
29923     
29924     plain : false,
29925     
29926     wheelIncrement : 20,
29927
29928     
29929     idDelimiter : '__',
29930
29931     
29932     itemCls : 'x-tab-item',
29933
29934     
29935     elements : 'body',
29936     headerAsText : false,
29937     frame : false,
29938     hideBorders :true,
29939
29940     
29941     initComponent : function(){
29942         this.frame = false;
29943         Ext.TabPanel.superclass.initComponent.call(this);
29944         this.addEvents(
29945             
29946             'beforetabchange',
29947             
29948             'tabchange',
29949             
29950             'contextmenu'
29951         );
29952         
29953         this.setLayout(new Ext.layout.CardLayout(Ext.apply({
29954             layoutOnCardChange: this.layoutOnTabChange,
29955             deferredRender: this.deferredRender
29956         }, this.layoutConfig)));
29957
29958         if(this.tabPosition == 'top'){
29959             this.elements += ',header';
29960             this.stripTarget = 'header';
29961         }else {
29962             this.elements += ',footer';
29963             this.stripTarget = 'footer';
29964         }
29965         if(!this.stack){
29966             this.stack = Ext.TabPanel.AccessStack();
29967         }
29968         this.initItems();
29969     },
29970
29971     
29972     onRender : function(ct, position){
29973         Ext.TabPanel.superclass.onRender.call(this, ct, position);
29974
29975         if(this.plain){
29976             var pos = this.tabPosition == 'top' ? 'header' : 'footer';
29977             this[pos].addClass('x-tab-panel-'+pos+'-plain');
29978         }
29979
29980         var st = this[this.stripTarget];
29981
29982         this.stripWrap = st.createChild({cls:'x-tab-strip-wrap', cn:{
29983             tag:'ul', cls:'x-tab-strip x-tab-strip-'+this.tabPosition}});
29984
29985         var beforeEl = (this.tabPosition=='bottom' ? this.stripWrap : null);
29986         st.createChild({cls:'x-tab-strip-spacer'}, beforeEl);
29987         this.strip = new Ext.Element(this.stripWrap.dom.firstChild);
29988
29989         
29990         this.edge = this.strip.createChild({tag:'li', cls:'x-tab-edge', cn: [{tag: 'span', cls: 'x-tab-strip-text', cn: '&#160;'}]});
29991         this.strip.createChild({cls:'x-clear'});
29992
29993         this.body.addClass('x-tab-panel-body-'+this.tabPosition);
29994
29995         
29996         if(!this.itemTpl){
29997             var tt = new Ext.Template(
29998                  '<li class="{cls}" id="{id}"><a class="x-tab-strip-close"></a>',
29999                  '<a class="x-tab-right" href="#"><em class="x-tab-left">',
30000                  '<span class="x-tab-strip-inner"><span class="x-tab-strip-text {iconCls}">{text}</span></span>',
30001                  '</em></a></li>'
30002             );
30003             tt.disableFormats = true;
30004             tt.compile();
30005             Ext.TabPanel.prototype.itemTpl = tt;
30006         }
30007
30008         this.items.each(this.initTab, this);
30009     },
30010
30011     
30012     afterRender : function(){
30013         Ext.TabPanel.superclass.afterRender.call(this);
30014         if(this.autoTabs){
30015             this.readTabs(false);
30016         }
30017         if(this.activeTab !== undefined){
30018             var item = Ext.isObject(this.activeTab) ? this.activeTab : this.items.get(this.activeTab);
30019             delete this.activeTab;
30020             this.setActiveTab(item);
30021         }
30022     },
30023
30024     
30025     initEvents : function(){
30026         Ext.TabPanel.superclass.initEvents.call(this);
30027         this.mon(this.strip, {
30028             scope: this,
30029             mousedown: this.onStripMouseDown,
30030             contextmenu: this.onStripContextMenu
30031         });
30032         if(this.enableTabScroll){
30033             this.mon(this.strip, 'mousewheel', this.onWheel, this);
30034         }
30035     },
30036
30037     
30038     findTargets : function(e){
30039         var item = null,
30040             itemEl = e.getTarget('li:not(.x-tab-edge)', this.strip);
30041
30042         if(itemEl){
30043             item = this.getComponent(itemEl.id.split(this.idDelimiter)[1]);
30044             if(item.disabled){
30045                 return {
30046                     close : null,
30047                     item : null,
30048                     el : null
30049                 };
30050             }
30051         }
30052         return {
30053             close : e.getTarget('.x-tab-strip-close', this.strip),
30054             item : item,
30055             el : itemEl
30056         };
30057     },
30058
30059     
30060     onStripMouseDown : function(e){
30061         if(e.button !== 0){
30062             return;
30063         }
30064         e.preventDefault();
30065         var t = this.findTargets(e);
30066         if(t.close){
30067             if (t.item.fireEvent('beforeclose', t.item) !== false) {
30068                 t.item.fireEvent('close', t.item);
30069                 this.remove(t.item);
30070             }
30071             return;
30072         }
30073         if(t.item && t.item != this.activeTab){
30074             this.setActiveTab(t.item);
30075         }
30076     },
30077
30078     
30079     onStripContextMenu : function(e){
30080         e.preventDefault();
30081         var t = this.findTargets(e);
30082         if(t.item){
30083             this.fireEvent('contextmenu', this, t.item, e);
30084         }
30085     },
30086
30087     
30088     readTabs : function(removeExisting){
30089         if(removeExisting === true){
30090             this.items.each(function(item){
30091                 this.remove(item);
30092             }, this);
30093         }
30094         var tabs = this.el.query(this.autoTabSelector);
30095         for(var i = 0, len = tabs.length; i < len; i++){
30096             var tab = tabs[i],
30097                 title = tab.getAttribute('title');
30098             tab.removeAttribute('title');
30099             this.add({
30100                 title: title,
30101                 contentEl: tab
30102             });
30103         }
30104     },
30105
30106     
30107     initTab : function(item, index){
30108         var before = this.strip.dom.childNodes[index],
30109             p = this.getTemplateArgs(item),
30110             el = before ?
30111                  this.itemTpl.insertBefore(before, p) :
30112                  this.itemTpl.append(this.strip, p),
30113             cls = 'x-tab-strip-over',
30114             tabEl = Ext.get(el);
30115
30116         tabEl.hover(function(){
30117             if(!item.disabled){
30118                 tabEl.addClass(cls);
30119             }
30120         }, function(){
30121             tabEl.removeClass(cls);
30122         });
30123
30124         if(item.tabTip){
30125             tabEl.child('span.x-tab-strip-text', true).qtip = item.tabTip;
30126         }
30127         item.tabEl = el;
30128
30129         
30130         tabEl.select('a').on('click', function(e){
30131             if(!e.getPageX()){
30132                 this.onStripMouseDown(e);
30133             }
30134         }, this, {preventDefault: true});
30135
30136         item.on({
30137             scope: this,
30138             disable: this.onItemDisabled,
30139             enable: this.onItemEnabled,
30140             titlechange: this.onItemTitleChanged,
30141             iconchange: this.onItemIconChanged,
30142             beforeshow: this.onBeforeShowItem
30143         });
30144     },
30145
30146
30147
30148     
30149     getTemplateArgs : function(item) {
30150         var cls = item.closable ? 'x-tab-strip-closable' : '';
30151         if(item.disabled){
30152             cls += ' x-item-disabled';
30153         }
30154         if(item.iconCls){
30155             cls += ' x-tab-with-icon';
30156         }
30157         if(item.tabCls){
30158             cls += ' ' + item.tabCls;
30159         }
30160
30161         return {
30162             id: this.id + this.idDelimiter + item.getItemId(),
30163             text: item.title,
30164             cls: cls,
30165             iconCls: item.iconCls || ''
30166         };
30167     },
30168
30169     
30170     onAdd : function(c){
30171         Ext.TabPanel.superclass.onAdd.call(this, c);
30172         if(this.rendered){
30173             var items = this.items;
30174             this.initTab(c, items.indexOf(c));
30175             this.delegateUpdates();
30176         }
30177     },
30178
30179     
30180     onBeforeAdd : function(item){
30181         var existing = item.events ? (this.items.containsKey(item.getItemId()) ? item : null) : this.items.get(item);
30182         if(existing){
30183             this.setActiveTab(item);
30184             return false;
30185         }
30186         Ext.TabPanel.superclass.onBeforeAdd.apply(this, arguments);
30187         var es = item.elements;
30188         item.elements = es ? es.replace(',header', '') : es;
30189         item.border = (item.border === true);
30190     },
30191
30192     
30193     onRemove : function(c){
30194         var te = Ext.get(c.tabEl);
30195         
30196         if(te){
30197             te.select('a').removeAllListeners();
30198             Ext.destroy(te);
30199         }
30200         Ext.TabPanel.superclass.onRemove.call(this, c);
30201         this.stack.remove(c);
30202         delete c.tabEl;
30203         c.un('disable', this.onItemDisabled, this);
30204         c.un('enable', this.onItemEnabled, this);
30205         c.un('titlechange', this.onItemTitleChanged, this);
30206         c.un('iconchange', this.onItemIconChanged, this);
30207         c.un('beforeshow', this.onBeforeShowItem, this);
30208         if(c == this.activeTab){
30209             var next = this.stack.next();
30210             if(next){
30211                 this.setActiveTab(next);
30212             }else if(this.items.getCount() > 0){
30213                 this.setActiveTab(0);
30214             }else{
30215                 this.setActiveTab(null);
30216             }
30217         }
30218         if(!this.destroying){
30219             this.delegateUpdates();
30220         }
30221     },
30222
30223     
30224     onBeforeShowItem : function(item){
30225         if(item != this.activeTab){
30226             this.setActiveTab(item);
30227             return false;
30228         }
30229     },
30230
30231     
30232     onItemDisabled : function(item){
30233         var el = this.getTabEl(item);
30234         if(el){
30235             Ext.fly(el).addClass('x-item-disabled');
30236         }
30237         this.stack.remove(item);
30238     },
30239
30240     
30241     onItemEnabled : function(item){
30242         var el = this.getTabEl(item);
30243         if(el){
30244             Ext.fly(el).removeClass('x-item-disabled');
30245         }
30246     },
30247
30248     
30249     onItemTitleChanged : function(item){
30250         var el = this.getTabEl(item);
30251         if(el){
30252             Ext.fly(el).child('span.x-tab-strip-text', true).innerHTML = item.title;
30253         }
30254     },
30255
30256     
30257     onItemIconChanged : function(item, iconCls, oldCls){
30258         var el = this.getTabEl(item);
30259         if(el){
30260             el = Ext.get(el);
30261             el.child('span.x-tab-strip-text').replaceClass(oldCls, iconCls);
30262             el[Ext.isEmpty(iconCls) ? 'removeClass' : 'addClass']('x-tab-with-icon');
30263         }
30264     },
30265
30266     
30267     getTabEl : function(item){
30268         var c = this.getComponent(item);
30269         return c ? c.tabEl : null;
30270     },
30271
30272     
30273     onResize : function(){
30274         Ext.TabPanel.superclass.onResize.apply(this, arguments);
30275         this.delegateUpdates();
30276     },
30277
30278     
30279     beginUpdate : function(){
30280         this.suspendUpdates = true;
30281     },
30282
30283     
30284     endUpdate : function(){
30285         this.suspendUpdates = false;
30286         this.delegateUpdates();
30287     },
30288
30289     
30290     hideTabStripItem : function(item){
30291         item = this.getComponent(item);
30292         var el = this.getTabEl(item);
30293         if(el){
30294             el.style.display = 'none';
30295             this.delegateUpdates();
30296         }
30297         this.stack.remove(item);
30298     },
30299
30300     
30301     unhideTabStripItem : function(item){
30302         item = this.getComponent(item);
30303         var el = this.getTabEl(item);
30304         if(el){
30305             el.style.display = '';
30306             this.delegateUpdates();
30307         }
30308     },
30309
30310     
30311     delegateUpdates : function(){
30312         var rendered = this.rendered;
30313         if(this.suspendUpdates){
30314             return;
30315         }
30316         if(this.resizeTabs && rendered){
30317             this.autoSizeTabs();
30318         }
30319         if(this.enableTabScroll && rendered){
30320             this.autoScrollTabs();
30321         }
30322     },
30323
30324     
30325     autoSizeTabs : function(){
30326         var count = this.items.length,
30327             ce = this.tabPosition != 'bottom' ? 'header' : 'footer',
30328             ow = this[ce].dom.offsetWidth,
30329             aw = this[ce].dom.clientWidth;
30330
30331         if(!this.resizeTabs || count < 1 || !aw){ 
30332             return;
30333         }
30334
30335         var each = Math.max(Math.min(Math.floor((aw-4) / count) - this.tabMargin, this.tabWidth), this.minTabWidth); 
30336         this.lastTabWidth = each;
30337         var lis = this.strip.query('li:not(.x-tab-edge)');
30338         for(var i = 0, len = lis.length; i < len; i++) {
30339             var li = lis[i],
30340                 inner = Ext.fly(li).child('.x-tab-strip-inner', true),
30341                 tw = li.offsetWidth,
30342                 iw = inner.offsetWidth;
30343             inner.style.width = (each - (tw-iw)) + 'px';
30344         }
30345     },
30346
30347     
30348     adjustBodyWidth : function(w){
30349         if(this.header){
30350             this.header.setWidth(w);
30351         }
30352         if(this.footer){
30353             this.footer.setWidth(w);
30354         }
30355         return w;
30356     },
30357
30358     
30359     setActiveTab : function(item){
30360         item = this.getComponent(item);
30361         if(this.fireEvent('beforetabchange', this, item, this.activeTab) === false){
30362             return;
30363         }
30364         if(!this.rendered){
30365             this.activeTab = item;
30366             return;
30367         }
30368         if(this.activeTab != item){
30369             if(this.activeTab){
30370                 var oldEl = this.getTabEl(this.activeTab);
30371                 if(oldEl){
30372                     Ext.fly(oldEl).removeClass('x-tab-strip-active');
30373                 }
30374             }
30375             this.activeTab = item;
30376             if(item){
30377                 var el = this.getTabEl(item);
30378                 Ext.fly(el).addClass('x-tab-strip-active');
30379                 this.stack.add(item);
30380
30381                 this.layout.setActiveItem(item);
30382                 
30383                 this.delegateUpdates();
30384                 if(this.scrolling){
30385                     this.scrollToTab(item, this.animScroll);
30386                 }
30387             }
30388             this.fireEvent('tabchange', this, item);
30389         }
30390     },
30391
30392     
30393     getActiveTab : function(){
30394         return this.activeTab || null;
30395     },
30396
30397     
30398     getItem : function(item){
30399         return this.getComponent(item);
30400     },
30401
30402     
30403     autoScrollTabs : function(){
30404         this.pos = this.tabPosition=='bottom' ? this.footer : this.header;
30405         var count = this.items.length,
30406             ow = this.pos.dom.offsetWidth,
30407             tw = this.pos.dom.clientWidth,
30408             wrap = this.stripWrap,
30409             wd = wrap.dom,
30410             cw = wd.offsetWidth,
30411             pos = this.getScrollPos(),
30412             l = this.edge.getOffsetsTo(this.stripWrap)[0] + pos;
30413
30414         if(!this.enableTabScroll || cw < 20){ 
30415             return;
30416         }
30417         if(count == 0 || l <= tw){
30418             
30419             wd.scrollLeft = 0;
30420             wrap.setWidth(tw);
30421             if(this.scrolling){
30422                 this.scrolling = false;
30423                 this.pos.removeClass('x-tab-scrolling');
30424                 this.scrollLeft.hide();
30425                 this.scrollRight.hide();
30426                 
30427                 if(Ext.isAir || Ext.isWebKit){
30428                     wd.style.marginLeft = '';
30429                     wd.style.marginRight = '';
30430                 }
30431             }
30432         }else{
30433             if(!this.scrolling){
30434                 this.pos.addClass('x-tab-scrolling');
30435                 
30436                 if(Ext.isAir || Ext.isWebKit){
30437                     wd.style.marginLeft = '18px';
30438                     wd.style.marginRight = '18px';
30439                 }
30440             }
30441             tw -= wrap.getMargins('lr');
30442             wrap.setWidth(tw > 20 ? tw : 20);
30443             if(!this.scrolling){
30444                 if(!this.scrollLeft){
30445                     this.createScrollers();
30446                 }else{
30447                     this.scrollLeft.show();
30448                     this.scrollRight.show();
30449                 }
30450             }
30451             this.scrolling = true;
30452             if(pos > (l-tw)){ 
30453                 wd.scrollLeft = l-tw;
30454             }else{ 
30455                 this.scrollToTab(this.activeTab, false);
30456             }
30457             this.updateScrollButtons();
30458         }
30459     },
30460
30461     
30462     createScrollers : function(){
30463         this.pos.addClass('x-tab-scrolling-' + this.tabPosition);
30464         var h = this.stripWrap.dom.offsetHeight;
30465
30466         
30467         var sl = this.pos.insertFirst({
30468             cls:'x-tab-scroller-left'
30469         });
30470         sl.setHeight(h);
30471         sl.addClassOnOver('x-tab-scroller-left-over');
30472         this.leftRepeater = new Ext.util.ClickRepeater(sl, {
30473             interval : this.scrollRepeatInterval,
30474             handler: this.onScrollLeft,
30475             scope: this
30476         });
30477         this.scrollLeft = sl;
30478
30479         
30480         var sr = this.pos.insertFirst({
30481             cls:'x-tab-scroller-right'
30482         });
30483         sr.setHeight(h);
30484         sr.addClassOnOver('x-tab-scroller-right-over');
30485         this.rightRepeater = new Ext.util.ClickRepeater(sr, {
30486             interval : this.scrollRepeatInterval,
30487             handler: this.onScrollRight,
30488             scope: this
30489         });
30490         this.scrollRight = sr;
30491     },
30492
30493     
30494     getScrollWidth : function(){
30495         return this.edge.getOffsetsTo(this.stripWrap)[0] + this.getScrollPos();
30496     },
30497
30498     
30499     getScrollPos : function(){
30500         return parseInt(this.stripWrap.dom.scrollLeft, 10) || 0;
30501     },
30502
30503     
30504     getScrollArea : function(){
30505         return parseInt(this.stripWrap.dom.clientWidth, 10) || 0;
30506     },
30507
30508     
30509     getScrollAnim : function(){
30510         return {duration:this.scrollDuration, callback: this.updateScrollButtons, scope: this};
30511     },
30512
30513     
30514     getScrollIncrement : function(){
30515         return this.scrollIncrement || (this.resizeTabs ? this.lastTabWidth+2 : 100);
30516     },
30517
30518     
30519
30520     scrollToTab : function(item, animate){
30521         if(!item){
30522             return;
30523         }
30524         var el = this.getTabEl(item),
30525             pos = this.getScrollPos(),
30526             area = this.getScrollArea(),
30527             left = Ext.fly(el).getOffsetsTo(this.stripWrap)[0] + pos,
30528             right = left + el.offsetWidth;
30529         if(left < pos){
30530             this.scrollTo(left, animate);
30531         }else if(right > (pos + area)){
30532             this.scrollTo(right - area, animate);
30533         }
30534     },
30535
30536     
30537     scrollTo : function(pos, animate){
30538         this.stripWrap.scrollTo('left', pos, animate ? this.getScrollAnim() : false);
30539         if(!animate){
30540             this.updateScrollButtons();
30541         }
30542     },
30543
30544     onWheel : function(e){
30545         var d = e.getWheelDelta()*this.wheelIncrement*-1;
30546         e.stopEvent();
30547
30548         var pos = this.getScrollPos(),
30549             newpos = pos + d,
30550             sw = this.getScrollWidth()-this.getScrollArea();
30551
30552         var s = Math.max(0, Math.min(sw, newpos));
30553         if(s != pos){
30554             this.scrollTo(s, false);
30555         }
30556     },
30557
30558     
30559     onScrollRight : function(){
30560         var sw = this.getScrollWidth()-this.getScrollArea(),
30561             pos = this.getScrollPos(),
30562             s = Math.min(sw, pos + this.getScrollIncrement());
30563         if(s != pos){
30564             this.scrollTo(s, this.animScroll);
30565         }
30566     },
30567
30568     
30569     onScrollLeft : function(){
30570         var pos = this.getScrollPos(),
30571             s = Math.max(0, pos - this.getScrollIncrement());
30572         if(s != pos){
30573             this.scrollTo(s, this.animScroll);
30574         }
30575     },
30576
30577     
30578     updateScrollButtons : function(){
30579         var pos = this.getScrollPos();
30580         this.scrollLeft[pos === 0 ? 'addClass' : 'removeClass']('x-tab-scroller-left-disabled');
30581         this.scrollRight[pos >= (this.getScrollWidth()-this.getScrollArea()) ? 'addClass' : 'removeClass']('x-tab-scroller-right-disabled');
30582     },
30583
30584     
30585     beforeDestroy : function() {
30586         Ext.destroy(this.leftRepeater, this.rightRepeater);
30587         this.deleteMembers('strip', 'edge', 'scrollLeft', 'scrollRight', 'stripWrap');
30588         this.activeTab = null;
30589         Ext.TabPanel.superclass.beforeDestroy.apply(this);
30590     }
30591
30592     
30593     
30594     
30595     
30596     
30597     
30598     
30599     
30600     
30601     
30602     
30603     
30604 });
30605 Ext.reg('tabpanel', Ext.TabPanel);
30606
30607
30608 Ext.TabPanel.prototype.activate = Ext.TabPanel.prototype.setActiveTab;
30609
30610
30611 Ext.TabPanel.AccessStack = function(){
30612     var items = [];
30613     return {
30614         add : function(item){
30615             items.push(item);
30616             if(items.length > 10){
30617                 items.shift();
30618             }
30619         },
30620
30621         remove : function(item){
30622             var s = [];
30623             for(var i = 0, len = items.length; i < len; i++) {
30624                 if(items[i] != item){
30625                     s.push(items[i]);
30626                 }
30627             }
30628             items = s;
30629         },
30630
30631         next : function(){
30632             return items.pop();
30633         }
30634     };
30635 };
30636
30637 Ext.Button = Ext.extend(Ext.BoxComponent, {
30638     
30639     hidden : false,
30640     
30641     disabled : false,
30642     
30643     pressed : false,
30644
30645     
30646
30647     
30648
30649     
30650     enableToggle : false,
30651     
30652     
30653     
30654     menuAlign : 'tl-bl?',
30655
30656     
30657     
30658     
30659     type : 'button',
30660
30661     
30662     menuClassTarget : 'tr:nth(2)',
30663
30664     
30665     clickEvent : 'click',
30666
30667     
30668     handleMouseEvents : true,
30669
30670     
30671     tooltipType : 'qtip',
30672
30673     
30674     buttonSelector : 'button:first-child',
30675
30676     
30677     scale : 'small',
30678
30679     
30680
30681     
30682     iconAlign : 'left',
30683
30684     
30685     arrowAlign : 'right',
30686
30687     
30688     
30689     
30690     
30691
30692     initComponent : function(){
30693         Ext.Button.superclass.initComponent.call(this);
30694
30695         this.addEvents(
30696             
30697             'click',
30698             
30699             'toggle',
30700             
30701             'mouseover',
30702             
30703             'mouseout',
30704             
30705             'menushow',
30706             
30707             'menuhide',
30708             
30709             'menutriggerover',
30710             
30711             'menutriggerout'
30712         );
30713         if(this.menu){
30714             this.menu = Ext.menu.MenuMgr.get(this.menu);
30715         }
30716         if(Ext.isString(this.toggleGroup)){
30717             this.enableToggle = true;
30718         }
30719     },
30720
30721
30722     getTemplateArgs : function(){
30723         return [this.type, 'x-btn-' + this.scale + ' x-btn-icon-' + this.scale + '-' + this.iconAlign, this.getMenuClass(), this.cls, this.id];
30724     },
30725
30726     
30727     setButtonClass : function(){
30728         if(this.useSetClass){
30729             if(!Ext.isEmpty(this.oldCls)){
30730                 this.el.removeClass([this.oldCls, 'x-btn-pressed']);
30731             }
30732             this.oldCls = (this.iconCls || this.icon) ? (this.text ? 'x-btn-text-icon' : 'x-btn-icon') : 'x-btn-noicon';
30733             this.el.addClass([this.oldCls, this.pressed ? 'x-btn-pressed' : null]);
30734         }
30735     },
30736
30737     
30738     getMenuClass : function(){
30739         return this.menu ? (this.arrowAlign != 'bottom' ? 'x-btn-arrow' : 'x-btn-arrow-bottom') : '';
30740     },
30741
30742     
30743     onRender : function(ct, position){
30744         if(!this.template){
30745             if(!Ext.Button.buttonTemplate){
30746                 
30747                 Ext.Button.buttonTemplate = new Ext.Template(
30748                     '<table id="{4}" cellspacing="0" class="x-btn {3}"><tbody class="{1}">',
30749                     '<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>',
30750                     '<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>',
30751                     '<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>',
30752                     '</tbody></table>');
30753                 Ext.Button.buttonTemplate.compile();
30754             }
30755             this.template = Ext.Button.buttonTemplate;
30756         }
30757
30758         var btn, targs = this.getTemplateArgs();
30759
30760         if(position){
30761             btn = this.template.insertBefore(position, targs, true);
30762         }else{
30763             btn = this.template.append(ct, targs, true);
30764         }
30765         
30766         this.btnEl = btn.child(this.buttonSelector);
30767         this.mon(this.btnEl, {
30768             scope: this,
30769             focus: this.onFocus,
30770             blur: this.onBlur
30771         });
30772
30773         this.initButtonEl(btn, this.btnEl);
30774
30775         Ext.ButtonToggleMgr.register(this);
30776     },
30777
30778     
30779     initButtonEl : function(btn, btnEl){
30780         this.el = btn;
30781         this.setIcon(this.icon);
30782         this.setText(this.text);
30783         this.setIconClass(this.iconCls);
30784         if(Ext.isDefined(this.tabIndex)){
30785             btnEl.dom.tabIndex = this.tabIndex;
30786         }
30787         if(this.tooltip){
30788             this.setTooltip(this.tooltip, true);
30789         }
30790
30791         if(this.handleMouseEvents){
30792             this.mon(btn, {
30793                 scope: this,
30794                 mouseover: this.onMouseOver,
30795                 mousedown: this.onMouseDown
30796             });
30797
30798             
30799             
30800         }
30801
30802         if(this.menu){
30803             this.mon(this.menu, {
30804                 scope: this,
30805                 show: this.onMenuShow,
30806                 hide: this.onMenuHide
30807             });
30808         }
30809
30810         if(this.repeat){
30811             var repeater = new Ext.util.ClickRepeater(btn, Ext.isObject(this.repeat) ? this.repeat : {});
30812             this.mon(repeater, 'click', this.onRepeatClick, this);
30813         }else{
30814             this.mon(btn, this.clickEvent, this.onClick, this);
30815         }
30816     },
30817
30818     
30819     afterRender : function(){
30820         Ext.Button.superclass.afterRender.call(this);
30821         this.useSetClass = true;
30822         this.setButtonClass();
30823         this.doc = Ext.getDoc();
30824         this.doAutoWidth();
30825     },
30826
30827     
30828     setIconClass : function(cls){
30829         this.iconCls = cls;
30830         if(this.el){
30831             this.btnEl.dom.className = '';
30832             this.btnEl.addClass(['x-btn-text', cls || '']);
30833             this.setButtonClass();
30834         }
30835         return this;
30836     },
30837
30838     
30839     setTooltip : function(tooltip,  initial){
30840         if(this.rendered){
30841             if(!initial){
30842                 this.clearTip();
30843             }
30844             if(Ext.isObject(tooltip)){
30845                 Ext.QuickTips.register(Ext.apply({
30846                       target: this.btnEl.id
30847                 }, tooltip));
30848                 this.tooltip = tooltip;
30849             }else{
30850                 this.btnEl.dom[this.tooltipType] = tooltip;
30851             }
30852         }else{
30853             this.tooltip = tooltip;
30854         }
30855         return this;
30856     },
30857
30858     
30859     clearTip : function(){
30860         if(Ext.isObject(this.tooltip)){
30861             Ext.QuickTips.unregister(this.btnEl);
30862         }
30863     },
30864
30865     
30866     beforeDestroy : function(){
30867         if(this.rendered){
30868             this.clearTip();
30869         }
30870         if(this.menu && this.destroyMenu !== false) {
30871             Ext.destroy(this.btnEl, this.menu);
30872         }
30873         Ext.destroy(this.repeater);
30874     },
30875
30876     
30877     onDestroy : function(){
30878         if(this.rendered){
30879             this.doc.un('mouseover', this.monitorMouseOver, this);
30880             this.doc.un('mouseup', this.onMouseUp, this);
30881             delete this.doc;
30882             delete this.btnEl;
30883             Ext.ButtonToggleMgr.unregister(this);
30884         }
30885         Ext.Button.superclass.onDestroy.call(this);
30886     },
30887
30888     
30889     doAutoWidth : function(){
30890         if(this.autoWidth !== false && this.el && this.text && this.width === undefined){
30891             this.el.setWidth('auto');
30892             if(Ext.isIE7 && Ext.isStrict){
30893                 var ib = this.btnEl;
30894                 if(ib && ib.getWidth() > 20){
30895                     ib.clip();
30896                     ib.setWidth(Ext.util.TextMetrics.measure(ib, this.text).width+ib.getFrameWidth('lr'));
30897                 }
30898             }
30899             if(this.minWidth){
30900                 if(this.el.getWidth() < this.minWidth){
30901                     this.el.setWidth(this.minWidth);
30902                 }
30903             }
30904         }
30905     },
30906
30907     
30908     setHandler : function(handler, scope){
30909         this.handler = handler;
30910         this.scope = scope;
30911         return this;
30912     },
30913
30914     
30915     setText : function(text){
30916         this.text = text;
30917         if(this.el){
30918             this.btnEl.update(text || '&#160;');
30919             this.setButtonClass();
30920         }
30921         this.doAutoWidth();
30922         return this;
30923     },
30924
30925     
30926     setIcon : function(icon){
30927         this.icon = icon;
30928         if(this.el){
30929             this.btnEl.setStyle('background-image', icon ? 'url(' + icon + ')' : '');
30930             this.setButtonClass();
30931         }
30932         return this;
30933     },
30934
30935     
30936     getText : function(){
30937         return this.text;
30938     },
30939
30940     
30941     toggle : function(state, suppressEvent){
30942         state = state === undefined ? !this.pressed : !!state;
30943         if(state != this.pressed){
30944             if(this.rendered){
30945                 this.el[state ? 'addClass' : 'removeClass']('x-btn-pressed');
30946             }
30947             this.pressed = state;
30948             if(!suppressEvent){
30949                 this.fireEvent('toggle', this, state);
30950                 if(this.toggleHandler){
30951                     this.toggleHandler.call(this.scope || this, this, state);
30952                 }
30953             }
30954         }
30955         return this;
30956     },
30957
30958     
30959     onDisable : function(){
30960         this.onDisableChange(true);
30961     },
30962
30963     
30964     onEnable : function(){
30965         this.onDisableChange(false);
30966     },
30967
30968     onDisableChange : function(disabled){
30969         if(this.el){
30970             if(!Ext.isIE6 || !this.text){
30971                 this.el[disabled ? 'addClass' : 'removeClass'](this.disabledClass);
30972             }
30973             this.el.dom.disabled = disabled;
30974         }
30975         this.disabled = disabled;
30976     },
30977
30978     
30979     showMenu : function(){
30980         if(this.rendered && this.menu){
30981             if(this.tooltip){
30982                 Ext.QuickTips.getQuickTip().cancelShow(this.btnEl);
30983             }
30984             if(this.menu.isVisible()){
30985                 this.menu.hide();
30986             }
30987             this.menu.ownerCt = this;
30988             this.menu.show(this.el, this.menuAlign);
30989         }
30990         return this;
30991     },
30992
30993     
30994     hideMenu : function(){
30995         if(this.hasVisibleMenu()){
30996             this.menu.hide();
30997         }
30998         return this;
30999     },
31000
31001     
31002     hasVisibleMenu : function(){
31003         return this.menu && this.menu.ownerCt == this && this.menu.isVisible();
31004     },
31005     
31006     
31007     onRepeatClick : function(repeat, e){
31008         this.onClick(e);
31009     },
31010
31011     
31012     onClick : function(e){
31013         if(e){
31014             e.preventDefault();
31015         }
31016         if(e.button !== 0){
31017             return;
31018         }
31019         if(!this.disabled){
31020             this.doToggle();
31021             if(this.menu && !this.hasVisibleMenu() && !this.ignoreNextClick){
31022                 this.showMenu();
31023             }
31024             this.fireEvent('click', this, e);
31025             if(this.handler){
31026                 
31027                 this.handler.call(this.scope || this, this, e);
31028             }
31029         }
31030     },
31031     
31032     
31033     doToggle: function(){
31034         if (this.enableToggle && (this.allowDepress !== false || !this.pressed)) {
31035             this.toggle();
31036         }
31037     },
31038
31039     
31040     isMenuTriggerOver : function(e, internal){
31041         return this.menu && !internal;
31042     },
31043
31044     
31045     isMenuTriggerOut : function(e, internal){
31046         return this.menu && !internal;
31047     },
31048
31049     
31050     onMouseOver : function(e){
31051         if(!this.disabled){
31052             var internal = e.within(this.el,  true);
31053             if(!internal){
31054                 this.el.addClass('x-btn-over');
31055                 if(!this.monitoringMouseOver){
31056                     this.doc.on('mouseover', this.monitorMouseOver, this);
31057                     this.monitoringMouseOver = true;
31058                 }
31059                 this.fireEvent('mouseover', this, e);
31060             }
31061             if(this.isMenuTriggerOver(e, internal)){
31062                 this.fireEvent('menutriggerover', this, this.menu, e);
31063             }
31064         }
31065     },
31066
31067     
31068     monitorMouseOver : function(e){
31069         if(e.target != this.el.dom && !e.within(this.el)){
31070             if(this.monitoringMouseOver){
31071                 this.doc.un('mouseover', this.monitorMouseOver, this);
31072                 this.monitoringMouseOver = false;
31073             }
31074             this.onMouseOut(e);
31075         }
31076     },
31077
31078     
31079     onMouseOut : function(e){
31080         var internal = e.within(this.el) && e.target != this.el.dom;
31081         this.el.removeClass('x-btn-over');
31082         this.fireEvent('mouseout', this, e);
31083         if(this.isMenuTriggerOut(e, internal)){
31084             this.fireEvent('menutriggerout', this, this.menu, e);
31085         }
31086     },
31087
31088     focus : function() {
31089         this.btnEl.focus();
31090     },
31091
31092     blur : function() {
31093         this.btnEl.blur();
31094     },
31095
31096     
31097     onFocus : function(e){
31098         if(!this.disabled){
31099             this.el.addClass('x-btn-focus');
31100         }
31101     },
31102     
31103     onBlur : function(e){
31104         this.el.removeClass('x-btn-focus');
31105     },
31106
31107     
31108     getClickEl : function(e, isUp){
31109        return this.el;
31110     },
31111
31112     
31113     onMouseDown : function(e){
31114         if(!this.disabled && e.button === 0){
31115             this.getClickEl(e).addClass('x-btn-click');
31116             this.doc.on('mouseup', this.onMouseUp, this);
31117         }
31118     },
31119     
31120     onMouseUp : function(e){
31121         if(e.button === 0){
31122             this.getClickEl(e, true).removeClass('x-btn-click');
31123             this.doc.un('mouseup', this.onMouseUp, this);
31124         }
31125     },
31126     
31127     onMenuShow : function(e){
31128         if(this.menu.ownerCt == this){
31129             this.menu.ownerCt = this;
31130             this.ignoreNextClick = 0;
31131             this.el.addClass('x-btn-menu-active');
31132             this.fireEvent('menushow', this, this.menu);
31133         }
31134     },
31135     
31136     onMenuHide : function(e){
31137         if(this.menu.ownerCt == this){
31138             this.el.removeClass('x-btn-menu-active');
31139             this.ignoreNextClick = this.restoreClick.defer(250, this);
31140             this.fireEvent('menuhide', this, this.menu);
31141             delete this.menu.ownerCt;
31142         }
31143     },
31144
31145     
31146     restoreClick : function(){
31147         this.ignoreNextClick = 0;
31148     }
31149
31150     
31151     
31152     
31153     
31154     
31155     
31156 });
31157 Ext.reg('button', Ext.Button);
31158
31159
31160 Ext.ButtonToggleMgr = function(){
31161    var groups = {};
31162
31163    function toggleGroup(btn, state){
31164        if(state){
31165            var g = groups[btn.toggleGroup];
31166            for(var i = 0, l = g.length; i < l; i++){
31167                if(g[i] != btn){
31168                    g[i].toggle(false);
31169                }
31170            }
31171        }
31172    }
31173
31174    return {
31175        register : function(btn){
31176            if(!btn.toggleGroup){
31177                return;
31178            }
31179            var g = groups[btn.toggleGroup];
31180            if(!g){
31181                g = groups[btn.toggleGroup] = [];
31182            }
31183            g.push(btn);
31184            btn.on('toggle', toggleGroup);
31185        },
31186
31187        unregister : function(btn){
31188            if(!btn.toggleGroup){
31189                return;
31190            }
31191            var g = groups[btn.toggleGroup];
31192            if(g){
31193                g.remove(btn);
31194                btn.un('toggle', toggleGroup);
31195            }
31196        },
31197
31198        
31199        getPressed : function(group){
31200            var g = groups[group];
31201            if(g){
31202                for(var i = 0, len = g.length; i < len; i++){
31203                    if(g[i].pressed === true){
31204                        return g[i];
31205                    }
31206                }
31207            }
31208            return null;
31209        }
31210    };
31211 }();
31212
31213 Ext.SplitButton = Ext.extend(Ext.Button, {
31214         
31215     arrowSelector : 'em',
31216     split: true,
31217
31218     
31219     initComponent : function(){
31220         Ext.SplitButton.superclass.initComponent.call(this);
31221         
31222         this.addEvents("arrowclick");
31223     },
31224
31225     
31226     onRender : function(){
31227         Ext.SplitButton.superclass.onRender.apply(this, arguments);
31228         if(this.arrowTooltip){
31229             this.el.child(this.arrowSelector).dom[this.tooltipType] = this.arrowTooltip;
31230         }
31231     },
31232
31233     
31234     setArrowHandler : function(handler, scope){
31235         this.arrowHandler = handler;
31236         this.scope = scope;
31237     },
31238
31239     getMenuClass : function(){
31240         return 'x-btn-split' + (this.arrowAlign == 'bottom' ? '-bottom' : '');
31241     },
31242
31243     isClickOnArrow : function(e){
31244         if (this.arrowAlign != 'bottom') {
31245             var visBtn = this.el.child('em.x-btn-split');
31246             var right = visBtn.getRegion().right - visBtn.getPadding('r');
31247             return e.getPageX() > right;
31248         } else {
31249             return e.getPageY() > this.btnEl.getRegion().bottom;
31250         }
31251     },
31252
31253     
31254     onClick : function(e, t){
31255         e.preventDefault();
31256         if(!this.disabled){
31257             if(this.isClickOnArrow(e)){
31258                 if(this.menu && !this.menu.isVisible() && !this.ignoreNextClick){
31259                     this.showMenu();
31260                 }
31261                 this.fireEvent("arrowclick", this, e);
31262                 if(this.arrowHandler){
31263                     this.arrowHandler.call(this.scope || this, this, e);
31264                 }
31265             }else{
31266                 this.doToggle();
31267                 this.fireEvent("click", this, e);
31268                 if(this.handler){
31269                     this.handler.call(this.scope || this, this, e);
31270                 }
31271             }
31272         }
31273     },
31274
31275     
31276     isMenuTriggerOver : function(e){
31277         return this.menu && e.target.tagName == this.arrowSelector;
31278     },
31279
31280     
31281     isMenuTriggerOut : function(e, internal){
31282         return this.menu && e.target.tagName != this.arrowSelector;
31283     }
31284 });
31285
31286 Ext.reg('splitbutton', Ext.SplitButton);
31287 Ext.CycleButton = Ext.extend(Ext.SplitButton, {
31288     
31289     
31290     
31291     
31292     
31293     
31294
31295     
31296     getItemText : function(item){
31297         if(item && this.showText === true){
31298             var text = '';
31299             if(this.prependText){
31300                 text += this.prependText;
31301             }
31302             text += item.text;
31303             return text;
31304         }
31305         return undefined;
31306     },
31307
31308     
31309     setActiveItem : function(item, suppressEvent){
31310         if(!Ext.isObject(item)){
31311             item = this.menu.getComponent(item);
31312         }
31313         if(item){
31314             if(!this.rendered){
31315                 this.text = this.getItemText(item);
31316                 this.iconCls = item.iconCls;
31317             }else{
31318                 var t = this.getItemText(item);
31319                 if(t){
31320                     this.setText(t);
31321                 }
31322                 this.setIconClass(item.iconCls);
31323             }
31324             this.activeItem = item;
31325             if(!item.checked){
31326                 item.setChecked(true, false);
31327             }
31328             if(this.forceIcon){
31329                 this.setIconClass(this.forceIcon);
31330             }
31331             if(!suppressEvent){
31332                 this.fireEvent('change', this, item);
31333             }
31334         }
31335     },
31336
31337     
31338     getActiveItem : function(){
31339         return this.activeItem;
31340     },
31341
31342     
31343     initComponent : function(){
31344         this.addEvents(
31345             
31346             "change"
31347         );
31348
31349         if(this.changeHandler){
31350             this.on('change', this.changeHandler, this.scope||this);
31351             delete this.changeHandler;
31352         }
31353
31354         this.itemCount = this.items.length;
31355
31356         this.menu = {cls:'x-cycle-menu', items:[]};
31357         var checked = 0;
31358         Ext.each(this.items, function(item, i){
31359             Ext.apply(item, {
31360                 group: item.group || this.id,
31361                 itemIndex: i,
31362                 checkHandler: this.checkHandler,
31363                 scope: this,
31364                 checked: item.checked || false
31365             });
31366             this.menu.items.push(item);
31367             if(item.checked){
31368                 checked = i;
31369             }
31370         }, this);
31371         Ext.CycleButton.superclass.initComponent.call(this);
31372         this.on('click', this.toggleSelected, this);
31373         this.setActiveItem(checked, true);
31374     },
31375
31376     
31377     checkHandler : function(item, pressed){
31378         if(pressed){
31379             this.setActiveItem(item);
31380         }
31381     },
31382
31383     
31384     toggleSelected : function(){
31385         var m = this.menu;
31386         m.render();
31387         
31388         if(!m.hasLayout){
31389             m.doLayout();
31390         }
31391         
31392         var nextIdx, checkItem;
31393         for (var i = 1; i < this.itemCount; i++) {
31394             nextIdx = (this.activeItem.itemIndex + i) % this.itemCount;
31395             
31396             checkItem = m.items.itemAt(nextIdx);
31397             
31398             if (!checkItem.disabled) {
31399                 checkItem.setChecked(true);
31400                 break;
31401             }
31402         }
31403     }
31404 });
31405 Ext.reg('cycle', Ext.CycleButton);
31406 Ext.Toolbar = function(config){
31407     if(Ext.isArray(config)){
31408         config = {items: config, layout: 'toolbar'};
31409     } else {
31410         config = Ext.apply({
31411             layout: 'toolbar'
31412         }, config);
31413         if(config.buttons) {
31414             config.items = config.buttons;
31415         }
31416     }
31417     Ext.Toolbar.superclass.constructor.call(this, config);
31418 };
31419
31420 (function(){
31421
31422 var T = Ext.Toolbar;
31423
31424 Ext.extend(T, Ext.Container, {
31425
31426     defaultType: 'button',
31427
31428     
31429
31430     enableOverflow : false,
31431
31432     
31433     
31434
31435     trackMenus : true,
31436     internalDefaults: {removeMode: 'container', hideParent: true},
31437     toolbarCls: 'x-toolbar',
31438
31439     initComponent : function(){
31440         T.superclass.initComponent.call(this);
31441
31442         
31443         this.addEvents('overflowchange');
31444     },
31445
31446     
31447     onRender : function(ct, position){
31448         if(!this.el){
31449             if(!this.autoCreate){
31450                 this.autoCreate = {
31451                     cls: this.toolbarCls + ' x-small-editor'
31452                 };
31453             }
31454             this.el = ct.createChild(Ext.apply({ id: this.id },this.autoCreate), position);
31455             Ext.Toolbar.superclass.onRender.apply(this, arguments);
31456         }
31457     },
31458
31459     
31460
31461     
31462     lookupComponent : function(c){
31463         if(Ext.isString(c)){
31464             if(c == '-'){
31465                 c = new T.Separator();
31466             }else if(c == ' '){
31467                 c = new T.Spacer();
31468             }else if(c == '->'){
31469                 c = new T.Fill();
31470             }else{
31471                 c = new T.TextItem(c);
31472             }
31473             this.applyDefaults(c);
31474         }else{
31475             if(c.isFormField || c.render){ 
31476                 c = this.createComponent(c);
31477             }else if(c.tag){ 
31478                 c = new T.Item({autoEl: c});
31479             }else if(c.tagName){ 
31480                 c = new T.Item({el:c});
31481             }else if(Ext.isObject(c)){ 
31482                 c = c.xtype ? this.createComponent(c) : this.constructButton(c);
31483             }
31484         }
31485         return c;
31486     },
31487
31488     
31489     applyDefaults : function(c){
31490         if(!Ext.isString(c)){
31491             c = Ext.Toolbar.superclass.applyDefaults.call(this, c);
31492             var d = this.internalDefaults;
31493             if(c.events){
31494                 Ext.applyIf(c.initialConfig, d);
31495                 Ext.apply(c, d);
31496             }else{
31497                 Ext.applyIf(c, d);
31498             }
31499         }
31500         return c;
31501     },
31502
31503     
31504     addSeparator : function(){
31505         return this.add(new T.Separator());
31506     },
31507
31508     
31509     addSpacer : function(){
31510         return this.add(new T.Spacer());
31511     },
31512
31513     
31514     addFill : function(){
31515         this.add(new T.Fill());
31516     },
31517
31518     
31519     addElement : function(el){
31520         return this.addItem(new T.Item({el:el}));
31521     },
31522
31523     
31524     addItem : function(item){
31525         return this.add.apply(this, arguments);
31526     },
31527
31528     
31529     addButton : function(config){
31530         if(Ext.isArray(config)){
31531             var buttons = [];
31532             for(var i = 0, len = config.length; i < len; i++) {
31533                 buttons.push(this.addButton(config[i]));
31534             }
31535             return buttons;
31536         }
31537         return this.add(this.constructButton(config));
31538     },
31539
31540     
31541     addText : function(text){
31542         return this.addItem(new T.TextItem(text));
31543     },
31544
31545     
31546     addDom : function(config){
31547         return this.add(new T.Item({autoEl: config}));
31548     },
31549
31550     
31551     addField : function(field){
31552         return this.add(field);
31553     },
31554
31555     
31556     insertButton : function(index, item){
31557         if(Ext.isArray(item)){
31558             var buttons = [];
31559             for(var i = 0, len = item.length; i < len; i++) {
31560                buttons.push(this.insertButton(index + i, item[i]));
31561             }
31562             return buttons;
31563         }
31564         return Ext.Toolbar.superclass.insert.call(this, index, item);
31565     },
31566
31567     
31568     trackMenu : function(item, remove){
31569         if(this.trackMenus && item.menu){
31570             var method = remove ? 'mun' : 'mon';
31571             this[method](item, 'menutriggerover', this.onButtonTriggerOver, this);
31572             this[method](item, 'menushow', this.onButtonMenuShow, this);
31573             this[method](item, 'menuhide', this.onButtonMenuHide, this);
31574         }
31575     },
31576
31577     
31578     constructButton : function(item){
31579         var b = item.events ? item : this.createComponent(item, item.split ? 'splitbutton' : this.defaultType);
31580         return b;
31581     },
31582
31583     
31584     onAdd : function(c){
31585         Ext.Toolbar.superclass.onAdd.call(this);
31586         this.trackMenu(c);
31587         if(this.disabled){
31588             c.disable();
31589         }
31590     },
31591
31592     
31593     onRemove : function(c){
31594         Ext.Toolbar.superclass.onRemove.call(this);
31595         if (c == this.activeMenuBtn) {
31596             delete this.activeMenuBtn;
31597         }
31598         this.trackMenu(c, true);
31599     },
31600
31601     
31602     onDisable : function(){
31603         this.items.each(function(item){
31604              if(item.disable){
31605                  item.disable();
31606              }
31607         });
31608     },
31609
31610     
31611     onEnable : function(){
31612         this.items.each(function(item){
31613              if(item.enable){
31614                  item.enable();
31615              }
31616         });
31617     },
31618
31619     
31620     onButtonTriggerOver : function(btn){
31621         if(this.activeMenuBtn && this.activeMenuBtn != btn){
31622             this.activeMenuBtn.hideMenu();
31623             btn.showMenu();
31624             this.activeMenuBtn = btn;
31625         }
31626     },
31627
31628     
31629     onButtonMenuShow : function(btn){
31630         this.activeMenuBtn = btn;
31631     },
31632
31633     
31634     onButtonMenuHide : function(btn){
31635         delete this.activeMenuBtn;
31636     }
31637 });
31638 Ext.reg('toolbar', Ext.Toolbar);
31639
31640
31641 T.Item = Ext.extend(Ext.BoxComponent, {
31642     hideParent: true, 
31643     enable:Ext.emptyFn,
31644     disable:Ext.emptyFn,
31645     focus:Ext.emptyFn
31646     
31647 });
31648 Ext.reg('tbitem', T.Item);
31649
31650
31651 T.Separator = Ext.extend(T.Item, {
31652     onRender : function(ct, position){
31653         this.el = ct.createChild({tag:'span', cls:'xtb-sep'}, position);
31654     }
31655 });
31656 Ext.reg('tbseparator', T.Separator);
31657
31658
31659 T.Spacer = Ext.extend(T.Item, {
31660     
31661
31662     onRender : function(ct, position){
31663         this.el = ct.createChild({tag:'div', cls:'xtb-spacer', style: this.width?'width:'+this.width+'px':''}, position);
31664     }
31665 });
31666 Ext.reg('tbspacer', T.Spacer);
31667
31668
31669 T.Fill = Ext.extend(T.Item, {
31670     
31671     render : Ext.emptyFn,
31672     isFill : true
31673 });
31674 Ext.reg('tbfill', T.Fill);
31675
31676
31677 T.TextItem = Ext.extend(T.Item, {
31678     
31679
31680     constructor: function(config){
31681         T.TextItem.superclass.constructor.call(this, Ext.isString(config) ? {text: config} : config);
31682     },
31683
31684     
31685     onRender : function(ct, position) {
31686         this.autoEl = {cls: 'xtb-text', html: this.text || ''};
31687         T.TextItem.superclass.onRender.call(this, ct, position);
31688     },
31689
31690     
31691     setText : function(t) {
31692         if(this.rendered){
31693             this.el.update(t);
31694         }else{
31695             this.text = t;
31696         }
31697     }
31698 });
31699 Ext.reg('tbtext', T.TextItem);
31700
31701
31702 T.Button = Ext.extend(Ext.Button, {});
31703 T.SplitButton = Ext.extend(Ext.SplitButton, {});
31704 Ext.reg('tbbutton', T.Button);
31705 Ext.reg('tbsplit', T.SplitButton);
31706
31707 })();
31708
31709 Ext.ButtonGroup = Ext.extend(Ext.Panel, {
31710     
31711     
31712     baseCls: 'x-btn-group',
31713     
31714     layout:'table',
31715     defaultType: 'button',
31716     
31717     frame: true,
31718     internalDefaults: {removeMode: 'container', hideParent: true},
31719
31720     initComponent : function(){
31721         this.layoutConfig = this.layoutConfig || {};
31722         Ext.applyIf(this.layoutConfig, {
31723             columns : this.columns
31724         });
31725         if(!this.title){
31726             this.addClass('x-btn-group-notitle');
31727         }
31728         this.on('afterlayout', this.onAfterLayout, this);
31729         Ext.ButtonGroup.superclass.initComponent.call(this);
31730     },
31731
31732     applyDefaults : function(c){
31733         c = Ext.ButtonGroup.superclass.applyDefaults.call(this, c);
31734         var d = this.internalDefaults;
31735         if(c.events){
31736             Ext.applyIf(c.initialConfig, d);
31737             Ext.apply(c, d);
31738         }else{
31739             Ext.applyIf(c, d);
31740         }
31741         return c;
31742     },
31743
31744     onAfterLayout : function(){
31745         var bodyWidth = this.body.getFrameWidth('lr') + this.body.dom.firstChild.offsetWidth;
31746         this.body.setWidth(bodyWidth);
31747         this.el.setWidth(bodyWidth + this.getFrameWidth());
31748     }
31749     
31750 });
31751
31752 Ext.reg('buttongroup', Ext.ButtonGroup);
31753
31754 (function() {
31755
31756 var T = Ext.Toolbar;
31757
31758 Ext.PagingToolbar = Ext.extend(Ext.Toolbar, {
31759     
31760     
31761     
31762     pageSize : 20,
31763     
31764     
31765     displayMsg : 'Displaying {0} - {1} of {2}',
31766     
31767     emptyMsg : 'No data to display',
31768     
31769     beforePageText : 'Page',
31770     
31771     afterPageText : 'of {0}',
31772     
31773     firstText : 'First Page',
31774     
31775     prevText : 'Previous Page',
31776     
31777     nextText : 'Next Page',
31778     
31779     lastText : 'Last Page',
31780     
31781     refreshText : 'Refresh',
31782
31783     
31784
31785     
31786
31787     
31788
31789     initComponent : function(){
31790         var pagingItems = [this.first = new T.Button({
31791             tooltip: this.firstText,
31792             overflowText: this.firstText,
31793             iconCls: 'x-tbar-page-first',
31794             disabled: true,
31795             handler: this.moveFirst,
31796             scope: this
31797         }), this.prev = new T.Button({
31798             tooltip: this.prevText,
31799             overflowText: this.prevText,
31800             iconCls: 'x-tbar-page-prev',
31801             disabled: true,
31802             handler: this.movePrevious,
31803             scope: this
31804         }), '-', this.beforePageText,
31805         this.inputItem = new Ext.form.NumberField({
31806             cls: 'x-tbar-page-number',
31807             allowDecimals: false,
31808             allowNegative: false,
31809             enableKeyEvents: true,
31810             selectOnFocus: true,
31811             submitValue: false,
31812             listeners: {
31813                 scope: this,
31814                 keydown: this.onPagingKeyDown,
31815                 blur: this.onPagingBlur
31816             }
31817         }), this.afterTextItem = new T.TextItem({
31818             text: String.format(this.afterPageText, 1)
31819         }), '-', this.next = new T.Button({
31820             tooltip: this.nextText,
31821             overflowText: this.nextText,
31822             iconCls: 'x-tbar-page-next',
31823             disabled: true,
31824             handler: this.moveNext,
31825             scope: this
31826         }), this.last = new T.Button({
31827             tooltip: this.lastText,
31828             overflowText: this.lastText,
31829             iconCls: 'x-tbar-page-last',
31830             disabled: true,
31831             handler: this.moveLast,
31832             scope: this
31833         }), '-', this.refresh = new T.Button({
31834             tooltip: this.refreshText,
31835             overflowText: this.refreshText,
31836             iconCls: 'x-tbar-loading',
31837             handler: this.doRefresh,
31838             scope: this
31839         })];
31840
31841
31842         var userItems = this.items || this.buttons || [];
31843         if (this.prependButtons) {
31844             this.items = userItems.concat(pagingItems);
31845         }else{
31846             this.items = pagingItems.concat(userItems);
31847         }
31848         delete this.buttons;
31849         if(this.displayInfo){
31850             this.items.push('->');
31851             this.items.push(this.displayItem = new T.TextItem({}));
31852         }
31853         Ext.PagingToolbar.superclass.initComponent.call(this);
31854         this.addEvents(
31855             
31856             'change',
31857             
31858             'beforechange'
31859         );
31860         this.on('afterlayout', this.onFirstLayout, this, {single: true});
31861         this.cursor = 0;
31862         this.bindStore(this.store, true);
31863     },
31864
31865     
31866     onFirstLayout : function(){
31867         if(this.dsLoaded){
31868             this.onLoad.apply(this, this.dsLoaded);
31869         }
31870     },
31871
31872     
31873     updateInfo : function(){
31874         if(this.displayItem){
31875             var count = this.store.getCount();
31876             var msg = count == 0 ?
31877                 this.emptyMsg :
31878                 String.format(
31879                     this.displayMsg,
31880                     this.cursor+1, this.cursor+count, this.store.getTotalCount()
31881                 );
31882             this.displayItem.setText(msg);
31883         }
31884     },
31885
31886     
31887     onLoad : function(store, r, o){
31888         if(!this.rendered){
31889             this.dsLoaded = [store, r, o];
31890             return;
31891         }
31892         var p = this.getParams();
31893         this.cursor = (o.params && o.params[p.start]) ? o.params[p.start] : 0;
31894         var d = this.getPageData(), ap = d.activePage, ps = d.pages;
31895
31896         this.afterTextItem.setText(String.format(this.afterPageText, d.pages));
31897         this.inputItem.setValue(ap);
31898         this.first.setDisabled(ap == 1);
31899         this.prev.setDisabled(ap == 1);
31900         this.next.setDisabled(ap == ps);
31901         this.last.setDisabled(ap == ps);
31902         this.refresh.enable();
31903         this.updateInfo();
31904         this.fireEvent('change', this, d);
31905     },
31906
31907     
31908     getPageData : function(){
31909         var total = this.store.getTotalCount();
31910         return {
31911             total : total,
31912             activePage : Math.ceil((this.cursor+this.pageSize)/this.pageSize),
31913             pages :  total < this.pageSize ? 1 : Math.ceil(total/this.pageSize)
31914         };
31915     },
31916
31917     
31918     changePage : function(page){
31919         this.doLoad(((page-1) * this.pageSize).constrain(0, this.store.getTotalCount()));
31920     },
31921
31922     
31923     onLoadError : function(){
31924         if(!this.rendered){
31925             return;
31926         }
31927         this.refresh.enable();
31928     },
31929
31930     
31931     readPage : function(d){
31932         var v = this.inputItem.getValue(), pageNum;
31933         if (!v || isNaN(pageNum = parseInt(v, 10))) {
31934             this.inputItem.setValue(d.activePage);
31935             return false;
31936         }
31937         return pageNum;
31938     },
31939
31940     onPagingFocus : function(){
31941         this.inputItem.select();
31942     },
31943
31944     
31945     onPagingBlur : function(e){
31946         this.inputItem.setValue(this.getPageData().activePage);
31947     },
31948
31949     
31950     onPagingKeyDown : function(field, e){
31951         var k = e.getKey(), d = this.getPageData(), pageNum;
31952         if (k == e.RETURN) {
31953             e.stopEvent();
31954             pageNum = this.readPage(d);
31955             if(pageNum !== false){
31956                 pageNum = Math.min(Math.max(1, pageNum), d.pages) - 1;
31957                 this.doLoad(pageNum * this.pageSize);
31958             }
31959         }else if (k == e.HOME || k == e.END){
31960             e.stopEvent();
31961             pageNum = k == e.HOME ? 1 : d.pages;
31962             field.setValue(pageNum);
31963         }else if (k == e.UP || k == e.PAGEUP || k == e.DOWN || k == e.PAGEDOWN){
31964             e.stopEvent();
31965             if((pageNum = this.readPage(d))){
31966                 var increment = e.shiftKey ? 10 : 1;
31967                 if(k == e.DOWN || k == e.PAGEDOWN){
31968                     increment *= -1;
31969                 }
31970                 pageNum += increment;
31971                 if(pageNum >= 1 & pageNum <= d.pages){
31972                     field.setValue(pageNum);
31973                 }
31974             }
31975         }
31976     },
31977
31978     
31979     getParams : function(){
31980         
31981         return this.paramNames || this.store.paramNames;
31982     },
31983
31984     
31985     beforeLoad : function(){
31986         if(this.rendered && this.refresh){
31987             this.refresh.disable();
31988         }
31989     },
31990
31991     
31992     doLoad : function(start){
31993         var o = {}, pn = this.getParams();
31994         o[pn.start] = start;
31995         o[pn.limit] = this.pageSize;
31996         if(this.fireEvent('beforechange', this, o) !== false){
31997             this.store.load({params:o});
31998         }
31999     },
32000
32001     
32002     moveFirst : function(){
32003         this.doLoad(0);
32004     },
32005
32006     
32007     movePrevious : function(){
32008         this.doLoad(Math.max(0, this.cursor-this.pageSize));
32009     },
32010
32011     
32012     moveNext : function(){
32013         this.doLoad(this.cursor+this.pageSize);
32014     },
32015
32016     
32017     moveLast : function(){
32018         var total = this.store.getTotalCount(),
32019             extra = total % this.pageSize;
32020
32021         this.doLoad(extra ? (total - extra) : total - this.pageSize);
32022     },
32023
32024     
32025     doRefresh : function(){
32026         this.doLoad(this.cursor);
32027     },
32028
32029     
32030     bindStore : function(store, initial){
32031         var doLoad;
32032         if(!initial && this.store){
32033             if(store !== this.store && this.store.autoDestroy){
32034                 this.store.destroy();
32035             }else{
32036                 this.store.un('beforeload', this.beforeLoad, this);
32037                 this.store.un('load', this.onLoad, this);
32038                 this.store.un('exception', this.onLoadError, this);
32039             }
32040             if(!store){
32041                 this.store = null;
32042             }
32043         }
32044         if(store){
32045             store = Ext.StoreMgr.lookup(store);
32046             store.on({
32047                 scope: this,
32048                 beforeload: this.beforeLoad,
32049                 load: this.onLoad,
32050                 exception: this.onLoadError
32051             });
32052             doLoad = true;
32053         }
32054         this.store = store;
32055         if(doLoad){
32056             this.onLoad(store, null, {});
32057         }
32058     },
32059
32060     
32061     unbind : function(store){
32062         this.bindStore(null);
32063     },
32064
32065     
32066     bind : function(store){
32067         this.bindStore(store);
32068     },
32069
32070     
32071     onDestroy : function(){
32072         this.bindStore(null);
32073         Ext.PagingToolbar.superclass.onDestroy.call(this);
32074     }
32075 });
32076
32077 })();
32078 Ext.reg('paging', Ext.PagingToolbar);
32079 Ext.History = (function () {
32080     var iframe, hiddenField;
32081     var ready = false;
32082     var currentToken;
32083
32084     function getHash() {
32085         var href = location.href, i = href.indexOf("#");
32086         return i >= 0 ? href.substr(i + 1) : null;
32087     }
32088
32089     function doSave() {
32090         hiddenField.value = currentToken;
32091     }
32092
32093     function handleStateChange(token) {
32094         currentToken = token;
32095         Ext.History.fireEvent('change', token);
32096     }
32097
32098     function updateIFrame (token) {
32099         var html = ['<html><body><div id="state">',Ext.util.Format.htmlEncode(token),'</div></body></html>'].join('');
32100         try {
32101             var doc = iframe.contentWindow.document;
32102             doc.open();
32103             doc.write(html);
32104             doc.close();
32105             return true;
32106         } catch (e) {
32107             return false;
32108         }
32109     }
32110
32111     function checkIFrame() {
32112         if (!iframe.contentWindow || !iframe.contentWindow.document) {
32113             setTimeout(checkIFrame, 10);
32114             return;
32115         }
32116
32117         var doc = iframe.contentWindow.document;
32118         var elem = doc.getElementById("state");
32119         var token = elem ? elem.innerText : null;
32120
32121         var hash = getHash();
32122
32123         setInterval(function () {
32124
32125             doc = iframe.contentWindow.document;
32126             elem = doc.getElementById("state");
32127
32128             var newtoken = elem ? elem.innerText : null;
32129
32130             var newHash = getHash();
32131
32132             if (newtoken !== token) {
32133                 token = newtoken;
32134                 handleStateChange(token);
32135                 top.location.hash = token;
32136                 hash = token;
32137                 doSave();
32138             } else if (newHash !== hash) {
32139                 hash = newHash;
32140                 updateIFrame(newHash);
32141             }
32142
32143         }, 50);
32144
32145         ready = true;
32146
32147         Ext.History.fireEvent('ready', Ext.History);
32148     }
32149
32150     function startUp() {
32151         currentToken = hiddenField.value ? hiddenField.value : getHash();
32152
32153         if (Ext.isIE) {
32154             checkIFrame();
32155         } else {
32156             var hash = getHash();
32157             setInterval(function () {
32158                 var newHash = getHash();
32159                 if (newHash !== hash) {
32160                     hash = newHash;
32161                     handleStateChange(hash);
32162                     doSave();
32163                 }
32164             }, 50);
32165             ready = true;
32166             Ext.History.fireEvent('ready', Ext.History);
32167         }
32168     }
32169
32170     return {
32171         
32172         fieldId: 'x-history-field',
32173         
32174         iframeId: 'x-history-frame',
32175
32176         events:{},
32177
32178         
32179         init: function (onReady, scope) {
32180             if(ready) {
32181                 Ext.callback(onReady, scope, [this]);
32182                 return;
32183             }
32184             if(!Ext.isReady){
32185                 Ext.onReady(function(){
32186                     Ext.History.init(onReady, scope);
32187                 });
32188                 return;
32189             }
32190             hiddenField = Ext.getDom(Ext.History.fieldId);
32191             if (Ext.isIE) {
32192                 iframe = Ext.getDom(Ext.History.iframeId);
32193             }
32194             this.addEvents(
32195                 
32196                 'ready',
32197                 
32198                 'change'
32199             );
32200             if(onReady){
32201                 this.on('ready', onReady, scope, {single:true});
32202             }
32203             startUp();
32204         },
32205
32206         
32207         add: function (token, preventDup) {
32208             if(preventDup !== false){
32209                 if(this.getToken() == token){
32210                     return true;
32211                 }
32212             }
32213             if (Ext.isIE) {
32214                 return updateIFrame(token);
32215             } else {
32216                 top.location.hash = token;
32217                 return true;
32218             }
32219         },
32220
32221         
32222         back: function(){
32223             history.go(-1);
32224         },
32225
32226         
32227         forward: function(){
32228             history.go(1);
32229         },
32230
32231         
32232         getToken: function() {
32233             return ready ? currentToken : getHash();
32234         }
32235     };
32236 })();
32237 Ext.apply(Ext.History, new Ext.util.Observable());
32238 Ext.Tip = Ext.extend(Ext.Panel, {
32239     
32240     
32241     
32242     minWidth : 40,
32243     
32244     maxWidth : 300,
32245     
32246     shadow : "sides",
32247     
32248     defaultAlign : "tl-bl?",
32249     autoRender: true,
32250     quickShowInterval : 250,
32251
32252     
32253     frame:true,
32254     hidden:true,
32255     baseCls: 'x-tip',
32256     floating:{shadow:true,shim:true,useDisplay:true,constrain:false},
32257     autoHeight:true,
32258
32259     closeAction: 'hide',
32260
32261     
32262     initComponent : function(){
32263         Ext.Tip.superclass.initComponent.call(this);
32264         if(this.closable && !this.title){
32265             this.elements += ',header';
32266         }
32267     },
32268
32269     
32270     afterRender : function(){
32271         Ext.Tip.superclass.afterRender.call(this);
32272         if(this.closable){
32273             this.addTool({
32274                 id: 'close',
32275                 handler: this[this.closeAction],
32276                 scope: this
32277             });
32278         }
32279     },
32280
32281     
32282     showAt : function(xy){
32283         Ext.Tip.superclass.show.call(this);
32284         if(this.measureWidth !== false && (!this.initialConfig || typeof this.initialConfig.width != 'number')){
32285             this.doAutoWidth();
32286         }
32287         if(this.constrainPosition){
32288             xy = this.el.adjustForConstraints(xy);
32289         }
32290         this.setPagePosition(xy[0], xy[1]);
32291     },
32292
32293     
32294     doAutoWidth : function(adjust){
32295         adjust = adjust || 0;
32296         var bw = this.body.getTextWidth();
32297         if(this.title){
32298             bw = Math.max(bw, this.header.child('span').getTextWidth(this.title));
32299         }
32300         bw += this.getFrameWidth() + (this.closable ? 20 : 0) + this.body.getPadding("lr") + adjust;
32301         this.setWidth(bw.constrain(this.minWidth, this.maxWidth));
32302         
32303         
32304         if(Ext.isIE7 && !this.repainted){
32305             this.el.repaint();
32306             this.repainted = true;
32307         }
32308     },
32309
32310     
32311     showBy : function(el, pos){
32312         if(!this.rendered){
32313             this.render(Ext.getBody());
32314         }
32315         this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign));
32316     },
32317
32318     initDraggable : function(){
32319         this.dd = new Ext.Tip.DD(this, typeof this.draggable == 'boolean' ? null : this.draggable);
32320         this.header.addClass('x-tip-draggable');
32321     }
32322 });
32323
32324 Ext.reg('tip', Ext.Tip);
32325
32326
32327 Ext.Tip.DD = function(tip, config){
32328     Ext.apply(this, config);
32329     this.tip = tip;
32330     Ext.Tip.DD.superclass.constructor.call(this, tip.el.id, 'WindowDD-'+tip.id);
32331     this.setHandleElId(tip.header.id);
32332     this.scroll = false;
32333 };
32334
32335 Ext.extend(Ext.Tip.DD, Ext.dd.DD, {
32336     moveOnly:true,
32337     scroll:false,
32338     headerOffsets:[100, 25],
32339     startDrag : function(){
32340         this.tip.el.disableShadow();
32341     },
32342     endDrag : function(e){
32343         this.tip.el.enableShadow(true);
32344     }
32345 });
32346 Ext.ToolTip = Ext.extend(Ext.Tip, {
32347     
32348     
32349     
32350     
32351     showDelay : 500,
32352     
32353     hideDelay : 200,
32354     
32355     dismissDelay : 5000,
32356     
32357     
32358     trackMouse : false,
32359     
32360     anchorToTarget : true,
32361     
32362     anchorOffset : 0,
32363     
32364
32365     
32366     targetCounter : 0,
32367
32368     constrainPosition : false,
32369
32370     
32371     initComponent : function(){
32372         Ext.ToolTip.superclass.initComponent.call(this);
32373         this.lastActive = new Date();
32374         this.initTarget(this.target);
32375         this.origAnchor = this.anchor;
32376     },
32377
32378     
32379     onRender : function(ct, position){
32380         Ext.ToolTip.superclass.onRender.call(this, ct, position);
32381         this.anchorCls = 'x-tip-anchor-' + this.getAnchorPosition();
32382         this.anchorEl = this.el.createChild({
32383             cls: 'x-tip-anchor ' + this.anchorCls
32384         });
32385     },
32386
32387     
32388     afterRender : function(){
32389         Ext.ToolTip.superclass.afterRender.call(this);
32390         this.anchorEl.setStyle('z-index', this.el.getZIndex() + 1).setVisibilityMode(Ext.Element.DISPLAY);
32391     },
32392
32393     
32394     initTarget : function(target){
32395         var t;
32396         if((t = Ext.get(target))){
32397             if(this.target){
32398                 var tg = Ext.get(this.target);
32399                 this.mun(tg, 'mouseover', this.onTargetOver, this);
32400                 this.mun(tg, 'mouseout', this.onTargetOut, this);
32401                 this.mun(tg, 'mousemove', this.onMouseMove, this);
32402             }
32403             this.mon(t, {
32404                 mouseover: this.onTargetOver,
32405                 mouseout: this.onTargetOut,
32406                 mousemove: this.onMouseMove,
32407                 scope: this
32408             });
32409             this.target = t;
32410         }
32411         if(this.anchor){
32412             this.anchorTarget = this.target;
32413         }
32414     },
32415
32416     
32417     onMouseMove : function(e){
32418         var t = this.delegate ? e.getTarget(this.delegate) : this.triggerElement = true;
32419         if (t) {
32420             this.targetXY = e.getXY();
32421             if (t === this.triggerElement) {
32422                 if(!this.hidden && this.trackMouse){
32423                     this.setPagePosition(this.getTargetXY());
32424                 }
32425             } else {
32426                 this.hide();
32427                 this.lastActive = new Date(0);
32428                 this.onTargetOver(e);
32429             }
32430         } else if (!this.closable && this.isVisible()) {
32431             this.hide();
32432         }
32433     },
32434
32435     
32436     getTargetXY : function(){
32437         if(this.delegate){
32438             this.anchorTarget = this.triggerElement;
32439         }
32440         if(this.anchor){
32441             this.targetCounter++;
32442             var offsets = this.getOffsets(),
32443                 xy = (this.anchorToTarget && !this.trackMouse) ? this.el.getAlignToXY(this.anchorTarget, this.getAnchorAlign()) : this.targetXY,
32444                 dw = Ext.lib.Dom.getViewWidth() - 5,
32445                 dh = Ext.lib.Dom.getViewHeight() - 5,
32446                 de = document.documentElement,
32447                 bd = document.body,
32448                 scrollX = (de.scrollLeft || bd.scrollLeft || 0) + 5,
32449                 scrollY = (de.scrollTop || bd.scrollTop || 0) + 5,
32450                 axy = [xy[0] + offsets[0], xy[1] + offsets[1]],
32451                 sz = this.getSize();
32452                 
32453             this.anchorEl.removeClass(this.anchorCls);
32454
32455             if(this.targetCounter < 2){
32456                 if(axy[0] < scrollX){
32457                     if(this.anchorToTarget){
32458                         this.defaultAlign = 'l-r';
32459                         if(this.mouseOffset){this.mouseOffset[0] *= -1;}
32460                     }
32461                     this.anchor = 'left';
32462                     return this.getTargetXY();
32463                 }
32464                 if(axy[0]+sz.width > dw){
32465                     if(this.anchorToTarget){
32466                         this.defaultAlign = 'r-l';
32467                         if(this.mouseOffset){this.mouseOffset[0] *= -1;}
32468                     }
32469                     this.anchor = 'right';
32470                     return this.getTargetXY();
32471                 }
32472                 if(axy[1] < scrollY){
32473                     if(this.anchorToTarget){
32474                         this.defaultAlign = 't-b';
32475                         if(this.mouseOffset){this.mouseOffset[1] *= -1;}
32476                     }
32477                     this.anchor = 'top';
32478                     return this.getTargetXY();
32479                 }
32480                 if(axy[1]+sz.height > dh){
32481                     if(this.anchorToTarget){
32482                         this.defaultAlign = 'b-t';
32483                         if(this.mouseOffset){this.mouseOffset[1] *= -1;}
32484                     }
32485                     this.anchor = 'bottom';
32486                     return this.getTargetXY();
32487                 }
32488             }
32489
32490             this.anchorCls = 'x-tip-anchor-'+this.getAnchorPosition();
32491             this.anchorEl.addClass(this.anchorCls);
32492             this.targetCounter = 0;
32493             return axy;
32494         }else{
32495             var mouseOffset = this.getMouseOffset();
32496             return [this.targetXY[0]+mouseOffset[0], this.targetXY[1]+mouseOffset[1]];
32497         }
32498     },
32499
32500     getMouseOffset : function(){
32501         var offset = this.anchor ? [0,0] : [15,18];
32502         if(this.mouseOffset){
32503             offset[0] += this.mouseOffset[0];
32504             offset[1] += this.mouseOffset[1];
32505         }
32506         return offset;
32507     },
32508
32509     
32510     getAnchorPosition : function(){
32511         if(this.anchor){
32512             this.tipAnchor = this.anchor.charAt(0);
32513         }else{
32514             var m = this.defaultAlign.match(/^([a-z]+)-([a-z]+)(\?)?$/);
32515             if(!m){
32516                throw 'AnchorTip.defaultAlign is invalid';
32517             }
32518             this.tipAnchor = m[1].charAt(0);
32519         }
32520
32521         switch(this.tipAnchor){
32522             case 't': return 'top';
32523             case 'b': return 'bottom';
32524             case 'r': return 'right';
32525         }
32526         return 'left';
32527     },
32528
32529     
32530     getAnchorAlign : function(){
32531         switch(this.anchor){
32532             case 'top'  : return 'tl-bl';
32533             case 'left' : return 'tl-tr';
32534             case 'right': return 'tr-tl';
32535             default     : return 'bl-tl';
32536         }
32537     },
32538
32539     
32540     getOffsets : function(){
32541         var offsets, 
32542             ap = this.getAnchorPosition().charAt(0);
32543         if(this.anchorToTarget && !this.trackMouse){
32544             switch(ap){
32545                 case 't':
32546                     offsets = [0, 9];
32547                     break;
32548                 case 'b':
32549                     offsets = [0, -13];
32550                     break;
32551                 case 'r':
32552                     offsets = [-13, 0];
32553                     break;
32554                 default:
32555                     offsets = [9, 0];
32556                     break;
32557             }
32558         }else{
32559             switch(ap){
32560                 case 't':
32561                     offsets = [-15-this.anchorOffset, 30];
32562                     break;
32563                 case 'b':
32564                     offsets = [-19-this.anchorOffset, -13-this.el.dom.offsetHeight];
32565                     break;
32566                 case 'r':
32567                     offsets = [-15-this.el.dom.offsetWidth, -13-this.anchorOffset];
32568                     break;
32569                 default:
32570                     offsets = [25, -13-this.anchorOffset];
32571                     break;
32572             }
32573         }
32574         var mouseOffset = this.getMouseOffset();
32575         offsets[0] += mouseOffset[0];
32576         offsets[1] += mouseOffset[1];
32577
32578         return offsets;
32579     },
32580
32581     
32582     onTargetOver : function(e){
32583         if(this.disabled || e.within(this.target.dom, true)){
32584             return;
32585         }
32586         var t = e.getTarget(this.delegate);
32587         if (t) {
32588             this.triggerElement = t;
32589             this.clearTimer('hide');
32590             this.targetXY = e.getXY();
32591             this.delayShow();
32592         }
32593     },
32594
32595     
32596     delayShow : function(){
32597         if(this.hidden && !this.showTimer){
32598             if(this.lastActive.getElapsed() < this.quickShowInterval){
32599                 this.show();
32600             }else{
32601                 this.showTimer = this.show.defer(this.showDelay, this);
32602             }
32603         }else if(!this.hidden && this.autoHide !== false){
32604             this.show();
32605         }
32606     },
32607
32608     
32609     onTargetOut : function(e){
32610         if(this.disabled || e.within(this.target.dom, true)){
32611             return;
32612         }
32613         this.clearTimer('show');
32614         if(this.autoHide !== false){
32615             this.delayHide();
32616         }
32617     },
32618
32619     
32620     delayHide : function(){
32621         if(!this.hidden && !this.hideTimer){
32622             this.hideTimer = this.hide.defer(this.hideDelay, this);
32623         }
32624     },
32625
32626     
32627     hide: function(){
32628         this.clearTimer('dismiss');
32629         this.lastActive = new Date();
32630         if(this.anchorEl){
32631             this.anchorEl.hide();
32632         }
32633         Ext.ToolTip.superclass.hide.call(this);
32634         delete this.triggerElement;
32635     },
32636
32637     
32638     show : function(){
32639         if(this.anchor){
32640             
32641             
32642             this.showAt([-1000,-1000]);
32643             this.origConstrainPosition = this.constrainPosition;
32644             this.constrainPosition = false;
32645             this.anchor = this.origAnchor;
32646         }
32647         this.showAt(this.getTargetXY());
32648
32649         if(this.anchor){
32650             this.anchorEl.show();
32651             this.syncAnchor();
32652             this.constrainPosition = this.origConstrainPosition;
32653         }else{
32654             this.anchorEl.hide();
32655         }
32656     },
32657
32658     
32659     showAt : function(xy){
32660         this.lastActive = new Date();
32661         this.clearTimers();
32662         Ext.ToolTip.superclass.showAt.call(this, xy);
32663         if(this.dismissDelay && this.autoHide !== false){
32664             this.dismissTimer = this.hide.defer(this.dismissDelay, this);
32665         }
32666         if(this.anchor && !this.anchorEl.isVisible()){
32667             this.syncAnchor();
32668             this.anchorEl.show();
32669         }else{
32670             this.anchorEl.hide();
32671         }
32672     },
32673
32674     
32675     syncAnchor : function(){
32676         var anchorPos, targetPos, offset;
32677         switch(this.tipAnchor.charAt(0)){
32678             case 't':
32679                 anchorPos = 'b';
32680                 targetPos = 'tl';
32681                 offset = [20+this.anchorOffset, 2];
32682                 break;
32683             case 'r':
32684                 anchorPos = 'l';
32685                 targetPos = 'tr';
32686                 offset = [-2, 11+this.anchorOffset];
32687                 break;
32688             case 'b':
32689                 anchorPos = 't';
32690                 targetPos = 'bl';
32691                 offset = [20+this.anchorOffset, -2];
32692                 break;
32693             default:
32694                 anchorPos = 'r';
32695                 targetPos = 'tl';
32696                 offset = [2, 11+this.anchorOffset];
32697                 break;
32698         }
32699         this.anchorEl.alignTo(this.el, anchorPos+'-'+targetPos, offset);
32700     },
32701
32702     
32703     setPagePosition : function(x, y){
32704         Ext.ToolTip.superclass.setPagePosition.call(this, x, y);
32705         if(this.anchor){
32706             this.syncAnchor();
32707         }
32708     },
32709
32710     
32711     clearTimer : function(name){
32712         name = name + 'Timer';
32713         clearTimeout(this[name]);
32714         delete this[name];
32715     },
32716
32717     
32718     clearTimers : function(){
32719         this.clearTimer('show');
32720         this.clearTimer('dismiss');
32721         this.clearTimer('hide');
32722     },
32723
32724     
32725     onShow : function(){
32726         Ext.ToolTip.superclass.onShow.call(this);
32727         Ext.getDoc().on('mousedown', this.onDocMouseDown, this);
32728     },
32729
32730     
32731     onHide : function(){
32732         Ext.ToolTip.superclass.onHide.call(this);
32733         Ext.getDoc().un('mousedown', this.onDocMouseDown, this);
32734     },
32735
32736     
32737     onDocMouseDown : function(e){
32738         if(this.autoHide !== true && !this.closable && !e.within(this.el.dom)){
32739             this.disable();
32740             this.doEnable.defer(100, this);
32741         }
32742     },
32743     
32744     
32745     doEnable : function(){
32746         if(!this.isDestroyed){
32747             this.enable();
32748         }
32749     },
32750
32751     
32752     onDisable : function(){
32753         this.clearTimers();
32754         this.hide();
32755     },
32756
32757     
32758     adjustPosition : function(x, y){
32759         if(this.contstrainPosition){
32760             var ay = this.targetXY[1], h = this.getSize().height;
32761             if(y <= ay && (y+h) >= ay){
32762                 y = ay-h-5;
32763             }
32764         }
32765         return {x : x, y: y};
32766     },
32767     
32768     beforeDestroy : function(){
32769         this.clearTimers();
32770         Ext.destroy(this.anchorEl);
32771         delete this.anchorEl;
32772         delete this.target;
32773         delete this.anchorTarget;
32774         delete this.triggerElement;
32775         Ext.ToolTip.superclass.beforeDestroy.call(this);    
32776     },
32777
32778     
32779     onDestroy : function(){
32780         Ext.getDoc().un('mousedown', this.onDocMouseDown, this);
32781         Ext.ToolTip.superclass.onDestroy.call(this);
32782     }
32783 });
32784
32785 Ext.reg('tooltip', Ext.ToolTip);
32786 Ext.QuickTip = Ext.extend(Ext.ToolTip, {
32787     
32788     
32789     interceptTitles : false,
32790
32791     
32792     tagConfig : {
32793         namespace : "ext",
32794         attribute : "qtip",
32795         width : "qwidth",
32796         target : "target",
32797         title : "qtitle",
32798         hide : "hide",
32799         cls : "qclass",
32800         align : "qalign",
32801         anchor : "anchor"
32802     },
32803
32804     
32805     initComponent : function(){
32806         this.target = this.target || Ext.getDoc();
32807         this.targets = this.targets || {};
32808         Ext.QuickTip.superclass.initComponent.call(this);
32809     },
32810
32811     
32812     register : function(config){
32813         var cs = Ext.isArray(config) ? config : arguments;
32814         for(var i = 0, len = cs.length; i < len; i++){
32815             var c = cs[i];
32816             var target = c.target;
32817             if(target){
32818                 if(Ext.isArray(target)){
32819                     for(var j = 0, jlen = target.length; j < jlen; j++){
32820                         this.targets[Ext.id(target[j])] = c;
32821                     }
32822                 } else{
32823                     this.targets[Ext.id(target)] = c;
32824                 }
32825             }
32826         }
32827     },
32828
32829     
32830     unregister : function(el){
32831         delete this.targets[Ext.id(el)];
32832     },
32833     
32834     
32835     cancelShow: function(el){
32836         var at = this.activeTarget;
32837         el = Ext.get(el).dom;
32838         if(this.isVisible()){
32839             if(at && at.el == el){
32840                 this.hide();
32841             }
32842         }else if(at && at.el == el){
32843             this.clearTimer('show');
32844         }
32845     },
32846     
32847     getTipCfg: function(e) {
32848         var t = e.getTarget(), 
32849             ttp, 
32850             cfg;
32851         if(this.interceptTitles && t.title && Ext.isString(t.title)){
32852             ttp = t.title;
32853             t.qtip = ttp;
32854             t.removeAttribute("title");
32855             e.preventDefault();
32856         }else{
32857             cfg = this.tagConfig;
32858             ttp = t.qtip || Ext.fly(t).getAttribute(cfg.attribute, cfg.namespace);
32859         }
32860         return ttp;
32861     },
32862
32863     
32864     onTargetOver : function(e){
32865         if(this.disabled){
32866             return;
32867         }
32868         this.targetXY = e.getXY();
32869         var t = e.getTarget();
32870         if(!t || t.nodeType !== 1 || t == document || t == document.body){
32871             return;
32872         }
32873         if(this.activeTarget && ((t == this.activeTarget.el) || Ext.fly(this.activeTarget.el).contains(t))){
32874             this.clearTimer('hide');
32875             this.show();
32876             return;
32877         }
32878         if(t && this.targets[t.id]){
32879             this.activeTarget = this.targets[t.id];
32880             this.activeTarget.el = t;
32881             this.anchor = this.activeTarget.anchor;
32882             if(this.anchor){
32883                 this.anchorTarget = t;
32884             }
32885             this.delayShow();
32886             return;
32887         }
32888         var ttp, et = Ext.fly(t), cfg = this.tagConfig, ns = cfg.namespace;
32889         if(ttp = this.getTipCfg(e)){
32890             var autoHide = et.getAttribute(cfg.hide, ns);
32891             this.activeTarget = {
32892                 el: t,
32893                 text: ttp,
32894                 width: et.getAttribute(cfg.width, ns),
32895                 autoHide: autoHide != "user" && autoHide !== 'false',
32896                 title: et.getAttribute(cfg.title, ns),
32897                 cls: et.getAttribute(cfg.cls, ns),
32898                 align: et.getAttribute(cfg.align, ns)
32899                 
32900             };
32901             this.anchor = et.getAttribute(cfg.anchor, ns);
32902             if(this.anchor){
32903                 this.anchorTarget = t;
32904             }
32905             this.delayShow();
32906         }
32907     },
32908
32909     
32910     onTargetOut : function(e){
32911
32912         
32913         if (this.activeTarget && e.within(this.activeTarget.el) && !this.getTipCfg(e)) {
32914             return;
32915         }
32916
32917         this.clearTimer('show');
32918         if(this.autoHide !== false){
32919             this.delayHide();
32920         }
32921     },
32922
32923     
32924     showAt : function(xy){
32925         var t = this.activeTarget;
32926         if(t){
32927             if(!this.rendered){
32928                 this.render(Ext.getBody());
32929                 this.activeTarget = t;
32930             }
32931             if(t.width){
32932                 this.setWidth(t.width);
32933                 this.body.setWidth(this.adjustBodyWidth(t.width - this.getFrameWidth()));
32934                 this.measureWidth = false;
32935             } else{
32936                 this.measureWidth = true;
32937             }
32938             this.setTitle(t.title || '');
32939             this.body.update(t.text);
32940             this.autoHide = t.autoHide;
32941             this.dismissDelay = t.dismissDelay || this.dismissDelay;
32942             if(this.lastCls){
32943                 this.el.removeClass(this.lastCls);
32944                 delete this.lastCls;
32945             }
32946             if(t.cls){
32947                 this.el.addClass(t.cls);
32948                 this.lastCls = t.cls;
32949             }
32950             if(this.anchor){
32951                 this.constrainPosition = false;
32952             }else if(t.align){ 
32953                 xy = this.el.getAlignToXY(t.el, t.align);
32954                 this.constrainPosition = false;
32955             }else{
32956                 this.constrainPosition = true;
32957             }
32958         }
32959         Ext.QuickTip.superclass.showAt.call(this, xy);
32960     },
32961
32962     
32963     hide: function(){
32964         delete this.activeTarget;
32965         Ext.QuickTip.superclass.hide.call(this);
32966     }
32967 });
32968 Ext.reg('quicktip', Ext.QuickTip);
32969 Ext.QuickTips = function(){
32970     var tip,
32971         disabled = false;
32972         
32973     return {
32974         
32975         init : function(autoRender){
32976             if(!tip){
32977                 if(!Ext.isReady){
32978                     Ext.onReady(function(){
32979                         Ext.QuickTips.init(autoRender);
32980                     });
32981                     return;
32982                 }
32983                 tip = new Ext.QuickTip({
32984                     elements:'header,body', 
32985                     disabled: disabled
32986                 });
32987                 if(autoRender !== false){
32988                     tip.render(Ext.getBody());
32989                 }
32990             }
32991         },
32992         
32993         
32994         ddDisable : function(){
32995             
32996             if(tip && !disabled){
32997                 tip.disable();
32998             }    
32999         },
33000         
33001         
33002         ddEnable : function(){
33003             
33004             if(tip && !disabled){
33005                 tip.enable();
33006             }
33007         },
33008
33009         
33010         enable : function(){
33011             if(tip){
33012                 tip.enable();
33013             }
33014             disabled = false;
33015         },
33016
33017         
33018         disable : function(){
33019             if(tip){
33020                 tip.disable();
33021             }
33022             disabled = true;
33023         },
33024
33025         
33026         isEnabled : function(){
33027             return tip !== undefined && !tip.disabled;
33028         },
33029
33030         
33031         getQuickTip : function(){
33032             return tip;
33033         },
33034
33035         
33036         register : function(){
33037             tip.register.apply(tip, arguments);
33038         },
33039
33040         
33041         unregister : function(){
33042             tip.unregister.apply(tip, arguments);
33043         },
33044
33045         
33046         tips : function(){
33047             tip.register.apply(tip, arguments);
33048         }
33049     };
33050 }();
33051 Ext.slider.Tip = Ext.extend(Ext.Tip, {
33052     minWidth: 10,
33053     offsets : [0, -10],
33054     
33055     init: function(slider) {
33056         slider.on({
33057             scope    : this,
33058             dragstart: this.onSlide,
33059             drag     : this.onSlide,
33060             dragend  : this.hide,
33061             destroy  : this.destroy
33062         });
33063     },
33064     
33065     
33066     onSlide : function(slider, e, thumb) {
33067         this.show();
33068         this.body.update(this.getText(thumb));
33069         this.doAutoWidth();
33070         this.el.alignTo(thumb.el, 'b-t?', this.offsets);
33071     },
33072
33073     
33074     getText : function(thumb) {
33075         return String(thumb.value);
33076     }
33077 });
33078
33079
33080 Ext.ux.SliderTip = Ext.slider.Tip;
33081 Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
33082     rootVisible : true,
33083     animate : Ext.enableFx,
33084     lines : true,
33085     enableDD : false,
33086     hlDrop : Ext.enableFx,
33087     pathSeparator : '/',
33088
33089     
33090     bubbleEvents : [],
33091
33092     initComponent : function(){
33093         Ext.tree.TreePanel.superclass.initComponent.call(this);
33094
33095         if(!this.eventModel){
33096             this.eventModel = new Ext.tree.TreeEventModel(this);
33097         }
33098
33099         
33100         var l = this.loader;
33101         if(!l){
33102             l = new Ext.tree.TreeLoader({
33103                 dataUrl: this.dataUrl,
33104                 requestMethod: this.requestMethod
33105             });
33106         }else if(Ext.isObject(l) && !l.load){
33107             l = new Ext.tree.TreeLoader(l);
33108         }
33109         this.loader = l;
33110
33111         this.nodeHash = {};
33112
33113         
33114         if(this.root){
33115             var r = this.root;
33116             delete this.root;
33117             this.setRootNode(r);
33118         }
33119
33120
33121         this.addEvents(
33122
33123             
33124            'append',
33125            
33126            'remove',
33127            
33128            'movenode',
33129            
33130            'insert',
33131            
33132            'beforeappend',
33133            
33134            'beforeremove',
33135            
33136            'beforemovenode',
33137            
33138             'beforeinsert',
33139
33140             
33141             'beforeload',
33142             
33143             'load',
33144             
33145             'textchange',
33146             
33147             'beforeexpandnode',
33148             
33149             'beforecollapsenode',
33150             
33151             'expandnode',
33152             
33153             'disabledchange',
33154             
33155             'collapsenode',
33156             
33157             'beforeclick',
33158             
33159             'click',
33160             
33161             'containerclick',
33162             
33163             'checkchange',
33164             
33165             'beforedblclick',
33166             
33167             'dblclick',
33168             
33169             'containerdblclick',
33170             
33171             'contextmenu',
33172             
33173             'containercontextmenu',
33174             
33175             'beforechildrenrendered',
33176            
33177             'startdrag',
33178             
33179             'enddrag',
33180             
33181             'dragdrop',
33182             
33183             'beforenodedrop',
33184             
33185             'nodedrop',
33186              
33187             'nodedragover'
33188         );
33189         if(this.singleExpand){
33190             this.on('beforeexpandnode', this.restrictExpand, this);
33191         }
33192     },
33193
33194     
33195     proxyNodeEvent : function(ename, a1, a2, a3, a4, a5, a6){
33196         if(ename == 'collapse' || ename == 'expand' || ename == 'beforecollapse' || ename == 'beforeexpand' || ename == 'move' || ename == 'beforemove'){
33197             ename = ename+'node';
33198         }
33199         
33200         return this.fireEvent(ename, a1, a2, a3, a4, a5, a6);
33201     },
33202
33203
33204     
33205     getRootNode : function(){
33206         return this.root;
33207     },
33208
33209     
33210     setRootNode : function(node){
33211         this.destroyRoot();
33212         if(!node.render){ 
33213             node = this.loader.createNode(node);
33214         }
33215         this.root = node;
33216         node.ownerTree = this;
33217         node.isRoot = true;
33218         this.registerNode(node);
33219         if(!this.rootVisible){
33220             var uiP = node.attributes.uiProvider;
33221             node.ui = uiP ? new uiP(node) : new Ext.tree.RootTreeNodeUI(node);
33222         }
33223         if(this.innerCt){
33224             this.clearInnerCt();
33225             this.renderRoot();
33226         }
33227         return node;
33228     },
33229     
33230     clearInnerCt : function(){
33231         this.innerCt.update('');    
33232     },
33233     
33234     
33235     renderRoot : function(){
33236         this.root.render();
33237         if(!this.rootVisible){
33238             this.root.renderChildren();
33239         }
33240     },
33241
33242     
33243     getNodeById : function(id){
33244         return this.nodeHash[id];
33245     },
33246
33247     
33248     registerNode : function(node){
33249         this.nodeHash[node.id] = node;
33250     },
33251
33252     
33253     unregisterNode : function(node){
33254         delete this.nodeHash[node.id];
33255     },
33256
33257     
33258     toString : function(){
33259         return '[Tree'+(this.id?' '+this.id:'')+']';
33260     },
33261
33262     
33263     restrictExpand : function(node){
33264         var p = node.parentNode;
33265         if(p){
33266             if(p.expandedChild && p.expandedChild.parentNode == p){
33267                 p.expandedChild.collapse();
33268             }
33269             p.expandedChild = node;
33270         }
33271     },
33272
33273     
33274     getChecked : function(a, startNode){
33275         startNode = startNode || this.root;
33276         var r = [];
33277         var f = function(){
33278             if(this.attributes.checked){
33279                 r.push(!a ? this : (a == 'id' ? this.id : this.attributes[a]));
33280             }
33281         };
33282         startNode.cascade(f);
33283         return r;
33284     },
33285
33286     
33287     getLoader : function(){
33288         return this.loader;
33289     },
33290
33291     
33292     expandAll : function(){
33293         this.root.expand(true);
33294     },
33295
33296     
33297     collapseAll : function(){
33298         this.root.collapse(true);
33299     },
33300
33301     
33302     getSelectionModel : function(){
33303         if(!this.selModel){
33304             this.selModel = new Ext.tree.DefaultSelectionModel();
33305         }
33306         return this.selModel;
33307     },
33308
33309     
33310     expandPath : function(path, attr, callback){
33311         if(Ext.isEmpty(path)){
33312             if(callback){
33313                 callback(false, undefined);
33314             }
33315             return;
33316         }
33317         attr = attr || 'id';
33318         var keys = path.split(this.pathSeparator);
33319         var curNode = this.root;
33320         if(curNode.attributes[attr] != keys[1]){ 
33321             if(callback){
33322                 callback(false, null);
33323             }
33324             return;
33325         }
33326         var index = 1;
33327         var f = function(){
33328             if(++index == keys.length){
33329                 if(callback){
33330                     callback(true, curNode);
33331                 }
33332                 return;
33333             }
33334             var c = curNode.findChild(attr, keys[index]);
33335             if(!c){
33336                 if(callback){
33337                     callback(false, curNode);
33338                 }
33339                 return;
33340             }
33341             curNode = c;
33342             c.expand(false, false, f);
33343         };
33344         curNode.expand(false, false, f);
33345     },
33346
33347     
33348     selectPath : function(path, attr, callback){
33349         if(Ext.isEmpty(path)){
33350             if(callback){
33351                 callback(false, undefined);
33352             }
33353             return;
33354         }
33355         attr = attr || 'id';
33356         var keys = path.split(this.pathSeparator),
33357             v = keys.pop();
33358         if(keys.length > 1){
33359             var f = function(success, node){
33360                 if(success && node){
33361                     var n = node.findChild(attr, v);
33362                     if(n){
33363                         n.select();
33364                         if(callback){
33365                             callback(true, n);
33366                         }
33367                     }else if(callback){
33368                         callback(false, n);
33369                     }
33370                 }else{
33371                     if(callback){
33372                         callback(false, n);
33373                     }
33374                 }
33375             };
33376             this.expandPath(keys.join(this.pathSeparator), attr, f);
33377         }else{
33378             this.root.select();
33379             if(callback){
33380                 callback(true, this.root);
33381             }
33382         }
33383     },
33384
33385     
33386     getTreeEl : function(){
33387         return this.body;
33388     },
33389
33390     
33391     onRender : function(ct, position){
33392         Ext.tree.TreePanel.superclass.onRender.call(this, ct, position);
33393         this.el.addClass('x-tree');
33394         this.innerCt = this.body.createChild({tag:'ul',
33395                cls:'x-tree-root-ct ' +
33396                (this.useArrows ? 'x-tree-arrows' : this.lines ? 'x-tree-lines' : 'x-tree-no-lines')});
33397     },
33398
33399     
33400     initEvents : function(){
33401         Ext.tree.TreePanel.superclass.initEvents.call(this);
33402
33403         if(this.containerScroll){
33404             Ext.dd.ScrollManager.register(this.body);
33405         }
33406         if((this.enableDD || this.enableDrop) && !this.dropZone){
33407            
33408              this.dropZone = new Ext.tree.TreeDropZone(this, this.dropConfig || {
33409                ddGroup: this.ddGroup || 'TreeDD', appendOnly: this.ddAppendOnly === true
33410            });
33411         }
33412         if((this.enableDD || this.enableDrag) && !this.dragZone){
33413            
33414             this.dragZone = new Ext.tree.TreeDragZone(this, this.dragConfig || {
33415                ddGroup: this.ddGroup || 'TreeDD',
33416                scroll: this.ddScroll
33417            });
33418         }
33419         this.getSelectionModel().init(this);
33420     },
33421
33422     
33423     afterRender : function(){
33424         Ext.tree.TreePanel.superclass.afterRender.call(this);
33425         this.renderRoot();
33426     },
33427
33428     beforeDestroy : function(){
33429         if(this.rendered){
33430             Ext.dd.ScrollManager.unregister(this.body);
33431             Ext.destroy(this.dropZone, this.dragZone);
33432         }
33433         this.destroyRoot();
33434         Ext.destroy(this.loader);
33435         this.nodeHash = this.root = this.loader = null;
33436         Ext.tree.TreePanel.superclass.beforeDestroy.call(this);
33437     },
33438     
33439     
33440     destroyRoot : function(){
33441         if(this.root && this.root.destroy){
33442             this.root.destroy(true);
33443         }
33444     }
33445
33446     
33447     
33448     
33449     
33450     
33451     
33452     
33453     
33454     
33455     
33456     
33457     
33458     
33459     
33460     
33461     
33462     
33463     
33464     
33465     
33466     
33467     
33468     
33469     
33470     
33471     
33472     
33473     
33474     
33475     
33476     
33477
33478
33479
33480     
33481     
33482     
33483     
33484     
33485     
33486     
33487     
33488     
33489     
33490     
33491     
33492     
33493     
33494     
33495     
33496 });
33497
33498 Ext.tree.TreePanel.nodeTypes = {};
33499
33500 Ext.reg('treepanel', Ext.tree.TreePanel);Ext.tree.TreeEventModel = function(tree){
33501     this.tree = tree;
33502     this.tree.on('render', this.initEvents, this);
33503 };
33504
33505 Ext.tree.TreeEventModel.prototype = {
33506     initEvents : function(){
33507         var t = this.tree;
33508
33509         if(t.trackMouseOver !== false){
33510             t.mon(t.innerCt, {
33511                 scope: this,
33512                 mouseover: this.delegateOver,
33513                 mouseout: this.delegateOut
33514             });
33515         }
33516         t.mon(t.getTreeEl(), {
33517             scope: this,
33518             click: this.delegateClick,
33519             dblclick: this.delegateDblClick,
33520             contextmenu: this.delegateContextMenu
33521         });
33522     },
33523
33524     getNode : function(e){
33525         var t;
33526         if(t = e.getTarget('.x-tree-node-el', 10)){
33527             var id = Ext.fly(t, '_treeEvents').getAttribute('tree-node-id', 'ext');
33528             if(id){
33529                 return this.tree.getNodeById(id);
33530             }
33531         }
33532         return null;
33533     },
33534
33535     getNodeTarget : function(e){
33536         var t = e.getTarget('.x-tree-node-icon', 1);
33537         if(!t){
33538             t = e.getTarget('.x-tree-node-el', 6);
33539         }
33540         return t;
33541     },
33542
33543     delegateOut : function(e, t){
33544         if(!this.beforeEvent(e)){
33545             return;
33546         }
33547         if(e.getTarget('.x-tree-ec-icon', 1)){
33548             var n = this.getNode(e);
33549             this.onIconOut(e, n);
33550             if(n == this.lastEcOver){
33551                 delete this.lastEcOver;
33552             }
33553         }
33554         if((t = this.getNodeTarget(e)) && !e.within(t, true)){
33555             this.onNodeOut(e, this.getNode(e));
33556         }
33557     },
33558
33559     delegateOver : function(e, t){
33560         if(!this.beforeEvent(e)){
33561             return;
33562         }
33563         if(Ext.isGecko && !this.trackingDoc){ 
33564             Ext.getBody().on('mouseover', this.trackExit, this);
33565             this.trackingDoc = true;
33566         }
33567         if(this.lastEcOver){ 
33568             this.onIconOut(e, this.lastEcOver);
33569             delete this.lastEcOver;
33570         }
33571         if(e.getTarget('.x-tree-ec-icon', 1)){
33572             this.lastEcOver = this.getNode(e);
33573             this.onIconOver(e, this.lastEcOver);
33574         }
33575         if(t = this.getNodeTarget(e)){
33576             this.onNodeOver(e, this.getNode(e));
33577         }
33578     },
33579
33580     trackExit : function(e){
33581         if(this.lastOverNode){
33582             if(this.lastOverNode.ui && !e.within(this.lastOverNode.ui.getEl())){
33583                 this.onNodeOut(e, this.lastOverNode);
33584             }
33585             delete this.lastOverNode;
33586             Ext.getBody().un('mouseover', this.trackExit, this);
33587             this.trackingDoc = false;
33588         }
33589
33590     },
33591
33592     delegateClick : function(e, t){
33593         if(this.beforeEvent(e)){
33594             if(e.getTarget('input[type=checkbox]', 1)){
33595                 this.onCheckboxClick(e, this.getNode(e));
33596             }else if(e.getTarget('.x-tree-ec-icon', 1)){
33597                 this.onIconClick(e, this.getNode(e));
33598             }else if(this.getNodeTarget(e)){
33599                 this.onNodeClick(e, this.getNode(e));
33600             }
33601         }else{
33602             this.checkContainerEvent(e, 'click');
33603         }
33604     },
33605
33606     delegateDblClick : function(e, t){
33607         if(this.beforeEvent(e)){
33608             if(this.getNodeTarget(e)){
33609                 this.onNodeDblClick(e, this.getNode(e));
33610             }
33611         }else{
33612             this.checkContainerEvent(e, 'dblclick');
33613         }
33614     },
33615
33616     delegateContextMenu : function(e, t){
33617         if(this.beforeEvent(e)){
33618             if(this.getNodeTarget(e)){
33619                 this.onNodeContextMenu(e, this.getNode(e));
33620             }
33621         }else{
33622             this.checkContainerEvent(e, 'contextmenu');
33623         }
33624     },
33625     
33626     checkContainerEvent: function(e, type){
33627         if(this.disabled){
33628             e.stopEvent();
33629             return false;
33630         }
33631         this.onContainerEvent(e, type);    
33632     },
33633
33634     onContainerEvent: function(e, type){
33635         this.tree.fireEvent('container' + type, this.tree, e);
33636     },
33637
33638     onNodeClick : function(e, node){
33639         node.ui.onClick(e);
33640     },
33641
33642     onNodeOver : function(e, node){
33643         this.lastOverNode = node;
33644         node.ui.onOver(e);
33645     },
33646
33647     onNodeOut : function(e, node){
33648         node.ui.onOut(e);
33649     },
33650
33651     onIconOver : function(e, node){
33652         node.ui.addClass('x-tree-ec-over');
33653     },
33654
33655     onIconOut : function(e, node){
33656         node.ui.removeClass('x-tree-ec-over');
33657     },
33658
33659     onIconClick : function(e, node){
33660         node.ui.ecClick(e);
33661     },
33662
33663     onCheckboxClick : function(e, node){
33664         node.ui.onCheckChange(e);
33665     },
33666
33667     onNodeDblClick : function(e, node){
33668         node.ui.onDblClick(e);
33669     },
33670
33671     onNodeContextMenu : function(e, node){
33672         node.ui.onContextMenu(e);
33673     },
33674
33675     beforeEvent : function(e){
33676         var node = this.getNode(e);
33677         if(this.disabled || !node || !node.ui){
33678             e.stopEvent();
33679             return false;
33680         }
33681         return true;
33682     },
33683
33684     disable: function(){
33685         this.disabled = true;
33686     },
33687
33688     enable: function(){
33689         this.disabled = false;
33690     }
33691 };
33692 Ext.tree.DefaultSelectionModel = Ext.extend(Ext.util.Observable, {
33693     
33694     constructor : function(config){
33695         this.selNode = null;
33696    
33697         this.addEvents(
33698             
33699             'selectionchange',
33700
33701             
33702             'beforeselect'
33703         );
33704
33705         Ext.apply(this, config);
33706         Ext.tree.DefaultSelectionModel.superclass.constructor.call(this);    
33707     },
33708     
33709     init : function(tree){
33710         this.tree = tree;
33711         tree.mon(tree.getTreeEl(), 'keydown', this.onKeyDown, this);
33712         tree.on('click', this.onNodeClick, this);
33713     },
33714     
33715     onNodeClick : function(node, e){
33716         this.select(node);
33717     },
33718     
33719     
33720     select : function(node,  selectNextNode){
33721         
33722         if (!Ext.fly(node.ui.wrap).isVisible() && selectNextNode) {
33723             return selectNextNode.call(this, node);
33724         }
33725         var last = this.selNode;
33726         if(node == last){
33727             node.ui.onSelectedChange(true);
33728         }else if(this.fireEvent('beforeselect', this, node, last) !== false){
33729             if(last && last.ui){
33730                 last.ui.onSelectedChange(false);
33731             }
33732             this.selNode = node;
33733             node.ui.onSelectedChange(true);
33734             this.fireEvent('selectionchange', this, node, last);
33735         }
33736         return node;
33737     },
33738     
33739     
33740     unselect : function(node, silent){
33741         if(this.selNode == node){
33742             this.clearSelections(silent);
33743         }    
33744     },
33745     
33746     
33747     clearSelections : function(silent){
33748         var n = this.selNode;
33749         if(n){
33750             n.ui.onSelectedChange(false);
33751             this.selNode = null;
33752             if(silent !== true){
33753                 this.fireEvent('selectionchange', this, null);
33754             }
33755         }
33756         return n;
33757     },
33758     
33759     
33760     getSelectedNode : function(){
33761         return this.selNode;    
33762     },
33763     
33764     
33765     isSelected : function(node){
33766         return this.selNode == node;  
33767     },
33768
33769     
33770     selectPrevious : function( s){
33771         if(!(s = s || this.selNode || this.lastSelNode)){
33772             return null;
33773         }
33774         
33775         var ps = s.previousSibling;
33776         if(ps){
33777             if(!ps.isExpanded() || ps.childNodes.length < 1){
33778                 return this.select(ps, this.selectPrevious);
33779             } else{
33780                 var lc = ps.lastChild;
33781                 while(lc && lc.isExpanded() && Ext.fly(lc.ui.wrap).isVisible() && lc.childNodes.length > 0){
33782                     lc = lc.lastChild;
33783                 }
33784                 return this.select(lc, this.selectPrevious);
33785             }
33786         } else if(s.parentNode && (this.tree.rootVisible || !s.parentNode.isRoot)){
33787             return this.select(s.parentNode, this.selectPrevious);
33788         }
33789         return null;
33790     },
33791
33792     
33793     selectNext : function( s){
33794         if(!(s = s || this.selNode || this.lastSelNode)){
33795             return null;
33796         }
33797         
33798         if(s.firstChild && s.isExpanded() && Ext.fly(s.ui.wrap).isVisible()){
33799              return this.select(s.firstChild, this.selectNext);
33800          }else if(s.nextSibling){
33801              return this.select(s.nextSibling, this.selectNext);
33802          }else if(s.parentNode){
33803             var newS = null;
33804             s.parentNode.bubble(function(){
33805                 if(this.nextSibling){
33806                     newS = this.getOwnerTree().selModel.select(this.nextSibling, this.selectNext);
33807                     return false;
33808                 }
33809             });
33810             return newS;
33811          }
33812         return null;
33813     },
33814
33815     onKeyDown : function(e){
33816         var s = this.selNode || this.lastSelNode;
33817         
33818         var sm = this;
33819         if(!s){
33820             return;
33821         }
33822         var k = e.getKey();
33823         switch(k){
33824              case e.DOWN:
33825                  e.stopEvent();
33826                  this.selectNext();
33827              break;
33828              case e.UP:
33829                  e.stopEvent();
33830                  this.selectPrevious();
33831              break;
33832              case e.RIGHT:
33833                  e.preventDefault();
33834                  if(s.hasChildNodes()){
33835                      if(!s.isExpanded()){
33836                          s.expand();
33837                      }else if(s.firstChild){
33838                          this.select(s.firstChild, e);
33839                      }
33840                  }
33841              break;
33842              case e.LEFT:
33843                  e.preventDefault();
33844                  if(s.hasChildNodes() && s.isExpanded()){
33845                      s.collapse();
33846                  }else if(s.parentNode && (this.tree.rootVisible || s.parentNode != this.tree.getRootNode())){
33847                      this.select(s.parentNode, e);
33848                  }
33849              break;
33850         };
33851     }
33852 });
33853
33854
33855 Ext.tree.MultiSelectionModel = Ext.extend(Ext.util.Observable, {
33856     
33857     constructor : function(config){
33858         this.selNodes = [];
33859         this.selMap = {};
33860         this.addEvents(
33861             
33862             'selectionchange'
33863         );
33864         Ext.apply(this, config);
33865         Ext.tree.MultiSelectionModel.superclass.constructor.call(this);    
33866     },
33867     
33868     init : function(tree){
33869         this.tree = tree;
33870         tree.mon(tree.getTreeEl(), 'keydown', this.onKeyDown, this);
33871         tree.on('click', this.onNodeClick, this);
33872     },
33873     
33874     onNodeClick : function(node, e){
33875         if(e.ctrlKey && this.isSelected(node)){
33876             this.unselect(node);
33877         }else{
33878             this.select(node, e, e.ctrlKey);
33879         }
33880     },
33881     
33882     
33883     select : function(node, e, keepExisting){
33884         if(keepExisting !== true){
33885             this.clearSelections(true);
33886         }
33887         if(this.isSelected(node)){
33888             this.lastSelNode = node;
33889             return node;
33890         }
33891         this.selNodes.push(node);
33892         this.selMap[node.id] = node;
33893         this.lastSelNode = node;
33894         node.ui.onSelectedChange(true);
33895         this.fireEvent('selectionchange', this, this.selNodes);
33896         return node;
33897     },
33898     
33899     
33900     unselect : function(node){
33901         if(this.selMap[node.id]){
33902             node.ui.onSelectedChange(false);
33903             var sn = this.selNodes;
33904             var index = sn.indexOf(node);
33905             if(index != -1){
33906                 this.selNodes.splice(index, 1);
33907             }
33908             delete this.selMap[node.id];
33909             this.fireEvent('selectionchange', this, this.selNodes);
33910         }
33911     },
33912     
33913     
33914     clearSelections : function(suppressEvent){
33915         var sn = this.selNodes;
33916         if(sn.length > 0){
33917             for(var i = 0, len = sn.length; i < len; i++){
33918                 sn[i].ui.onSelectedChange(false);
33919             }
33920             this.selNodes = [];
33921             this.selMap = {};
33922             if(suppressEvent !== true){
33923                 this.fireEvent('selectionchange', this, this.selNodes);
33924             }
33925         }
33926     },
33927     
33928     
33929     isSelected : function(node){
33930         return this.selMap[node.id] ? true : false;  
33931     },
33932     
33933     
33934     getSelectedNodes : function(){
33935         return this.selNodes.concat([]);
33936     },
33937
33938     onKeyDown : Ext.tree.DefaultSelectionModel.prototype.onKeyDown,
33939
33940     selectNext : Ext.tree.DefaultSelectionModel.prototype.selectNext,
33941
33942     selectPrevious : Ext.tree.DefaultSelectionModel.prototype.selectPrevious
33943 });
33944 Ext.data.Tree = Ext.extend(Ext.util.Observable, {
33945     
33946     constructor: function(root){
33947         this.nodeHash = {};
33948         
33949         this.root = null;
33950         if(root){
33951             this.setRootNode(root);
33952         }
33953         this.addEvents(
33954             
33955             "append",
33956             
33957             "remove",
33958             
33959             "move",
33960             
33961             "insert",
33962             
33963             "beforeappend",
33964             
33965             "beforeremove",
33966             
33967             "beforemove",
33968             
33969             "beforeinsert"
33970         );
33971         Ext.data.Tree.superclass.constructor.call(this);        
33972     },
33973     
33974     
33975     pathSeparator: "/",
33976
33977     
33978     proxyNodeEvent : function(){
33979         return this.fireEvent.apply(this, arguments);
33980     },
33981
33982     
33983     getRootNode : function(){
33984         return this.root;
33985     },
33986
33987     
33988     setRootNode : function(node){
33989         this.root = node;
33990         node.ownerTree = this;
33991         node.isRoot = true;
33992         this.registerNode(node);
33993         return node;
33994     },
33995
33996     
33997     getNodeById : function(id){
33998         return this.nodeHash[id];
33999     },
34000
34001     
34002     registerNode : function(node){
34003         this.nodeHash[node.id] = node;
34004     },
34005
34006     
34007     unregisterNode : function(node){
34008         delete this.nodeHash[node.id];
34009     },
34010
34011     toString : function(){
34012         return "[Tree"+(this.id?" "+this.id:"")+"]";
34013     }
34014 });
34015
34016
34017 Ext.data.Node = Ext.extend(Ext.util.Observable, {
34018     
34019     constructor: function(attributes){
34020         
34021         this.attributes = attributes || {};
34022         this.leaf = this.attributes.leaf;
34023         
34024         this.id = this.attributes.id;
34025         if(!this.id){
34026             this.id = Ext.id(null, "xnode-");
34027             this.attributes.id = this.id;
34028         }
34029         
34030         this.childNodes = [];
34031         
34032         this.parentNode = null;
34033         
34034         this.firstChild = null;
34035         
34036         this.lastChild = null;
34037         
34038         this.previousSibling = null;
34039         
34040         this.nextSibling = null;
34041
34042         this.addEvents({
34043             
34044             "append" : true,
34045             
34046             "remove" : true,
34047             
34048             "move" : true,
34049             
34050             "insert" : true,
34051             
34052             "beforeappend" : true,
34053             
34054             "beforeremove" : true,
34055             
34056             "beforemove" : true,
34057              
34058             "beforeinsert" : true
34059         });
34060         this.listeners = this.attributes.listeners;
34061         Ext.data.Node.superclass.constructor.call(this);    
34062     },
34063     
34064     
34065     fireEvent : function(evtName){
34066         
34067         if(Ext.data.Node.superclass.fireEvent.apply(this, arguments) === false){
34068             return false;
34069         }
34070         
34071         var ot = this.getOwnerTree();
34072         if(ot){
34073             if(ot.proxyNodeEvent.apply(ot, arguments) === false){
34074                 return false;
34075             }
34076         }
34077         return true;
34078     },
34079
34080     
34081     isLeaf : function(){
34082         return this.leaf === true;
34083     },
34084
34085     
34086     setFirstChild : function(node){
34087         this.firstChild = node;
34088     },
34089
34090     
34091     setLastChild : function(node){
34092         this.lastChild = node;
34093     },
34094
34095
34096     
34097     isLast : function(){
34098        return (!this.parentNode ? true : this.parentNode.lastChild == this);
34099     },
34100
34101     
34102     isFirst : function(){
34103        return (!this.parentNode ? true : this.parentNode.firstChild == this);
34104     },
34105
34106     
34107     hasChildNodes : function(){
34108         return !this.isLeaf() && this.childNodes.length > 0;
34109     },
34110
34111     
34112     isExpandable : function(){
34113         return this.attributes.expandable || this.hasChildNodes();
34114     },
34115
34116     
34117     appendChild : function(node){
34118         var multi = false;
34119         if(Ext.isArray(node)){
34120             multi = node;
34121         }else if(arguments.length > 1){
34122             multi = arguments;
34123         }
34124         
34125         if(multi){
34126             for(var i = 0, len = multi.length; i < len; i++) {
34127                 this.appendChild(multi[i]);
34128             }
34129         }else{
34130             if(this.fireEvent("beforeappend", this.ownerTree, this, node) === false){
34131                 return false;
34132             }
34133             var index = this.childNodes.length;
34134             var oldParent = node.parentNode;
34135             
34136             if(oldParent){
34137                 if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index) === false){
34138                     return false;
34139                 }
34140                 oldParent.removeChild(node);
34141             }
34142             index = this.childNodes.length;
34143             if(index === 0){
34144                 this.setFirstChild(node);
34145             }
34146             this.childNodes.push(node);
34147             node.parentNode = this;
34148             var ps = this.childNodes[index-1];
34149             if(ps){
34150                 node.previousSibling = ps;
34151                 ps.nextSibling = node;
34152             }else{
34153                 node.previousSibling = null;
34154             }
34155             node.nextSibling = null;
34156             this.setLastChild(node);
34157             node.setOwnerTree(this.getOwnerTree());
34158             this.fireEvent("append", this.ownerTree, this, node, index);
34159             if(oldParent){
34160                 node.fireEvent("move", this.ownerTree, node, oldParent, this, index);
34161             }
34162             return node;
34163         }
34164     },
34165
34166     
34167     removeChild : function(node, destroy){
34168         var index = this.childNodes.indexOf(node);
34169         if(index == -1){
34170             return false;
34171         }
34172         if(this.fireEvent("beforeremove", this.ownerTree, this, node) === false){
34173             return false;
34174         }
34175
34176         
34177         this.childNodes.splice(index, 1);
34178
34179         
34180         if(node.previousSibling){
34181             node.previousSibling.nextSibling = node.nextSibling;
34182         }
34183         if(node.nextSibling){
34184             node.nextSibling.previousSibling = node.previousSibling;
34185         }
34186
34187         
34188         if(this.firstChild == node){
34189             this.setFirstChild(node.nextSibling);
34190         }
34191         if(this.lastChild == node){
34192             this.setLastChild(node.previousSibling);
34193         }
34194
34195         this.fireEvent("remove", this.ownerTree, this, node);
34196         if(destroy){
34197             node.destroy(true);
34198         }else{
34199             node.clear();
34200         }
34201         return node;
34202     },
34203
34204     
34205     clear : function(destroy){
34206         
34207         this.setOwnerTree(null, destroy);
34208         this.parentNode = this.previousSibling = this.nextSibling = null;
34209         if(destroy){
34210             this.firstChild = this.lastChild = null;
34211         }
34212     },
34213
34214     
34215     destroy : function( silent){
34216         
34217         if(silent === true){
34218             this.purgeListeners();
34219             this.clear(true);
34220             Ext.each(this.childNodes, function(n){
34221                 n.destroy(true);
34222             });
34223             this.childNodes = null;
34224         }else{
34225             this.remove(true);
34226         }
34227     },
34228
34229     
34230     insertBefore : function(node, refNode){
34231         if(!refNode){ 
34232             return this.appendChild(node);
34233         }
34234         
34235         if(node == refNode){
34236             return false;
34237         }
34238
34239         if(this.fireEvent("beforeinsert", this.ownerTree, this, node, refNode) === false){
34240             return false;
34241         }
34242         var index = this.childNodes.indexOf(refNode);
34243         var oldParent = node.parentNode;
34244         var refIndex = index;
34245
34246         
34247         if(oldParent == this && this.childNodes.indexOf(node) < index){
34248             refIndex--;
34249         }
34250
34251         
34252         if(oldParent){
34253             if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index, refNode) === false){
34254                 return false;
34255             }
34256             oldParent.removeChild(node);
34257         }
34258         if(refIndex === 0){
34259             this.setFirstChild(node);
34260         }
34261         this.childNodes.splice(refIndex, 0, node);
34262         node.parentNode = this;
34263         var ps = this.childNodes[refIndex-1];
34264         if(ps){
34265             node.previousSibling = ps;
34266             ps.nextSibling = node;
34267         }else{
34268             node.previousSibling = null;
34269         }
34270         node.nextSibling = refNode;
34271         refNode.previousSibling = node;
34272         node.setOwnerTree(this.getOwnerTree());
34273         this.fireEvent("insert", this.ownerTree, this, node, refNode);
34274         if(oldParent){
34275             node.fireEvent("move", this.ownerTree, node, oldParent, this, refIndex, refNode);
34276         }
34277         return node;
34278     },
34279
34280     
34281     remove : function(destroy){
34282         if (this.parentNode) {
34283             this.parentNode.removeChild(this, destroy);
34284         }
34285         return this;
34286     },
34287
34288     
34289     removeAll : function(destroy){
34290         var cn = this.childNodes,
34291             n;
34292         while((n = cn[0])){
34293             this.removeChild(n, destroy);
34294         }
34295         return this;
34296     },
34297
34298     
34299     item : function(index){
34300         return this.childNodes[index];
34301     },
34302
34303     
34304     replaceChild : function(newChild, oldChild){
34305         var s = oldChild ? oldChild.nextSibling : null;
34306         this.removeChild(oldChild);
34307         this.insertBefore(newChild, s);
34308         return oldChild;
34309     },
34310
34311     
34312     indexOf : function(child){
34313         return this.childNodes.indexOf(child);
34314     },
34315
34316     
34317     getOwnerTree : function(){
34318         
34319         if(!this.ownerTree){
34320             var p = this;
34321             while(p){
34322                 if(p.ownerTree){
34323                     this.ownerTree = p.ownerTree;
34324                     break;
34325                 }
34326                 p = p.parentNode;
34327             }
34328         }
34329         return this.ownerTree;
34330     },
34331
34332     
34333     getDepth : function(){
34334         var depth = 0;
34335         var p = this;
34336         while(p.parentNode){
34337             ++depth;
34338             p = p.parentNode;
34339         }
34340         return depth;
34341     },
34342
34343     
34344     setOwnerTree : function(tree, destroy){
34345         
34346         if(tree != this.ownerTree){
34347             if(this.ownerTree){
34348                 this.ownerTree.unregisterNode(this);
34349             }
34350             this.ownerTree = tree;
34351             
34352             if(destroy !== true){
34353                 Ext.each(this.childNodes, function(n){
34354                     n.setOwnerTree(tree);
34355                 });
34356             }
34357             if(tree){
34358                 tree.registerNode(this);
34359             }
34360         }
34361     },
34362
34363     
34364     setId: function(id){
34365         if(id !== this.id){
34366             var t = this.ownerTree;
34367             if(t){
34368                 t.unregisterNode(this);
34369             }
34370             this.id = this.attributes.id = id;
34371             if(t){
34372                 t.registerNode(this);
34373             }
34374             this.onIdChange(id);
34375         }
34376     },
34377
34378     
34379     onIdChange: Ext.emptyFn,
34380
34381     
34382     getPath : function(attr){
34383         attr = attr || "id";
34384         var p = this.parentNode;
34385         var b = [this.attributes[attr]];
34386         while(p){
34387             b.unshift(p.attributes[attr]);
34388             p = p.parentNode;
34389         }
34390         var sep = this.getOwnerTree().pathSeparator;
34391         return sep + b.join(sep);
34392     },
34393
34394     
34395     bubble : function(fn, scope, args){
34396         var p = this;
34397         while(p){
34398             if(fn.apply(scope || p, args || [p]) === false){
34399                 break;
34400             }
34401             p = p.parentNode;
34402         }
34403     },
34404
34405     
34406     cascade : function(fn, scope, args){
34407         if(fn.apply(scope || this, args || [this]) !== false){
34408             var cs = this.childNodes;
34409             for(var i = 0, len = cs.length; i < len; i++) {
34410                 cs[i].cascade(fn, scope, args);
34411             }
34412         }
34413     },
34414
34415     
34416     eachChild : function(fn, scope, args){
34417         var cs = this.childNodes;
34418         for(var i = 0, len = cs.length; i < len; i++) {
34419             if(fn.apply(scope || cs[i], args || [cs[i]]) === false){
34420                 break;
34421             }
34422         }
34423     },
34424
34425     
34426     findChild : function(attribute, value, deep){
34427         return this.findChildBy(function(){
34428             return this.attributes[attribute] == value;
34429         }, null, deep);
34430     },
34431
34432     
34433     findChildBy : function(fn, scope, deep){
34434         var cs = this.childNodes,
34435             len = cs.length,
34436             i = 0,
34437             n,
34438             res;
34439         for(; i < len; i++){
34440             n = cs[i];
34441             if(fn.call(scope || n, n) === true){
34442                 return n;
34443             }else if (deep){
34444                 res = n.findChildBy(fn, scope, deep);
34445                 if(res != null){
34446                     return res;
34447                 }
34448             }
34449             
34450         }
34451         return null;
34452     },
34453
34454     
34455     sort : function(fn, scope){
34456         var cs = this.childNodes;
34457         var len = cs.length;
34458         if(len > 0){
34459             var sortFn = scope ? function(){fn.apply(scope, arguments);} : fn;
34460             cs.sort(sortFn);
34461             for(var i = 0; i < len; i++){
34462                 var n = cs[i];
34463                 n.previousSibling = cs[i-1];
34464                 n.nextSibling = cs[i+1];
34465                 if(i === 0){
34466                     this.setFirstChild(n);
34467                 }
34468                 if(i == len-1){
34469                     this.setLastChild(n);
34470                 }
34471             }
34472         }
34473     },
34474
34475     
34476     contains : function(node){
34477         return node.isAncestor(this);
34478     },
34479
34480     
34481     isAncestor : function(node){
34482         var p = this.parentNode;
34483         while(p){
34484             if(p == node){
34485                 return true;
34486             }
34487             p = p.parentNode;
34488         }
34489         return false;
34490     },
34491
34492     toString : function(){
34493         return "[Node"+(this.id?" "+this.id:"")+"]";
34494     }
34495 });
34496 Ext.tree.TreeNode = Ext.extend(Ext.data.Node, {
34497     
34498     constructor : function(attributes){
34499         attributes = attributes || {};
34500         if(Ext.isString(attributes)){
34501             attributes = {text: attributes};
34502         }
34503         this.childrenRendered = false;
34504         this.rendered = false;
34505         Ext.tree.TreeNode.superclass.constructor.call(this, attributes);
34506         this.expanded = attributes.expanded === true;
34507         this.isTarget = attributes.isTarget !== false;
34508         this.draggable = attributes.draggable !== false && attributes.allowDrag !== false;
34509         this.allowChildren = attributes.allowChildren !== false && attributes.allowDrop !== false;
34510
34511         
34512         this.text = attributes.text;
34513         
34514         this.disabled = attributes.disabled === true;
34515         
34516         this.hidden = attributes.hidden === true;
34517     
34518         this.addEvents(
34519             
34520             'textchange',
34521             
34522             'beforeexpand',
34523             
34524             'beforecollapse',
34525             
34526             'expand',
34527             
34528             'disabledchange',
34529             
34530             'collapse',
34531             
34532             'beforeclick',
34533             
34534             'click',
34535             
34536             'checkchange',
34537             
34538             'beforedblclick',
34539             
34540             'dblclick',
34541             
34542             'contextmenu',
34543             
34544             'beforechildrenrendered'
34545         );
34546     
34547         var uiClass = this.attributes.uiProvider || this.defaultUI || Ext.tree.TreeNodeUI;
34548     
34549         
34550         this.ui = new uiClass(this);    
34551     },
34552     
34553     preventHScroll : true,
34554     
34555     isExpanded : function(){
34556         return this.expanded;
34557     },
34558
34559
34560     getUI : function(){
34561         return this.ui;
34562     },
34563
34564     getLoader : function(){
34565         var owner;
34566         return this.loader || ((owner = this.getOwnerTree()) && owner.loader ? owner.loader : (this.loader = new Ext.tree.TreeLoader()));
34567     },
34568
34569     
34570     setFirstChild : function(node){
34571         var of = this.firstChild;
34572         Ext.tree.TreeNode.superclass.setFirstChild.call(this, node);
34573         if(this.childrenRendered && of && node != of){
34574             of.renderIndent(true, true);
34575         }
34576         if(this.rendered){
34577             this.renderIndent(true, true);
34578         }
34579     },
34580
34581     
34582     setLastChild : function(node){
34583         var ol = this.lastChild;
34584         Ext.tree.TreeNode.superclass.setLastChild.call(this, node);
34585         if(this.childrenRendered && ol && node != ol){
34586             ol.renderIndent(true, true);
34587         }
34588         if(this.rendered){
34589             this.renderIndent(true, true);
34590         }
34591     },
34592
34593     
34594     
34595     appendChild : function(n){
34596         if(!n.render && !Ext.isArray(n)){
34597             n = this.getLoader().createNode(n);
34598         }
34599         var node = Ext.tree.TreeNode.superclass.appendChild.call(this, n);
34600         if(node && this.childrenRendered){
34601             node.render();
34602         }
34603         this.ui.updateExpandIcon();
34604         return node;
34605     },
34606
34607     
34608     removeChild : function(node, destroy){
34609         this.ownerTree.getSelectionModel().unselect(node);
34610         Ext.tree.TreeNode.superclass.removeChild.apply(this, arguments);
34611         
34612         if(!destroy){
34613             var rendered = node.ui.rendered;
34614             
34615             if(rendered){
34616                 node.ui.remove();
34617             }
34618             if(rendered && this.childNodes.length < 1){
34619                 this.collapse(false, false);
34620             }else{
34621                 this.ui.updateExpandIcon();
34622             }
34623             if(!this.firstChild && !this.isHiddenRoot()){
34624                 this.childrenRendered = false;
34625             }
34626         }
34627         return node;
34628     },
34629
34630     
34631     insertBefore : function(node, refNode){
34632         if(!node.render){
34633             node = this.getLoader().createNode(node);
34634         }
34635         var newNode = Ext.tree.TreeNode.superclass.insertBefore.call(this, node, refNode);
34636         if(newNode && refNode && this.childrenRendered){
34637             node.render();
34638         }
34639         this.ui.updateExpandIcon();
34640         return newNode;
34641     },
34642
34643     
34644     setText : function(text){
34645         var oldText = this.text;
34646         this.text = this.attributes.text = text;
34647         if(this.rendered){ 
34648             this.ui.onTextChange(this, text, oldText);
34649         }
34650         this.fireEvent('textchange', this, text, oldText);
34651     },
34652     
34653     
34654     setIconCls : function(cls){
34655         var old = this.attributes.iconCls;
34656         this.attributes.iconCls = cls;
34657         if(this.rendered){
34658             this.ui.onIconClsChange(this, cls, old);
34659         }
34660     },
34661     
34662     
34663     setTooltip : function(tip, title){
34664         this.attributes.qtip = tip;
34665         this.attributes.qtipTitle = title;
34666         if(this.rendered){
34667             this.ui.onTipChange(this, tip, title);
34668         }
34669     },
34670     
34671     
34672     setIcon : function(icon){
34673         this.attributes.icon = icon;
34674         if(this.rendered){
34675             this.ui.onIconChange(this, icon);
34676         }
34677     },
34678     
34679     
34680     setHref : function(href, target){
34681         this.attributes.href = href;
34682         this.attributes.hrefTarget = target;
34683         if(this.rendered){
34684             this.ui.onHrefChange(this, href, target);
34685         }
34686     },
34687     
34688     
34689     setCls : function(cls){
34690         var old = this.attributes.cls;
34691         this.attributes.cls = cls;
34692         if(this.rendered){
34693             this.ui.onClsChange(this, cls, old);
34694         }
34695     },
34696
34697     
34698     select : function(){
34699         var t = this.getOwnerTree();
34700         if(t){
34701             t.getSelectionModel().select(this);
34702         }
34703     },
34704
34705     
34706     unselect : function(silent){
34707         var t = this.getOwnerTree();
34708         if(t){
34709             t.getSelectionModel().unselect(this, silent);
34710         }
34711     },
34712
34713     
34714     isSelected : function(){
34715         var t = this.getOwnerTree();
34716         return t ? t.getSelectionModel().isSelected(this) : false;
34717     },
34718
34719     
34720     expand : function(deep, anim, callback, scope){
34721         if(!this.expanded){
34722             if(this.fireEvent('beforeexpand', this, deep, anim) === false){
34723                 return;
34724             }
34725             if(!this.childrenRendered){
34726                 this.renderChildren();
34727             }
34728             this.expanded = true;
34729             if(!this.isHiddenRoot() && (this.getOwnerTree().animate && anim !== false) || anim){
34730                 this.ui.animExpand(function(){
34731                     this.fireEvent('expand', this);
34732                     this.runCallback(callback, scope || this, [this]);
34733                     if(deep === true){
34734                         this.expandChildNodes(true, true);
34735                     }
34736                 }.createDelegate(this));
34737                 return;
34738             }else{
34739                 this.ui.expand();
34740                 this.fireEvent('expand', this);
34741                 this.runCallback(callback, scope || this, [this]);
34742             }
34743         }else{
34744            this.runCallback(callback, scope || this, [this]);
34745         }
34746         if(deep === true){
34747             this.expandChildNodes(true);
34748         }
34749     },
34750
34751     runCallback : function(cb, scope, args){
34752         if(Ext.isFunction(cb)){
34753             cb.apply(scope, args);
34754         }
34755     },
34756
34757     isHiddenRoot : function(){
34758         return this.isRoot && !this.getOwnerTree().rootVisible;
34759     },
34760
34761     
34762     collapse : function(deep, anim, callback, scope){
34763         if(this.expanded && !this.isHiddenRoot()){
34764             if(this.fireEvent('beforecollapse', this, deep, anim) === false){
34765                 return;
34766             }
34767             this.expanded = false;
34768             if((this.getOwnerTree().animate && anim !== false) || anim){
34769                 this.ui.animCollapse(function(){
34770                     this.fireEvent('collapse', this);
34771                     this.runCallback(callback, scope || this, [this]);
34772                     if(deep === true){
34773                         this.collapseChildNodes(true);
34774                     }
34775                 }.createDelegate(this));
34776                 return;
34777             }else{
34778                 this.ui.collapse();
34779                 this.fireEvent('collapse', this);
34780                 this.runCallback(callback, scope || this, [this]);
34781             }
34782         }else if(!this.expanded){
34783             this.runCallback(callback, scope || this, [this]);
34784         }
34785         if(deep === true){
34786             var cs = this.childNodes;
34787             for(var i = 0, len = cs.length; i < len; i++) {
34788                 cs[i].collapse(true, false);
34789             }
34790         }
34791     },
34792
34793     
34794     delayedExpand : function(delay){
34795         if(!this.expandProcId){
34796             this.expandProcId = this.expand.defer(delay, this);
34797         }
34798     },
34799
34800     
34801     cancelExpand : function(){
34802         if(this.expandProcId){
34803             clearTimeout(this.expandProcId);
34804         }
34805         this.expandProcId = false;
34806     },
34807
34808     
34809     toggle : function(){
34810         if(this.expanded){
34811             this.collapse();
34812         }else{
34813             this.expand();
34814         }
34815     },
34816
34817     
34818     ensureVisible : function(callback, scope){
34819         var tree = this.getOwnerTree();
34820         tree.expandPath(this.parentNode ? this.parentNode.getPath() : this.getPath(), false, function(){
34821             var node = tree.getNodeById(this.id);  
34822             tree.getTreeEl().scrollChildIntoView(node.ui.anchor);
34823             this.runCallback(callback, scope || this, [this]);
34824         }.createDelegate(this));
34825     },
34826
34827     
34828     expandChildNodes : function(deep, anim) {
34829         var cs = this.childNodes,
34830             i,
34831             len = cs.length;
34832         for (i = 0; i < len; i++) {
34833                 cs[i].expand(deep, anim);
34834         }
34835     },
34836
34837     
34838     collapseChildNodes : function(deep){
34839         var cs = this.childNodes;
34840         for(var i = 0, len = cs.length; i < len; i++) {
34841                 cs[i].collapse(deep);
34842         }
34843     },
34844
34845     
34846     disable : function(){
34847         this.disabled = true;
34848         this.unselect();
34849         if(this.rendered && this.ui.onDisableChange){ 
34850             this.ui.onDisableChange(this, true);
34851         }
34852         this.fireEvent('disabledchange', this, true);
34853     },
34854
34855     
34856     enable : function(){
34857         this.disabled = false;
34858         if(this.rendered && this.ui.onDisableChange){ 
34859             this.ui.onDisableChange(this, false);
34860         }
34861         this.fireEvent('disabledchange', this, false);
34862     },
34863
34864     
34865     renderChildren : function(suppressEvent){
34866         if(suppressEvent !== false){
34867             this.fireEvent('beforechildrenrendered', this);
34868         }
34869         var cs = this.childNodes;
34870         for(var i = 0, len = cs.length; i < len; i++){
34871             cs[i].render(true);
34872         }
34873         this.childrenRendered = true;
34874     },
34875
34876     
34877     sort : function(fn, scope){
34878         Ext.tree.TreeNode.superclass.sort.apply(this, arguments);
34879         if(this.childrenRendered){
34880             var cs = this.childNodes;
34881             for(var i = 0, len = cs.length; i < len; i++){
34882                 cs[i].render(true);
34883             }
34884         }
34885     },
34886
34887     
34888     render : function(bulkRender){
34889         this.ui.render(bulkRender);
34890         if(!this.rendered){
34891             
34892             this.getOwnerTree().registerNode(this);
34893             this.rendered = true;
34894             if(this.expanded){
34895                 this.expanded = false;
34896                 this.expand(false, false);
34897             }
34898         }
34899     },
34900
34901     
34902     renderIndent : function(deep, refresh){
34903         if(refresh){
34904             this.ui.childIndent = null;
34905         }
34906         this.ui.renderIndent();
34907         if(deep === true && this.childrenRendered){
34908             var cs = this.childNodes;
34909             for(var i = 0, len = cs.length; i < len; i++){
34910                 cs[i].renderIndent(true, refresh);
34911             }
34912         }
34913     },
34914
34915     beginUpdate : function(){
34916         this.childrenRendered = false;
34917     },
34918
34919     endUpdate : function(){
34920         if(this.expanded && this.rendered){
34921             this.renderChildren();
34922         }
34923     },
34924
34925     
34926     destroy : function(silent){
34927         if(silent === true){
34928             this.unselect(true);
34929         }
34930         Ext.tree.TreeNode.superclass.destroy.call(this, silent);
34931         Ext.destroy(this.ui, this.loader);
34932         this.ui = this.loader = null;
34933     },
34934
34935     
34936     onIdChange : function(id){
34937         this.ui.onIdChange(id);
34938     }
34939 });
34940
34941 Ext.tree.TreePanel.nodeTypes.node = Ext.tree.TreeNode;
34942  Ext.tree.AsyncTreeNode = function(config){
34943     this.loaded = config && config.loaded === true;
34944     this.loading = false;
34945     Ext.tree.AsyncTreeNode.superclass.constructor.apply(this, arguments);
34946     
34947     this.addEvents('beforeload', 'load');
34948     
34949     
34950 };
34951 Ext.extend(Ext.tree.AsyncTreeNode, Ext.tree.TreeNode, {
34952     expand : function(deep, anim, callback, scope){
34953         if(this.loading){ 
34954             var timer;
34955             var f = function(){
34956                 if(!this.loading){ 
34957                     clearInterval(timer);
34958                     this.expand(deep, anim, callback, scope);
34959                 }
34960             }.createDelegate(this);
34961             timer = setInterval(f, 200);
34962             return;
34963         }
34964         if(!this.loaded){
34965             if(this.fireEvent("beforeload", this) === false){
34966                 return;
34967             }
34968             this.loading = true;
34969             this.ui.beforeLoad(this);
34970             var loader = this.loader || this.attributes.loader || this.getOwnerTree().getLoader();
34971             if(loader){
34972                 loader.load(this, this.loadComplete.createDelegate(this, [deep, anim, callback, scope]), this);
34973                 return;
34974             }
34975         }
34976         Ext.tree.AsyncTreeNode.superclass.expand.call(this, deep, anim, callback, scope);
34977     },
34978     
34979     
34980     isLoading : function(){
34981         return this.loading;  
34982     },
34983     
34984     loadComplete : function(deep, anim, callback, scope){
34985         this.loading = false;
34986         this.loaded = true;
34987         this.ui.afterLoad(this);
34988         this.fireEvent("load", this);
34989         this.expand(deep, anim, callback, scope);
34990     },
34991     
34992     
34993     isLoaded : function(){
34994         return this.loaded;
34995     },
34996     
34997     hasChildNodes : function(){
34998         if(!this.isLeaf() && !this.loaded){
34999             return true;
35000         }else{
35001             return Ext.tree.AsyncTreeNode.superclass.hasChildNodes.call(this);
35002         }
35003     },
35004
35005     
35006     reload : function(callback, scope){
35007         this.collapse(false, false);
35008         while(this.firstChild){
35009             this.removeChild(this.firstChild).destroy();
35010         }
35011         this.childrenRendered = false;
35012         this.loaded = false;
35013         if(this.isHiddenRoot()){
35014             this.expanded = false;
35015         }
35016         this.expand(false, false, callback, scope);
35017     }
35018 });
35019
35020 Ext.tree.TreePanel.nodeTypes.async = Ext.tree.AsyncTreeNode;
35021 Ext.tree.TreeNodeUI = Ext.extend(Object, {
35022     
35023     constructor : function(node){
35024         Ext.apply(this, {
35025             node: node,
35026             rendered: false,
35027             animating: false,
35028             wasLeaf: true,
35029             ecc: 'x-tree-ec-icon x-tree-elbow',
35030             emptyIcon: Ext.BLANK_IMAGE_URL    
35031         });
35032     },
35033     
35034     
35035     removeChild : function(node){
35036         if(this.rendered){
35037             this.ctNode.removeChild(node.ui.getEl());
35038         }
35039     },
35040
35041     
35042     beforeLoad : function(){
35043          this.addClass("x-tree-node-loading");
35044     },
35045
35046     
35047     afterLoad : function(){
35048          this.removeClass("x-tree-node-loading");
35049     },
35050
35051     
35052     onTextChange : function(node, text, oldText){
35053         if(this.rendered){
35054             this.textNode.innerHTML = text;
35055         }
35056     },
35057     
35058     
35059     onIconClsChange : function(node, cls, oldCls){
35060         if(this.rendered){
35061             Ext.fly(this.iconNode).replaceClass(oldCls, cls);
35062         }
35063     },
35064     
35065     
35066     onIconChange : function(node, icon){
35067         if(this.rendered){
35068             
35069             var empty = Ext.isEmpty(icon);
35070             this.iconNode.src = empty ? this.emptyIcon : icon;
35071             Ext.fly(this.iconNode)[empty ? 'removeClass' : 'addClass']('x-tree-node-inline-icon');
35072         }
35073     },
35074     
35075     
35076     onTipChange : function(node, tip, title){
35077         if(this.rendered){
35078             var hasTitle = Ext.isDefined(title);
35079             if(this.textNode.setAttributeNS){
35080                 this.textNode.setAttributeNS("ext", "qtip", tip);
35081                 if(hasTitle){
35082                     this.textNode.setAttributeNS("ext", "qtitle", title);
35083                 }
35084             }else{
35085                 this.textNode.setAttribute("ext:qtip", tip);
35086                 if(hasTitle){
35087                     this.textNode.setAttribute("ext:qtitle", title);
35088                 }
35089             }
35090         }
35091     },
35092     
35093     
35094     onHrefChange : function(node, href, target){
35095         if(this.rendered){
35096             this.anchor.href = this.getHref(href);
35097             if(Ext.isDefined(target)){
35098                 this.anchor.target = target;
35099             }
35100         }
35101     },
35102     
35103     
35104     onClsChange : function(node, cls, oldCls){
35105         if(this.rendered){
35106             Ext.fly(this.elNode).replaceClass(oldCls, cls);
35107         }    
35108     },
35109
35110     
35111     onDisableChange : function(node, state){
35112         this.disabled = state;
35113         if (this.checkbox) {
35114             this.checkbox.disabled = state;
35115         }
35116         this[state ? 'addClass' : 'removeClass']('x-tree-node-disabled');
35117     },
35118
35119     
35120     onSelectedChange : function(state){
35121         if(state){
35122             this.focus();
35123             this.addClass("x-tree-selected");
35124         }else{
35125             
35126             this.removeClass("x-tree-selected");
35127         }
35128     },
35129
35130     
35131     onMove : function(tree, node, oldParent, newParent, index, refNode){
35132         this.childIndent = null;
35133         if(this.rendered){
35134             var targetNode = newParent.ui.getContainer();
35135             if(!targetNode){
35136                 this.holder = document.createElement("div");
35137                 this.holder.appendChild(this.wrap);
35138                 return;
35139             }
35140             var insertBefore = refNode ? refNode.ui.getEl() : null;
35141             if(insertBefore){
35142                 targetNode.insertBefore(this.wrap, insertBefore);
35143             }else{
35144                 targetNode.appendChild(this.wrap);
35145             }
35146             this.node.renderIndent(true, oldParent != newParent);
35147         }
35148     },
35149
35150
35151     addClass : function(cls){
35152         if(this.elNode){
35153             Ext.fly(this.elNode).addClass(cls);
35154         }
35155     },
35156
35157
35158     removeClass : function(cls){
35159         if(this.elNode){
35160             Ext.fly(this.elNode).removeClass(cls);
35161         }
35162     },
35163
35164     
35165     remove : function(){
35166         if(this.rendered){
35167             this.holder = document.createElement("div");
35168             this.holder.appendChild(this.wrap);
35169         }
35170     },
35171
35172     
35173     fireEvent : function(){
35174         return this.node.fireEvent.apply(this.node, arguments);
35175     },
35176
35177     
35178     initEvents : function(){
35179         this.node.on("move", this.onMove, this);
35180
35181         if(this.node.disabled){
35182             this.onDisableChange(this.node, true);
35183         }
35184         if(this.node.hidden){
35185             this.hide();
35186         }
35187         var ot = this.node.getOwnerTree();
35188         var dd = ot.enableDD || ot.enableDrag || ot.enableDrop;
35189         if(dd && (!this.node.isRoot || ot.rootVisible)){
35190             Ext.dd.Registry.register(this.elNode, {
35191                 node: this.node,
35192                 handles: this.getDDHandles(),
35193                 isHandle: false
35194             });
35195         }
35196     },
35197
35198     
35199     getDDHandles : function(){
35200         return [this.iconNode, this.textNode, this.elNode];
35201     },
35202
35203
35204     hide : function(){
35205         this.node.hidden = true;
35206         if(this.wrap){
35207             this.wrap.style.display = "none";
35208         }
35209     },
35210
35211
35212     show : function(){
35213         this.node.hidden = false;
35214         if(this.wrap){
35215             this.wrap.style.display = "";
35216         }
35217     },
35218
35219     
35220     onContextMenu : function(e){
35221         if (this.node.hasListener("contextmenu") || this.node.getOwnerTree().hasListener("contextmenu")) {
35222             e.preventDefault();
35223             this.focus();
35224             this.fireEvent("contextmenu", this.node, e);
35225         }
35226     },
35227
35228     
35229     onClick : function(e){
35230         if(this.dropping){
35231             e.stopEvent();
35232             return;
35233         }
35234         if(this.fireEvent("beforeclick", this.node, e) !== false){
35235             var a = e.getTarget('a');
35236             if(!this.disabled && this.node.attributes.href && a){
35237                 this.fireEvent("click", this.node, e);
35238                 return;
35239             }else if(a && e.ctrlKey){
35240                 e.stopEvent();
35241             }
35242             e.preventDefault();
35243             if(this.disabled){
35244                 return;
35245             }
35246
35247             if(this.node.attributes.singleClickExpand && !this.animating && this.node.isExpandable()){
35248                 this.node.toggle();
35249             }
35250
35251             this.fireEvent("click", this.node, e);
35252         }else{
35253             e.stopEvent();
35254         }
35255     },
35256
35257     
35258     onDblClick : function(e){
35259         e.preventDefault();
35260         if(this.disabled){
35261             return;
35262         }
35263         if(this.fireEvent("beforedblclick", this.node, e) !== false){
35264             if(this.checkbox){
35265                 this.toggleCheck();
35266             }
35267             if(!this.animating && this.node.isExpandable()){
35268                 this.node.toggle();
35269             }
35270             this.fireEvent("dblclick", this.node, e);
35271         }
35272     },
35273
35274     onOver : function(e){
35275         this.addClass('x-tree-node-over');
35276     },
35277
35278     onOut : function(e){
35279         this.removeClass('x-tree-node-over');
35280     },
35281
35282     
35283     onCheckChange : function(){
35284         var checked = this.checkbox.checked;
35285         
35286         this.checkbox.defaultChecked = checked;
35287         this.node.attributes.checked = checked;
35288         this.fireEvent('checkchange', this.node, checked);
35289     },
35290
35291     
35292     ecClick : function(e){
35293         if(!this.animating && this.node.isExpandable()){
35294             this.node.toggle();
35295         }
35296     },
35297
35298     
35299     startDrop : function(){
35300         this.dropping = true;
35301     },
35302
35303     
35304     endDrop : function(){
35305        setTimeout(function(){
35306            this.dropping = false;
35307        }.createDelegate(this), 50);
35308     },
35309
35310     
35311     expand : function(){
35312         this.updateExpandIcon();
35313         this.ctNode.style.display = "";
35314     },
35315
35316     
35317     focus : function(){
35318         if(!this.node.preventHScroll){
35319             try{this.anchor.focus();
35320             }catch(e){}
35321         }else{
35322             try{
35323                 var noscroll = this.node.getOwnerTree().getTreeEl().dom;
35324                 var l = noscroll.scrollLeft;
35325                 this.anchor.focus();
35326                 noscroll.scrollLeft = l;
35327             }catch(e){}
35328         }
35329     },
35330
35331
35332     toggleCheck : function(value){
35333         var cb = this.checkbox;
35334         if(cb){
35335             cb.checked = (value === undefined ? !cb.checked : value);
35336             this.onCheckChange();
35337         }
35338     },
35339
35340     
35341     blur : function(){
35342         try{
35343             this.anchor.blur();
35344         }catch(e){}
35345     },
35346
35347     
35348     animExpand : function(callback){
35349         var ct = Ext.get(this.ctNode);
35350         ct.stopFx();
35351         if(!this.node.isExpandable()){
35352             this.updateExpandIcon();
35353             this.ctNode.style.display = "";
35354             Ext.callback(callback);
35355             return;
35356         }
35357         this.animating = true;
35358         this.updateExpandIcon();
35359
35360         ct.slideIn('t', {
35361            callback : function(){
35362                this.animating = false;
35363                Ext.callback(callback);
35364             },
35365             scope: this,
35366             duration: this.node.ownerTree.duration || .25
35367         });
35368     },
35369
35370     
35371     highlight : function(){
35372         var tree = this.node.getOwnerTree();
35373         Ext.fly(this.wrap).highlight(
35374             tree.hlColor || "C3DAF9",
35375             {endColor: tree.hlBaseColor}
35376         );
35377     },
35378
35379     
35380     collapse : function(){
35381         this.updateExpandIcon();
35382         this.ctNode.style.display = "none";
35383     },
35384
35385     
35386     animCollapse : function(callback){
35387         var ct = Ext.get(this.ctNode);
35388         ct.enableDisplayMode('block');
35389         ct.stopFx();
35390
35391         this.animating = true;
35392         this.updateExpandIcon();
35393
35394         ct.slideOut('t', {
35395             callback : function(){
35396                this.animating = false;
35397                Ext.callback(callback);
35398             },
35399             scope: this,
35400             duration: this.node.ownerTree.duration || .25
35401         });
35402     },
35403
35404     
35405     getContainer : function(){
35406         return this.ctNode;
35407     },
35408
35409
35410     getEl : function(){
35411         return this.wrap;
35412     },
35413
35414     
35415     appendDDGhost : function(ghostNode){
35416         ghostNode.appendChild(this.elNode.cloneNode(true));
35417     },
35418
35419     
35420     getDDRepairXY : function(){
35421         return Ext.lib.Dom.getXY(this.iconNode);
35422     },
35423
35424     
35425     onRender : function(){
35426         this.render();
35427     },
35428
35429     
35430     render : function(bulkRender){
35431         var n = this.node, a = n.attributes;
35432         var targetNode = n.parentNode ?
35433               n.parentNode.ui.getContainer() : n.ownerTree.innerCt.dom;
35434
35435         if(!this.rendered){
35436             this.rendered = true;
35437
35438             this.renderElements(n, a, targetNode, bulkRender);
35439
35440             if(a.qtip){
35441                 this.onTipChange(n, a.qtip, a.qtipTitle);
35442             }else if(a.qtipCfg){
35443                 a.qtipCfg.target = Ext.id(this.textNode);
35444                 Ext.QuickTips.register(a.qtipCfg);
35445             }
35446             this.initEvents();
35447             if(!this.node.expanded){
35448                 this.updateExpandIcon(true);
35449             }
35450         }else{
35451             if(bulkRender === true) {
35452                 targetNode.appendChild(this.wrap);
35453             }
35454         }
35455     },
35456
35457     
35458     renderElements : function(n, a, targetNode, bulkRender){
35459         
35460         this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';
35461
35462         var cb = Ext.isBoolean(a.checked),
35463             nel,
35464             href = this.getHref(a.href),
35465             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">',
35466             '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",
35467             '<img alt="" src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow" />',
35468             '<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" />',
35469             cb ? ('<input class="x-tree-node-cb" type="checkbox" ' + (a.checked ? 'checked="checked" />' : '/>')) : '',
35470             '<a hidefocus="on" class="x-tree-node-anchor" href="',href,'" tabIndex="1" ',
35471              a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", '><span unselectable="on">',n.text,"</span></a></div>",
35472             '<ul class="x-tree-node-ct" style="display:none;"></ul>',
35473             "</li>"].join('');
35474
35475         if(bulkRender !== true && n.nextSibling && (nel = n.nextSibling.ui.getEl())){
35476             this.wrap = Ext.DomHelper.insertHtml("beforeBegin", nel, buf);
35477         }else{
35478             this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf);
35479         }
35480
35481         this.elNode = this.wrap.childNodes[0];
35482         this.ctNode = this.wrap.childNodes[1];
35483         var cs = this.elNode.childNodes;
35484         this.indentNode = cs[0];
35485         this.ecNode = cs[1];
35486         this.iconNode = cs[2];
35487         var index = 3;
35488         if(cb){
35489             this.checkbox = cs[3];
35490             
35491             this.checkbox.defaultChecked = this.checkbox.checked;
35492             index++;
35493         }
35494         this.anchor = cs[index];
35495         this.textNode = cs[index].firstChild;
35496     },
35497     
35498     
35499     getHref : function(href){
35500         return Ext.isEmpty(href) ? (Ext.isGecko ? '' : '#') : href;
35501     },
35502
35503
35504     getAnchor : function(){
35505         return this.anchor;
35506     },
35507
35508
35509     getTextEl : function(){
35510         return this.textNode;
35511     },
35512
35513
35514     getIconEl : function(){
35515         return this.iconNode;
35516     },
35517
35518
35519     isChecked : function(){
35520         return this.checkbox ? this.checkbox.checked : false;
35521     },
35522
35523     
35524     updateExpandIcon : function(){
35525         if(this.rendered){
35526             var n = this.node,
35527                 c1,
35528                 c2,
35529                 cls = n.isLast() ? "x-tree-elbow-end" : "x-tree-elbow",
35530                 hasChild = n.hasChildNodes();
35531             if(hasChild || n.attributes.expandable){
35532                 if(n.expanded){
35533                     cls += "-minus";
35534                     c1 = "x-tree-node-collapsed";
35535                     c2 = "x-tree-node-expanded";
35536                 }else{
35537                     cls += "-plus";
35538                     c1 = "x-tree-node-expanded";
35539                     c2 = "x-tree-node-collapsed";
35540                 }
35541                 if(this.wasLeaf){
35542                     this.removeClass("x-tree-node-leaf");
35543                     this.wasLeaf = false;
35544                 }
35545                 if(this.c1 != c1 || this.c2 != c2){
35546                     Ext.fly(this.elNode).replaceClass(c1, c2);
35547                     this.c1 = c1; this.c2 = c2;
35548                 }
35549             }else{
35550                 if(!this.wasLeaf){
35551                     Ext.fly(this.elNode).replaceClass("x-tree-node-expanded", "x-tree-node-collapsed");
35552                     delete this.c1;
35553                     delete this.c2;
35554                     this.wasLeaf = true;
35555                 }
35556             }
35557             var ecc = "x-tree-ec-icon "+cls;
35558             if(this.ecc != ecc){
35559                 this.ecNode.className = ecc;
35560                 this.ecc = ecc;
35561             }
35562         }
35563     },
35564
35565     
35566     onIdChange: function(id){
35567         if(this.rendered){
35568             this.elNode.setAttribute('ext:tree-node-id', id);
35569         }
35570     },
35571
35572     
35573     getChildIndent : function(){
35574         if(!this.childIndent){
35575             var buf = [],
35576                 p = this.node;
35577             while(p){
35578                 if(!p.isRoot || (p.isRoot && p.ownerTree.rootVisible)){
35579                     if(!p.isLast()) {
35580                         buf.unshift('<img alt="" src="'+this.emptyIcon+'" class="x-tree-elbow-line" />');
35581                     } else {
35582                         buf.unshift('<img alt="" src="'+this.emptyIcon+'" class="x-tree-icon" />');
35583                     }
35584                 }
35585                 p = p.parentNode;
35586             }
35587             this.childIndent = buf.join("");
35588         }
35589         return this.childIndent;
35590     },
35591
35592     
35593     renderIndent : function(){
35594         if(this.rendered){
35595             var indent = "",
35596                 p = this.node.parentNode;
35597             if(p){
35598                 indent = p.ui.getChildIndent();
35599             }
35600             if(this.indentMarkup != indent){ 
35601                 this.indentNode.innerHTML = indent;
35602                 this.indentMarkup = indent;
35603             }
35604             this.updateExpandIcon();
35605         }
35606     },
35607
35608     destroy : function(){
35609         if(this.elNode){
35610             Ext.dd.Registry.unregister(this.elNode.id);
35611         }
35612
35613         Ext.each(['textnode', 'anchor', 'checkbox', 'indentNode', 'ecNode', 'iconNode', 'elNode', 'ctNode', 'wrap', 'holder'], function(el){
35614             if(this[el]){
35615                 Ext.fly(this[el]).remove();
35616                 delete this[el];
35617             }
35618         }, this);
35619         delete this.node;
35620     }
35621 });
35622
35623
35624 Ext.tree.RootTreeNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
35625     
35626     render : function(){
35627         if(!this.rendered){
35628             var targetNode = this.node.ownerTree.innerCt.dom;
35629             this.node.expanded = true;
35630             targetNode.innerHTML = '<div class="x-tree-root-node"></div>';
35631             this.wrap = this.ctNode = targetNode.firstChild;
35632         }
35633     },
35634     collapse : Ext.emptyFn,
35635     expand : Ext.emptyFn
35636 });
35637 Ext.tree.TreeLoader = function(config){
35638     this.baseParams = {};
35639     Ext.apply(this, config);
35640
35641     this.addEvents(
35642         
35643         "beforeload",
35644         
35645         "load",
35646         
35647         "loadexception"
35648     );
35649     Ext.tree.TreeLoader.superclass.constructor.call(this);
35650     if(Ext.isString(this.paramOrder)){
35651         this.paramOrder = this.paramOrder.split(/[\s,|]/);
35652     }
35653 };
35654
35655 Ext.extend(Ext.tree.TreeLoader, Ext.util.Observable, {
35656     
35657     
35658     
35659     
35660     
35661     
35662     
35663     uiProviders : {},
35664
35665     
35666     clearOnLoad : true,
35667
35668     
35669     paramOrder: undefined,
35670
35671     
35672     paramsAsHash: false,
35673
35674     
35675     nodeParameter: 'node',
35676
35677     
35678     directFn : undefined,
35679
35680     
35681     load : function(node, callback, scope){
35682         if(this.clearOnLoad){
35683             while(node.firstChild){
35684                 node.removeChild(node.firstChild);
35685             }
35686         }
35687         if(this.doPreload(node)){ 
35688             this.runCallback(callback, scope || node, [node]);
35689         }else if(this.directFn || this.dataUrl || this.url){
35690             this.requestData(node, callback, scope || node);
35691         }
35692     },
35693
35694     doPreload : function(node){
35695         if(node.attributes.children){
35696             if(node.childNodes.length < 1){ 
35697                 var cs = node.attributes.children;
35698                 node.beginUpdate();
35699                 for(var i = 0, len = cs.length; i < len; i++){
35700                     var cn = node.appendChild(this.createNode(cs[i]));
35701                     if(this.preloadChildren){
35702                         this.doPreload(cn);
35703                     }
35704                 }
35705                 node.endUpdate();
35706             }
35707             return true;
35708         }
35709         return false;
35710     },
35711
35712     getParams: function(node){
35713         var bp = Ext.apply({}, this.baseParams),
35714             np = this.nodeParameter,
35715             po = this.paramOrder;
35716
35717         np && (bp[ np ] = node.id);
35718
35719         if(this.directFn){
35720             var buf = [node.id];
35721             if(po){
35722                 
35723                 if(np && po.indexOf(np) > -1){
35724                     buf = [];
35725                 }
35726
35727                 for(var i = 0, len = po.length; i < len; i++){
35728                     buf.push(bp[ po[i] ]);
35729                 }
35730             }else if(this.paramsAsHash){
35731                 buf = [bp];
35732             }
35733             return buf;
35734         }else{
35735             return bp;
35736         }
35737     },
35738
35739     requestData : function(node, callback, scope){
35740         if(this.fireEvent("beforeload", this, node, callback) !== false){
35741             if(this.directFn){
35742                 var args = this.getParams(node);
35743                 args.push(this.processDirectResponse.createDelegate(this, [{callback: callback, node: node, scope: scope}], true));
35744                 this.directFn.apply(window, args);
35745             }else{
35746                 this.transId = Ext.Ajax.request({
35747                     method:this.requestMethod,
35748                     url: this.dataUrl||this.url,
35749                     success: this.handleResponse,
35750                     failure: this.handleFailure,
35751                     scope: this,
35752                     argument: {callback: callback, node: node, scope: scope},
35753                     params: this.getParams(node)
35754                 });
35755             }
35756         }else{
35757             
35758             
35759             this.runCallback(callback, scope || node, []);
35760         }
35761     },
35762
35763     processDirectResponse: function(result, response, args){
35764         if(response.status){
35765             this.handleResponse({
35766                 responseData: Ext.isArray(result) ? result : null,
35767                 responseText: result,
35768                 argument: args
35769             });
35770         }else{
35771             this.handleFailure({
35772                 argument: args
35773             });
35774         }
35775     },
35776
35777     
35778     runCallback: function(cb, scope, args){
35779         if(Ext.isFunction(cb)){
35780             cb.apply(scope, args);
35781         }
35782     },
35783
35784     isLoading : function(){
35785         return !!this.transId;
35786     },
35787
35788     abort : function(){
35789         if(this.isLoading()){
35790             Ext.Ajax.abort(this.transId);
35791         }
35792     },
35793
35794     
35795     createNode : function(attr){
35796         
35797         if(this.baseAttrs){
35798             Ext.applyIf(attr, this.baseAttrs);
35799         }
35800         if(this.applyLoader !== false && !attr.loader){
35801             attr.loader = this;
35802         }
35803         if(Ext.isString(attr.uiProvider)){
35804            attr.uiProvider = this.uiProviders[attr.uiProvider] || eval(attr.uiProvider);
35805         }
35806         if(attr.nodeType){
35807             return new Ext.tree.TreePanel.nodeTypes[attr.nodeType](attr);
35808         }else{
35809             return attr.leaf ?
35810                         new Ext.tree.TreeNode(attr) :
35811                         new Ext.tree.AsyncTreeNode(attr);
35812         }
35813     },
35814
35815     processResponse : function(response, node, callback, scope){
35816         var json = response.responseText;
35817         try {
35818             var o = response.responseData || Ext.decode(json);
35819             node.beginUpdate();
35820             for(var i = 0, len = o.length; i < len; i++){
35821                 var n = this.createNode(o[i]);
35822                 if(n){
35823                     node.appendChild(n);
35824                 }
35825             }
35826             node.endUpdate();
35827             this.runCallback(callback, scope || node, [node]);
35828         }catch(e){
35829             this.handleFailure(response);
35830         }
35831     },
35832
35833     handleResponse : function(response){
35834         this.transId = false;
35835         var a = response.argument;
35836         this.processResponse(response, a.node, a.callback, a.scope);
35837         this.fireEvent("load", this, a.node, response);
35838     },
35839
35840     handleFailure : function(response){
35841         this.transId = false;
35842         var a = response.argument;
35843         this.fireEvent("loadexception", this, a.node, response);
35844         this.runCallback(a.callback, a.scope || a.node, [a.node]);
35845     },
35846
35847     destroy : function(){
35848         this.abort();
35849         this.purgeListeners();
35850     }
35851 });
35852 Ext.tree.TreeFilter = function(tree, config){
35853     this.tree = tree;
35854     this.filtered = {};
35855     Ext.apply(this, config);
35856 };
35857
35858 Ext.tree.TreeFilter.prototype = {
35859     clearBlank:false,
35860     reverse:false,
35861     autoClear:false,
35862     remove:false,
35863
35864      
35865     filter : function(value, attr, startNode){
35866         attr = attr || "text";
35867         var f;
35868         if(typeof value == "string"){
35869             var vlen = value.length;
35870             
35871             if(vlen == 0 && this.clearBlank){
35872                 this.clear();
35873                 return;
35874             }
35875             value = value.toLowerCase();
35876             f = function(n){
35877                 return n.attributes[attr].substr(0, vlen).toLowerCase() == value;
35878             };
35879         }else if(value.exec){ 
35880             f = function(n){
35881                 return value.test(n.attributes[attr]);
35882             };
35883         }else{
35884             throw 'Illegal filter type, must be string or regex';
35885         }
35886         this.filterBy(f, null, startNode);
35887         },
35888
35889     
35890     filterBy : function(fn, scope, startNode){
35891         startNode = startNode || this.tree.root;
35892         if(this.autoClear){
35893             this.clear();
35894         }
35895         var af = this.filtered, rv = this.reverse;
35896         var f = function(n){
35897             if(n == startNode){
35898                 return true;
35899             }
35900             if(af[n.id]){
35901                 return false;
35902             }
35903             var m = fn.call(scope || n, n);
35904             if(!m || rv){
35905                 af[n.id] = n;
35906                 n.ui.hide();
35907                 return false;
35908             }
35909             return true;
35910         };
35911         startNode.cascade(f);
35912         if(this.remove){
35913            for(var id in af){
35914                if(typeof id != "function"){
35915                    var n = af[id];
35916                    if(n && n.parentNode){
35917                        n.parentNode.removeChild(n);
35918                    }
35919                }
35920            }
35921         }
35922     },
35923
35924     
35925     clear : function(){
35926         var t = this.tree;
35927         var af = this.filtered;
35928         for(var id in af){
35929             if(typeof id != "function"){
35930                 var n = af[id];
35931                 if(n){
35932                     n.ui.show();
35933                 }
35934             }
35935         }
35936         this.filtered = {};
35937     }
35938 };
35939
35940 Ext.tree.TreeSorter = Ext.extend(Object, {
35941     
35942     constructor: function(tree, config){
35943         
35944     
35945     
35946     
35947     
35948     
35949
35950     Ext.apply(this, config);
35951     tree.on({
35952         scope: this,
35953         beforechildrenrendered: this.doSort,
35954         append: this.updateSort,
35955         insert: this.updateSort,
35956         textchange: this.updateSortParent
35957     });
35958
35959     var desc = this.dir && this.dir.toLowerCase() == 'desc',
35960         prop = this.property || 'text';
35961         sortType = this.sortType;
35962         folderSort = this.folderSort;
35963         caseSensitive = this.caseSensitive === true;
35964         leafAttr = this.leafAttr || 'leaf';
35965
35966     if(Ext.isString(sortType)){
35967         sortType = Ext.data.SortTypes[sortType];
35968     }
35969     this.sortFn = function(n1, n2){
35970         var attr1 = n1.attributes,
35971             attr2 = n2.attributes;
35972             
35973         if(folderSort){
35974             if(attr1[leafAttr] && !attr2[leafAttr]){
35975                 return 1;
35976             }
35977             if(!attr1[leafAttr] && attr2[leafAttr]){
35978                 return -1;
35979             }
35980         }
35981         var prop1 = attr1[prop],
35982             prop2 = attr2[prop],
35983             v1 = sortType ? sortType(prop1) : (caseSensitive ? prop1 : prop1.toUpperCase());
35984             v2 = sortType ? sortType(prop2) : (caseSensitive ? prop2 : prop2.toUpperCase());
35985             
35986         if(v1 < v2){
35987             return desc ? 1 : -1;
35988         }else if(v1 > v2){
35989             return desc ? -1 : 1;
35990         }
35991         return 0;
35992     };
35993     },
35994     
35995     doSort : function(node){
35996         node.sort(this.sortFn);
35997     },
35998
35999     updateSort : function(tree, node){
36000         if(node.childrenRendered){
36001             this.doSort.defer(1, this, [node]);
36002         }
36003     },
36004
36005     updateSortParent : function(node){
36006         var p = node.parentNode;
36007         if(p && p.childrenRendered){
36008             this.doSort.defer(1, this, [p]);
36009         }
36010     }    
36011 });
36012 if(Ext.dd.DropZone){
36013     
36014 Ext.tree.TreeDropZone = function(tree, config){
36015     
36016     this.allowParentInsert = config.allowParentInsert || false;
36017     
36018     this.allowContainerDrop = config.allowContainerDrop || false;
36019     
36020     this.appendOnly = config.appendOnly || false;
36021
36022     Ext.tree.TreeDropZone.superclass.constructor.call(this, tree.getTreeEl(), config);
36023     
36024     this.tree = tree;
36025     
36026     this.dragOverData = {};
36027     
36028     this.lastInsertClass = "x-tree-no-status";
36029 };
36030
36031 Ext.extend(Ext.tree.TreeDropZone, Ext.dd.DropZone, {
36032     
36033     ddGroup : "TreeDD",
36034
36035     
36036     expandDelay : 1000,
36037
36038     
36039     expandNode : function(node){
36040         if(node.hasChildNodes() && !node.isExpanded()){
36041             node.expand(false, null, this.triggerCacheRefresh.createDelegate(this));
36042         }
36043     },
36044
36045     
36046     queueExpand : function(node){
36047         this.expandProcId = this.expandNode.defer(this.expandDelay, this, [node]);
36048     },
36049
36050     
36051     cancelExpand : function(){
36052         if(this.expandProcId){
36053             clearTimeout(this.expandProcId);
36054             this.expandProcId = false;
36055         }
36056     },
36057
36058     
36059     isValidDropPoint : function(n, pt, dd, e, data){
36060         if(!n || !data){ return false; }
36061         var targetNode = n.node;
36062         var dropNode = data.node;
36063         
36064         if(!(targetNode && targetNode.isTarget && pt)){
36065             return false;
36066         }
36067         if(pt == "append" && targetNode.allowChildren === false){
36068             return false;
36069         }
36070         if((pt == "above" || pt == "below") && (targetNode.parentNode && targetNode.parentNode.allowChildren === false)){
36071             return false;
36072         }
36073         if(dropNode && (targetNode == dropNode || dropNode.contains(targetNode))){
36074             return false;
36075         }
36076         
36077         var overEvent = this.dragOverData;
36078         overEvent.tree = this.tree;
36079         overEvent.target = targetNode;
36080         overEvent.data = data;
36081         overEvent.point = pt;
36082         overEvent.source = dd;
36083         overEvent.rawEvent = e;
36084         overEvent.dropNode = dropNode;
36085         overEvent.cancel = false;  
36086         var result = this.tree.fireEvent("nodedragover", overEvent);
36087         return overEvent.cancel === false && result !== false;
36088     },
36089
36090     
36091     getDropPoint : function(e, n, dd){
36092         var tn = n.node;
36093         if(tn.isRoot){
36094             return tn.allowChildren !== false ? "append" : false; 
36095         }
36096         var dragEl = n.ddel;
36097         var t = Ext.lib.Dom.getY(dragEl), b = t + dragEl.offsetHeight;
36098         var y = Ext.lib.Event.getPageY(e);
36099         var noAppend = tn.allowChildren === false || tn.isLeaf();
36100         if(this.appendOnly || tn.parentNode.allowChildren === false){
36101             return noAppend ? false : "append";
36102         }
36103         var noBelow = false;
36104         if(!this.allowParentInsert){
36105             noBelow = tn.hasChildNodes() && tn.isExpanded();
36106         }
36107         var q = (b - t) / (noAppend ? 2 : 3);
36108         if(y >= t && y < (t + q)){
36109             return "above";
36110         }else if(!noBelow && (noAppend || y >= b-q && y <= b)){
36111             return "below";
36112         }else{
36113             return "append";
36114         }
36115     },
36116
36117     
36118     onNodeEnter : function(n, dd, e, data){
36119         this.cancelExpand();
36120     },
36121     
36122     onContainerOver : function(dd, e, data) {
36123         if (this.allowContainerDrop && this.isValidDropPoint({ ddel: this.tree.getRootNode().ui.elNode, node: this.tree.getRootNode() }, "append", dd, e, data)) {
36124             return this.dropAllowed;
36125         }
36126         return this.dropNotAllowed;
36127     },
36128
36129     
36130     onNodeOver : function(n, dd, e, data){
36131         var pt = this.getDropPoint(e, n, dd);
36132         var node = n.node;
36133         
36134         
36135         if(!this.expandProcId && pt == "append" && node.hasChildNodes() && !n.node.isExpanded()){
36136             this.queueExpand(node);
36137         }else if(pt != "append"){
36138             this.cancelExpand();
36139         }
36140         
36141         
36142         var returnCls = this.dropNotAllowed;
36143         if(this.isValidDropPoint(n, pt, dd, e, data)){
36144            if(pt){
36145                var el = n.ddel;
36146                var cls;
36147                if(pt == "above"){
36148                    returnCls = n.node.isFirst() ? "x-tree-drop-ok-above" : "x-tree-drop-ok-between";
36149                    cls = "x-tree-drag-insert-above";
36150                }else if(pt == "below"){
36151                    returnCls = n.node.isLast() ? "x-tree-drop-ok-below" : "x-tree-drop-ok-between";
36152                    cls = "x-tree-drag-insert-below";
36153                }else{
36154                    returnCls = "x-tree-drop-ok-append";
36155                    cls = "x-tree-drag-append";
36156                }
36157                if(this.lastInsertClass != cls){
36158                    Ext.fly(el).replaceClass(this.lastInsertClass, cls);
36159                    this.lastInsertClass = cls;
36160                }
36161            }
36162        }
36163        return returnCls;
36164     },
36165
36166     
36167     onNodeOut : function(n, dd, e, data){
36168         this.cancelExpand();
36169         this.removeDropIndicators(n);
36170     },
36171
36172     
36173     onNodeDrop : function(n, dd, e, data){
36174         var point = this.getDropPoint(e, n, dd);
36175         var targetNode = n.node;
36176         targetNode.ui.startDrop();
36177         if(!this.isValidDropPoint(n, point, dd, e, data)){
36178             targetNode.ui.endDrop();
36179             return false;
36180         }
36181         
36182         var dropNode = data.node || (dd.getTreeNode ? dd.getTreeNode(data, targetNode, point, e) : null);
36183         return this.processDrop(targetNode, data, point, dd, e, dropNode);
36184     },
36185     
36186     onContainerDrop : function(dd, e, data){
36187         if (this.allowContainerDrop && this.isValidDropPoint({ ddel: this.tree.getRootNode().ui.elNode, node: this.tree.getRootNode() }, "append", dd, e, data)) {
36188             var targetNode = this.tree.getRootNode();       
36189             targetNode.ui.startDrop();
36190             var dropNode = data.node || (dd.getTreeNode ? dd.getTreeNode(data, targetNode, 'append', e) : null);
36191             return this.processDrop(targetNode, data, 'append', dd, e, dropNode);
36192         }
36193         return false;
36194     },
36195     
36196     
36197     processDrop: function(target, data, point, dd, e, dropNode){
36198         var dropEvent = {
36199             tree : this.tree,
36200             target: target,
36201             data: data,
36202             point: point,
36203             source: dd,
36204             rawEvent: e,
36205             dropNode: dropNode,
36206             cancel: !dropNode,
36207             dropStatus: false
36208         };
36209         var retval = this.tree.fireEvent("beforenodedrop", dropEvent);
36210         if(retval === false || dropEvent.cancel === true || !dropEvent.dropNode){
36211             target.ui.endDrop();
36212             return dropEvent.dropStatus;
36213         }
36214     
36215         target = dropEvent.target;
36216         if(point == 'append' && !target.isExpanded()){
36217             target.expand(false, null, function(){
36218                 this.completeDrop(dropEvent);
36219             }.createDelegate(this));
36220         }else{
36221             this.completeDrop(dropEvent);
36222         }
36223         return true;
36224     },
36225
36226     
36227     completeDrop : function(de){
36228         var ns = de.dropNode, p = de.point, t = de.target;
36229         if(!Ext.isArray(ns)){
36230             ns = [ns];
36231         }
36232         var n;
36233         for(var i = 0, len = ns.length; i < len; i++){
36234             n = ns[i];
36235             if(p == "above"){
36236                 t.parentNode.insertBefore(n, t);
36237             }else if(p == "below"){
36238                 t.parentNode.insertBefore(n, t.nextSibling);
36239             }else{
36240                 t.appendChild(n);
36241             }
36242         }
36243         n.ui.focus();
36244         if(Ext.enableFx && this.tree.hlDrop){
36245             n.ui.highlight();
36246         }
36247         t.ui.endDrop();
36248         this.tree.fireEvent("nodedrop", de);
36249     },
36250
36251     
36252     afterNodeMoved : function(dd, data, e, targetNode, dropNode){
36253         if(Ext.enableFx && this.tree.hlDrop){
36254             dropNode.ui.focus();
36255             dropNode.ui.highlight();
36256         }
36257         this.tree.fireEvent("nodedrop", this.tree, targetNode, data, dd, e);
36258     },
36259
36260     
36261     getTree : function(){
36262         return this.tree;
36263     },
36264
36265     
36266     removeDropIndicators : function(n){
36267         if(n && n.ddel){
36268             var el = n.ddel;
36269             Ext.fly(el).removeClass([
36270                     "x-tree-drag-insert-above",
36271                     "x-tree-drag-insert-below",
36272                     "x-tree-drag-append"]);
36273             this.lastInsertClass = "_noclass";
36274         }
36275     },
36276
36277     
36278     beforeDragDrop : function(target, e, id){
36279         this.cancelExpand();
36280         return true;
36281     },
36282
36283     
36284     afterRepair : function(data){
36285         if(data && Ext.enableFx){
36286             data.node.ui.highlight();
36287         }
36288         this.hideProxy();
36289     }    
36290 });
36291
36292 }
36293 if(Ext.dd.DragZone){
36294 Ext.tree.TreeDragZone = function(tree, config){
36295     Ext.tree.TreeDragZone.superclass.constructor.call(this, tree.innerCt, config);
36296     
36297     this.tree = tree;
36298 };
36299
36300 Ext.extend(Ext.tree.TreeDragZone, Ext.dd.DragZone, {
36301     
36302     ddGroup : "TreeDD",
36303
36304     
36305     onBeforeDrag : function(data, e){
36306         var n = data.node;
36307         return n && n.draggable && !n.disabled;
36308     },
36309
36310     
36311     onInitDrag : function(e){
36312         var data = this.dragData;
36313         this.tree.getSelectionModel().select(data.node);
36314         this.tree.eventModel.disable();
36315         this.proxy.update("");
36316         data.node.ui.appendDDGhost(this.proxy.ghost.dom);
36317         this.tree.fireEvent("startdrag", this.tree, data.node, e);
36318     },
36319
36320     
36321     getRepairXY : function(e, data){
36322         return data.node.ui.getDDRepairXY();
36323     },
36324
36325     
36326     onEndDrag : function(data, e){
36327         this.tree.eventModel.enable.defer(100, this.tree.eventModel);
36328         this.tree.fireEvent("enddrag", this.tree, data.node, e);
36329     },
36330
36331     
36332     onValidDrop : function(dd, e, id){
36333         this.tree.fireEvent("dragdrop", this.tree, this.dragData.node, dd, e);
36334         this.hideProxy();
36335     },
36336
36337     
36338     beforeInvalidDrop : function(e, id){
36339         
36340         var sm = this.tree.getSelectionModel();
36341         sm.clearSelections();
36342         sm.select(this.dragData.node);
36343     },
36344     
36345     
36346     afterRepair : function(){
36347         if (Ext.enableFx && this.tree.hlDrop) {
36348             Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
36349         }
36350         this.dragging = false;
36351     }
36352 });
36353 }
36354 Ext.tree.TreeEditor = function(tree, fc, config){
36355     fc = fc || {};
36356     var field = fc.events ? fc : new Ext.form.TextField(fc);
36357     
36358     Ext.tree.TreeEditor.superclass.constructor.call(this, field, config);
36359
36360     this.tree = tree;
36361
36362     if(!tree.rendered){
36363         tree.on('render', this.initEditor, this);
36364     }else{
36365         this.initEditor(tree);
36366     }
36367 };
36368
36369 Ext.extend(Ext.tree.TreeEditor, Ext.Editor, {
36370     
36371     alignment: "l-l",
36372     
36373     autoSize: false,
36374     
36375     hideEl : false,
36376     
36377     cls: "x-small-editor x-tree-editor",
36378     
36379     shim:false,
36380     
36381     shadow:"frame",
36382     
36383     maxWidth: 250,
36384     
36385     editDelay : 350,
36386
36387     initEditor : function(tree){
36388         tree.on({
36389             scope      : this,
36390             beforeclick: this.beforeNodeClick,
36391             dblclick   : this.onNodeDblClick
36392         });
36393         
36394         this.on({
36395             scope          : this,
36396             complete       : this.updateNode,
36397             beforestartedit: this.fitToTree,
36398             specialkey     : this.onSpecialKey
36399         });
36400         
36401         this.on('startedit', this.bindScroll, this, {delay:10});
36402     },
36403
36404     
36405     fitToTree : function(ed, el){
36406         var td = this.tree.getTreeEl().dom, nd = el.dom;
36407         if(td.scrollLeft >  nd.offsetLeft){ 
36408             td.scrollLeft = nd.offsetLeft;
36409         }
36410         var w = Math.min(
36411                 this.maxWidth,
36412                 (td.clientWidth > 20 ? td.clientWidth : td.offsetWidth) - Math.max(0, nd.offsetLeft-td.scrollLeft) - 5);
36413         this.setSize(w, '');
36414     },
36415
36416     
36417     triggerEdit : function(node, defer){
36418         this.completeEdit();
36419                 if(node.attributes.editable !== false){
36420            
36421                         this.editNode = node;
36422             if(this.tree.autoScroll){
36423                 Ext.fly(node.ui.getEl()).scrollIntoView(this.tree.body);
36424             }
36425             var value = node.text || '';
36426             if (!Ext.isGecko && Ext.isEmpty(node.text)){
36427                 node.setText('&#160;');
36428             }
36429             this.autoEditTimer = this.startEdit.defer(this.editDelay, this, [node.ui.textNode, value]);
36430             return false;
36431         }
36432     },
36433
36434     
36435     bindScroll : function(){
36436         this.tree.getTreeEl().on('scroll', this.cancelEdit, this);
36437     },
36438
36439     
36440     beforeNodeClick : function(node, e){
36441         clearTimeout(this.autoEditTimer);
36442         if(this.tree.getSelectionModel().isSelected(node)){
36443             e.stopEvent();
36444             return this.triggerEdit(node);
36445         }
36446     },
36447
36448     onNodeDblClick : function(node, e){
36449         clearTimeout(this.autoEditTimer);
36450     },
36451
36452     
36453     updateNode : function(ed, value){
36454         this.tree.getTreeEl().un('scroll', this.cancelEdit, this);
36455         this.editNode.setText(value);
36456     },
36457
36458     
36459     onHide : function(){
36460         Ext.tree.TreeEditor.superclass.onHide.call(this);
36461         if(this.editNode){
36462             this.editNode.ui.focus.defer(50, this.editNode.ui);
36463         }
36464     },
36465
36466     
36467     onSpecialKey : function(field, e){
36468         var k = e.getKey();
36469         if(k == e.ESC){
36470             e.stopEvent();
36471             this.cancelEdit();
36472         }else if(k == e.ENTER && !e.hasModifier()){
36473             e.stopEvent();
36474             this.completeEdit();
36475         }
36476     },
36477     
36478     onDestroy : function(){
36479         clearTimeout(this.autoEditTimer);
36480         Ext.tree.TreeEditor.superclass.onDestroy.call(this);
36481         var tree = this.tree;
36482         tree.un('beforeclick', this.beforeNodeClick, this);
36483         tree.un('dblclick', this.onNodeDblClick, this);
36484     }
36485 });
36486
36487 var swfobject = function() {
36488     
36489     var UNDEF = "undefined",
36490         OBJECT = "object",
36491         SHOCKWAVE_FLASH = "Shockwave Flash",
36492         SHOCKWAVE_FLASH_AX = "ShockwaveFlash.ShockwaveFlash",
36493         FLASH_MIME_TYPE = "application/x-shockwave-flash",
36494         EXPRESS_INSTALL_ID = "SWFObjectExprInst",
36495         ON_READY_STATE_CHANGE = "onreadystatechange",
36496         
36497         win = window,
36498         doc = document,
36499         nav = navigator,
36500         
36501         plugin = false,
36502         domLoadFnArr = [main],
36503         regObjArr = [],
36504         objIdArr = [],
36505         listenersArr = [],
36506         storedAltContent,
36507         storedAltContentId,
36508         storedCallbackFn,
36509         storedCallbackObj,
36510         isDomLoaded = false,
36511         isExpressInstallActive = false,
36512         dynamicStylesheet,
36513         dynamicStylesheetMedia,
36514         autoHideShow = true,
36515     
36516       
36517     ua = function() {
36518         var w3cdom = typeof doc.getElementById != UNDEF && typeof doc.getElementsByTagName != UNDEF && typeof doc.createElement != UNDEF,
36519             u = nav.userAgent.toLowerCase(),
36520             p = nav.platform.toLowerCase(),
36521             windows = p ? (/win/).test(p) : /win/.test(u),
36522             mac = p ? (/mac/).test(p) : /mac/.test(u),
36523             webkit = /webkit/.test(u) ? parseFloat(u.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false, 
36524             ie = !+"\v1", 
36525             playerVersion = [0,0,0],
36526             d = null;
36527         if (typeof nav.plugins != UNDEF && typeof nav.plugins[SHOCKWAVE_FLASH] == OBJECT) {
36528             d = nav.plugins[SHOCKWAVE_FLASH].description;
36529             if (d && !(typeof nav.mimeTypes != UNDEF && nav.mimeTypes[FLASH_MIME_TYPE] && !nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) { 
36530                 plugin = true;
36531                 ie = false; 
36532                 d = d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
36533                 playerVersion[0] = parseInt(d.replace(/^(.*)\..*$/, "$1"), 10);
36534                 playerVersion[1] = parseInt(d.replace(/^.*\.(.*)\s.*$/, "$1"), 10);
36535                 playerVersion[2] = /[a-zA-Z]/.test(d) ? parseInt(d.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0;
36536             }
36537         }
36538         else if (typeof win.ActiveXObject != UNDEF) {
36539             try {
36540                 var a = new ActiveXObject(SHOCKWAVE_FLASH_AX);
36541                 if (a) { 
36542                     d = a.GetVariable("$version");
36543                     if (d) {
36544                         ie = true; 
36545                         d = d.split(" ")[1].split(",");
36546                         playerVersion = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
36547                     }
36548                 }
36549             }
36550             catch(e) {}
36551         }
36552         return { w3:w3cdom, pv:playerVersion, wk:webkit, ie:ie, win:windows, mac:mac };
36553     }(),
36554     
36555      
36556     onDomLoad = function() {
36557         if (!ua.w3) { return; }
36558         if ((typeof doc.readyState != UNDEF && doc.readyState == "complete") || (typeof doc.readyState == UNDEF && (doc.getElementsByTagName("body")[0] || doc.body))) { 
36559             callDomLoadFunctions();
36560         }
36561         if (!isDomLoaded) {
36562             if (typeof doc.addEventListener != UNDEF) {
36563                 doc.addEventListener("DOMContentLoaded", callDomLoadFunctions, false);
36564             }       
36565             if (ua.ie && ua.win) {
36566                 doc.attachEvent(ON_READY_STATE_CHANGE, function() {
36567                     if (doc.readyState == "complete") {
36568                         doc.detachEvent(ON_READY_STATE_CHANGE, arguments.callee);
36569                         callDomLoadFunctions();
36570                     }
36571                 });
36572                 if (win == top) { 
36573                     (function(){
36574                         if (isDomLoaded) { return; }
36575                         try {
36576                             doc.documentElement.doScroll("left");
36577                         }
36578                         catch(e) {
36579                             setTimeout(arguments.callee, 0);
36580                             return;
36581                         }
36582                         callDomLoadFunctions();
36583                     })();
36584                 }
36585             }
36586             if (ua.wk) {
36587                 (function(){
36588                     if (isDomLoaded) { return; }
36589                     if (!(/loaded|complete/).test(doc.readyState)) {
36590                         setTimeout(arguments.callee, 0);
36591                         return;
36592                     }
36593                     callDomLoadFunctions();
36594                 })();
36595             }
36596             addLoadEvent(callDomLoadFunctions);
36597         }
36598     }();
36599     
36600     function callDomLoadFunctions() {
36601         if (isDomLoaded) { return; }
36602         try { 
36603             var t = doc.getElementsByTagName("body")[0].appendChild(createElement("span"));
36604             t.parentNode.removeChild(t);
36605         }
36606         catch (e) { return; }
36607         isDomLoaded = true;
36608         var dl = domLoadFnArr.length;
36609         for (var i = 0; i < dl; i++) {
36610             domLoadFnArr[i]();
36611         }
36612     }
36613     
36614     function addDomLoadEvent(fn) {
36615         if (isDomLoaded) {
36616             fn();
36617         }
36618         else { 
36619             domLoadFnArr[domLoadFnArr.length] = fn; 
36620         }
36621     }
36622     
36623     
36624     function addLoadEvent(fn) {
36625         if (typeof win.addEventListener != UNDEF) {
36626             win.addEventListener("load", fn, false);
36627         }
36628         else if (typeof doc.addEventListener != UNDEF) {
36629             doc.addEventListener("load", fn, false);
36630         }
36631         else if (typeof win.attachEvent != UNDEF) {
36632             addListener(win, "onload", fn);
36633         }
36634         else if (typeof win.onload == "function") {
36635             var fnOld = win.onload;
36636             win.onload = function() {
36637                 fnOld();
36638                 fn();
36639             };
36640         }
36641         else {
36642             win.onload = fn;
36643         }
36644     }
36645     
36646     
36647     function main() { 
36648         if (plugin) {
36649             testPlayerVersion();
36650         }
36651         else {
36652             matchVersions();
36653         }
36654     }
36655     
36656     
36657     function testPlayerVersion() {
36658         var b = doc.getElementsByTagName("body")[0];
36659         var o = createElement(OBJECT);
36660         o.setAttribute("type", FLASH_MIME_TYPE);
36661         var t = b.appendChild(o);
36662         if (t) {
36663             var counter = 0;
36664             (function(){
36665                 if (typeof t.GetVariable != UNDEF) {
36666                     var d = t.GetVariable("$version");
36667                     if (d) {
36668                         d = d.split(" ")[1].split(",");
36669                         ua.pv = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
36670                     }
36671                 }
36672                 else if (counter < 10) {
36673                     counter++;
36674                     setTimeout(arguments.callee, 10);
36675                     return;
36676                 }
36677                 b.removeChild(o);
36678                 t = null;
36679                 matchVersions();
36680             })();
36681         }
36682         else {
36683             matchVersions();
36684         }
36685     }
36686     
36687     
36688     function matchVersions() {
36689         var rl = regObjArr.length;
36690         if (rl > 0) {
36691             for (var i = 0; i < rl; i++) { 
36692                 var id = regObjArr[i].id;
36693                 var cb = regObjArr[i].callbackFn;
36694                 var cbObj = {success:false, id:id};
36695                 if (ua.pv[0] > 0) {
36696                     var obj = getElementById(id);
36697                     if (obj) {
36698                         if (hasPlayerVersion(regObjArr[i].swfVersion) && !(ua.wk && ua.wk < 312)) { 
36699                             setVisibility(id, true);
36700                             if (cb) {
36701                                 cbObj.success = true;
36702                                 cbObj.ref = getObjectById(id);
36703                                 cb(cbObj);
36704                             }
36705                         }
36706                         else if (regObjArr[i].expressInstall && canExpressInstall()) { 
36707                             var att = {};
36708                             att.data = regObjArr[i].expressInstall;
36709                             att.width = obj.getAttribute("width") || "0";
36710                             att.height = obj.getAttribute("height") || "0";
36711                             if (obj.getAttribute("class")) { att.styleclass = obj.getAttribute("class"); }
36712                             if (obj.getAttribute("align")) { att.align = obj.getAttribute("align"); }
36713                             
36714                             var par = {};
36715                             var p = obj.getElementsByTagName("param");
36716                             var pl = p.length;
36717                             for (var j = 0; j < pl; j++) {
36718                                 if (p[j].getAttribute("name").toLowerCase() != "movie") {
36719                                     par[p[j].getAttribute("name")] = p[j].getAttribute("value");
36720                                 }
36721                             }
36722                             showExpressInstall(att, par, id, cb);
36723                         }
36724                         else { 
36725                             displayAltContent(obj);
36726                             if (cb) { cb(cbObj); }
36727                         }
36728                     }
36729                 }
36730                 else {  
36731                     setVisibility(id, true);
36732                     if (cb) {
36733                         var o = getObjectById(id); 
36734                         if (o && typeof o.SetVariable != UNDEF) { 
36735                             cbObj.success = true;
36736                             cbObj.ref = o;
36737                         }
36738                         cb(cbObj);
36739                     }
36740                 }
36741             }
36742         }
36743     }
36744     
36745     function getObjectById(objectIdStr) {
36746         var r = null;
36747         var o = getElementById(objectIdStr);
36748         if (o && o.nodeName == "OBJECT") {
36749             if (typeof o.SetVariable != UNDEF) {
36750                 r = o;
36751             }
36752             else {
36753                 var n = o.getElementsByTagName(OBJECT)[0];
36754                 if (n) {
36755                     r = n;
36756                 }
36757             }
36758         }
36759         return r;
36760     }
36761     
36762     
36763     function canExpressInstall() {
36764         return !isExpressInstallActive && hasPlayerVersion("6.0.65") && (ua.win || ua.mac) && !(ua.wk && ua.wk < 312);
36765     }
36766     
36767     
36768     function showExpressInstall(att, par, replaceElemIdStr, callbackFn) {
36769         isExpressInstallActive = true;
36770         storedCallbackFn = callbackFn || null;
36771         storedCallbackObj = {success:false, id:replaceElemIdStr};
36772         var obj = getElementById(replaceElemIdStr);
36773         if (obj) {
36774             if (obj.nodeName == "OBJECT") { 
36775                 storedAltContent = abstractAltContent(obj);
36776                 storedAltContentId = null;
36777             }
36778             else { 
36779                 storedAltContent = obj;
36780                 storedAltContentId = replaceElemIdStr;
36781             }
36782             att.id = EXPRESS_INSTALL_ID;
36783             if (typeof att.width == UNDEF || (!(/%$/).test(att.width) && parseInt(att.width, 10) < 310)) {
36784                 att.width = "310";
36785             }
36786             
36787             if (typeof att.height == UNDEF || (!(/%$/).test(att.height) && parseInt(att.height, 10) < 137)) {
36788                 att.height = "137";
36789             }
36790             doc.title = doc.title.slice(0, 47) + " - Flash Player Installation";
36791             var pt = ua.ie && ua.win ? "ActiveX" : "PlugIn",
36792                 fv = "MMredirectURL=" + win.location.toString().replace(/&/g,"%26") + "&MMplayerType=" + pt + "&MMdoctitle=" + doc.title;
36793             if (typeof par.flashvars != UNDEF) {
36794                 par.flashvars += "&" + fv;
36795             }
36796             else {
36797                 par.flashvars = fv;
36798             }
36799             
36800             
36801             if (ua.ie && ua.win && obj.readyState != 4) {
36802                 var newObj = createElement("div");
36803                 replaceElemIdStr += "SWFObjectNew";
36804                 newObj.setAttribute("id", replaceElemIdStr);
36805                 obj.parentNode.insertBefore(newObj, obj); 
36806                 obj.style.display = "none";
36807                 (function(){
36808                     if (obj.readyState == 4) {
36809                         obj.parentNode.removeChild(obj);
36810                     }
36811                     else {
36812                         setTimeout(arguments.callee, 10);
36813                     }
36814                 })();
36815             }
36816             createSWF(att, par, replaceElemIdStr);
36817         }
36818     }
36819     
36820     
36821     function displayAltContent(obj) {
36822         if (ua.ie && ua.win && obj.readyState != 4) {
36823             
36824             
36825             var el = createElement("div");
36826             obj.parentNode.insertBefore(el, obj); 
36827             el.parentNode.replaceChild(abstractAltContent(obj), el);
36828             obj.style.display = "none";
36829             (function(){
36830                 if (obj.readyState == 4) {
36831                     obj.parentNode.removeChild(obj);
36832                 }
36833                 else {
36834                     setTimeout(arguments.callee, 10);
36835                 }
36836             })();
36837         }
36838         else {
36839             obj.parentNode.replaceChild(abstractAltContent(obj), obj);
36840         }
36841     } 
36842
36843     function abstractAltContent(obj) {
36844         var ac = createElement("div");
36845         if (ua.win && ua.ie) {
36846             ac.innerHTML = obj.innerHTML;
36847         }
36848         else {
36849             var nestedObj = obj.getElementsByTagName(OBJECT)[0];
36850             if (nestedObj) {
36851                 var c = nestedObj.childNodes;
36852                 if (c) {
36853                     var cl = c.length;
36854                     for (var i = 0; i < cl; i++) {
36855                         if (!(c[i].nodeType == 1 && c[i].nodeName == "PARAM") && !(c[i].nodeType == 8)) {
36856                             ac.appendChild(c[i].cloneNode(true));
36857                         }
36858                     }
36859                 }
36860             }
36861         }
36862         return ac;
36863     }
36864     
36865     
36866     function createSWF(attObj, parObj, id) {
36867         var r, el = getElementById(id);
36868         if (ua.wk && ua.wk < 312) { return r; }
36869         if (el) {
36870             if (typeof attObj.id == UNDEF) { 
36871                 attObj.id = id;
36872             }
36873             if (ua.ie && ua.win) { 
36874                 var att = "";
36875                 for (var i in attObj) {
36876                     if (attObj[i] != Object.prototype[i]) { 
36877                         if (i.toLowerCase() == "data") {
36878                             parObj.movie = attObj[i];
36879                         }
36880                         else if (i.toLowerCase() == "styleclass") { 
36881                             att += ' class="' + attObj[i] + '"';
36882                         }
36883                         else if (i.toLowerCase() != "classid") {
36884                             att += ' ' + i + '="' + attObj[i] + '"';
36885                         }
36886                     }
36887                 }
36888                 var par = "";
36889                 for (var j in parObj) {
36890                     if (parObj[j] != Object.prototype[j]) { 
36891                         par += '<param name="' + j + '" value="' + parObj[j] + '" />';
36892                     }
36893                 }
36894                 el.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' + att + '>' + par + '</object>';
36895                 objIdArr[objIdArr.length] = attObj.id; 
36896                 r = getElementById(attObj.id);  
36897             }
36898             else { 
36899                 var o = createElement(OBJECT);
36900                 o.setAttribute("type", FLASH_MIME_TYPE);
36901                 for (var m in attObj) {
36902                     if (attObj[m] != Object.prototype[m]) { 
36903                         if (m.toLowerCase() == "styleclass") { 
36904                             o.setAttribute("class", attObj[m]);
36905                         }
36906                         else if (m.toLowerCase() != "classid") { 
36907                             o.setAttribute(m, attObj[m]);
36908                         }
36909                     }
36910                 }
36911                 for (var n in parObj) {
36912                     if (parObj[n] != Object.prototype[n] && n.toLowerCase() != "movie") { 
36913                         createObjParam(o, n, parObj[n]);
36914                     }
36915                 }
36916                 el.parentNode.replaceChild(o, el);
36917                 r = o;
36918             }
36919         }
36920         return r;
36921     }
36922     
36923     function createObjParam(el, pName, pValue) {
36924         var p = createElement("param");
36925         p.setAttribute("name", pName);  
36926         p.setAttribute("value", pValue);
36927         el.appendChild(p);
36928     }
36929     
36930     
36931     function removeSWF(id) {
36932         var obj = getElementById(id);
36933         if (obj && obj.nodeName == "OBJECT") {
36934             if (ua.ie && ua.win) {
36935                 obj.style.display = "none";
36936                 (function(){
36937                     if (obj.readyState == 4) {
36938                         removeObjectInIE(id);
36939                     }
36940                     else {
36941                         setTimeout(arguments.callee, 10);
36942                     }
36943                 })();
36944             }
36945             else {
36946                 obj.parentNode.removeChild(obj);
36947             }
36948         }
36949     }
36950     
36951     function removeObjectInIE(id) {
36952         var obj = getElementById(id);
36953         if (obj) {
36954             for (var i in obj) {
36955                 if (typeof obj[i] == "function") {
36956                     obj[i] = null;
36957                 }
36958             }
36959             obj.parentNode.removeChild(obj);
36960         }
36961     }
36962     
36963     
36964     function getElementById(id) {
36965         var el = null;
36966         try {
36967             el = doc.getElementById(id);
36968         }
36969         catch (e) {}
36970         return el;
36971     }
36972     
36973     function createElement(el) {
36974         return doc.createElement(el);
36975     }
36976     
36977       
36978     function addListener(target, eventType, fn) {
36979         target.attachEvent(eventType, fn);
36980         listenersArr[listenersArr.length] = [target, eventType, fn];
36981     }
36982     
36983     
36984     function hasPlayerVersion(rv) {
36985         var pv = ua.pv, v = rv.split(".");
36986         v[0] = parseInt(v[0], 10);
36987         v[1] = parseInt(v[1], 10) || 0; 
36988         v[2] = parseInt(v[2], 10) || 0;
36989         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;
36990     }
36991     
36992       
36993     function createCSS(sel, decl, media, newStyle) {
36994         if (ua.ie && ua.mac) { return; }
36995         var h = doc.getElementsByTagName("head")[0];
36996         if (!h) { return; } 
36997         var m = (media && typeof media == "string") ? media : "screen";
36998         if (newStyle) {
36999             dynamicStylesheet = null;
37000             dynamicStylesheetMedia = null;
37001         }
37002         if (!dynamicStylesheet || dynamicStylesheetMedia != m) { 
37003             
37004             var s = createElement("style");
37005             s.setAttribute("type", "text/css");
37006             s.setAttribute("media", m);
37007             dynamicStylesheet = h.appendChild(s);
37008             if (ua.ie && ua.win && typeof doc.styleSheets != UNDEF && doc.styleSheets.length > 0) {
37009                 dynamicStylesheet = doc.styleSheets[doc.styleSheets.length - 1];
37010             }
37011             dynamicStylesheetMedia = m;
37012         }
37013         
37014         if (ua.ie && ua.win) {
37015             if (dynamicStylesheet && typeof dynamicStylesheet.addRule == OBJECT) {
37016                 dynamicStylesheet.addRule(sel, decl);
37017             }
37018         }
37019         else {
37020             if (dynamicStylesheet && typeof doc.createTextNode != UNDEF) {
37021                 dynamicStylesheet.appendChild(doc.createTextNode(sel + " {" + decl + "}"));
37022             }
37023         }
37024     }
37025     
37026     function setVisibility(id, isVisible) {
37027         if (!autoHideShow) { return; }
37028         var v = isVisible ? "visible" : "hidden";
37029         if (isDomLoaded && getElementById(id)) {
37030             getElementById(id).style.visibility = v;
37031         }
37032         else {
37033             createCSS("#" + id, "visibility:" + v);
37034         }
37035     }
37036
37037     
37038     function urlEncodeIfNecessary(s) {
37039         var regex = /[\\\"<>\.;]/;
37040         var hasBadChars = regex.exec(s) != null;
37041         return hasBadChars && typeof encodeURIComponent != UNDEF ? encodeURIComponent(s) : s;
37042     }
37043     
37044     
37045     var cleanup = function() {
37046         if (ua.ie && ua.win) {
37047             window.attachEvent("onunload", function() {
37048                 
37049                 var ll = listenersArr.length;
37050                 for (var i = 0; i < ll; i++) {
37051                     listenersArr[i][0].detachEvent(listenersArr[i][1], listenersArr[i][2]);
37052                 }
37053                 
37054                 var il = objIdArr.length;
37055                 for (var j = 0; j < il; j++) {
37056                     removeSWF(objIdArr[j]);
37057                 }
37058                 
37059                 for (var k in ua) {
37060                     ua[k] = null;
37061                 }
37062                 ua = null;
37063                 for (var l in swfobject) {
37064                     swfobject[l] = null;
37065                 }
37066                 swfobject = null;
37067             });
37068         }
37069     }();
37070     
37071     return {
37072          
37073         registerObject: function(objectIdStr, swfVersionStr, xiSwfUrlStr, callbackFn) {
37074             if (ua.w3 && objectIdStr && swfVersionStr) {
37075                 var regObj = {};
37076                 regObj.id = objectIdStr;
37077                 regObj.swfVersion = swfVersionStr;
37078                 regObj.expressInstall = xiSwfUrlStr;
37079                 regObj.callbackFn = callbackFn;
37080                 regObjArr[regObjArr.length] = regObj;
37081                 setVisibility(objectIdStr, false);
37082             }
37083             else if (callbackFn) {
37084                 callbackFn({success:false, id:objectIdStr});
37085             }
37086         },
37087         
37088         getObjectById: function(objectIdStr) {
37089             if (ua.w3) {
37090                 return getObjectById(objectIdStr);
37091             }
37092         },
37093         
37094         embedSWF: function(swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr, xiSwfUrlStr, flashvarsObj, parObj, attObj, callbackFn) {
37095             var callbackObj = {success:false, id:replaceElemIdStr};
37096             if (ua.w3 && !(ua.wk && ua.wk < 312) && swfUrlStr && replaceElemIdStr && widthStr && heightStr && swfVersionStr) {
37097                 setVisibility(replaceElemIdStr, false);
37098                 addDomLoadEvent(function() {
37099                     widthStr += ""; 
37100                     heightStr += "";
37101                     var att = {};
37102                     if (attObj && typeof attObj === OBJECT) {
37103                         for (var i in attObj) { 
37104                             att[i] = attObj[i];
37105                         }
37106                     }
37107                     att.data = swfUrlStr;
37108                     att.width = widthStr;
37109                     att.height = heightStr;
37110                     var par = {}; 
37111                     if (parObj && typeof parObj === OBJECT) {
37112                         for (var j in parObj) { 
37113                             par[j] = parObj[j];
37114                         }
37115                     }
37116                     if (flashvarsObj && typeof flashvarsObj === OBJECT) {
37117                         for (var k in flashvarsObj) { 
37118                             if (typeof par.flashvars != UNDEF) {
37119                                 par.flashvars += "&" + k + "=" + flashvarsObj[k];
37120                             }
37121                             else {
37122                                 par.flashvars = k + "=" + flashvarsObj[k];
37123                             }
37124                         }
37125                     }
37126                     if (hasPlayerVersion(swfVersionStr)) { 
37127                         var obj = createSWF(att, par, replaceElemIdStr);
37128                         if (att.id == replaceElemIdStr) {
37129                             setVisibility(replaceElemIdStr, true);
37130                         }
37131                         callbackObj.success = true;
37132                         callbackObj.ref = obj;
37133                     }
37134                     else if (xiSwfUrlStr && canExpressInstall()) { 
37135                         att.data = xiSwfUrlStr;
37136                         showExpressInstall(att, par, replaceElemIdStr, callbackFn);
37137                         return;
37138                     }
37139                     else { 
37140                         setVisibility(replaceElemIdStr, true);
37141                     }
37142                     if (callbackFn) { callbackFn(callbackObj); }
37143                 });
37144             }
37145             else if (callbackFn) { callbackFn(callbackObj); }
37146         },
37147         
37148         switchOffAutoHideShow: function() {
37149             autoHideShow = false;
37150         },
37151         
37152         ua: ua,
37153         
37154         getFlashPlayerVersion: function() {
37155             return { major:ua.pv[0], minor:ua.pv[1], release:ua.pv[2] };
37156         },
37157         
37158         hasFlashPlayerVersion: hasPlayerVersion,
37159         
37160         createSWF: function(attObj, parObj, replaceElemIdStr) {
37161             if (ua.w3) {
37162                 return createSWF(attObj, parObj, replaceElemIdStr);
37163             }
37164             else {
37165                 return undefined;
37166             }
37167         },
37168         
37169         showExpressInstall: function(att, par, replaceElemIdStr, callbackFn) {
37170             if (ua.w3 && canExpressInstall()) {
37171                 showExpressInstall(att, par, replaceElemIdStr, callbackFn);
37172             }
37173         },
37174         
37175         removeSWF: function(objElemIdStr) {
37176             if (ua.w3) {
37177                 removeSWF(objElemIdStr);
37178             }
37179         },
37180         
37181         createCSS: function(selStr, declStr, mediaStr, newStyleBoolean) {
37182             if (ua.w3) {
37183                 createCSS(selStr, declStr, mediaStr, newStyleBoolean);
37184             }
37185         },
37186         
37187         addDomLoadEvent: addDomLoadEvent,
37188         
37189         addLoadEvent: addLoadEvent,
37190         
37191         getQueryParamValue: function(param) {
37192             var q = doc.location.search || doc.location.hash;
37193             if (q) {
37194                 if (/\?/.test(q)) { q = q.split("?")[1]; } 
37195                 if (param == null) {
37196                     return urlEncodeIfNecessary(q);
37197                 }
37198                 var pairs = q.split("&");
37199                 for (var i = 0; i < pairs.length; i++) {
37200                     if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) {
37201                         return urlEncodeIfNecessary(pairs[i].substring((pairs[i].indexOf("=") + 1)));
37202                     }
37203                 }
37204             }
37205             return "";
37206         },
37207         
37208         
37209         expressInstallCallback: function() {
37210             if (isExpressInstallActive) {
37211                 var obj = getElementById(EXPRESS_INSTALL_ID);
37212                 if (obj && storedAltContent) {
37213                     obj.parentNode.replaceChild(storedAltContent, obj);
37214                     if (storedAltContentId) {
37215                         setVisibility(storedAltContentId, true);
37216                         if (ua.ie && ua.win) { storedAltContent.style.display = "block"; }
37217                     }
37218                     if (storedCallbackFn) { storedCallbackFn(storedCallbackObj); }
37219                 }
37220                 isExpressInstallActive = false;
37221             } 
37222         }
37223     };
37224 }();
37225
37226 Ext.FlashComponent = Ext.extend(Ext.BoxComponent, {
37227     
37228     flashVersion : '9.0.115',
37229
37230     
37231     backgroundColor: '#ffffff',
37232
37233     
37234     wmode: 'opaque',
37235
37236     
37237     flashVars: undefined,
37238
37239     
37240     flashParams: undefined,
37241
37242     
37243     url: undefined,
37244     swfId : undefined,
37245     swfWidth: '100%',
37246     swfHeight: '100%',
37247
37248     
37249     expressInstall: false,
37250
37251     initComponent : function(){
37252         Ext.FlashComponent.superclass.initComponent.call(this);
37253
37254         this.addEvents(
37255             
37256             'initialize'
37257         );
37258     },
37259
37260     onRender : function(){
37261         Ext.FlashComponent.superclass.onRender.apply(this, arguments);
37262
37263         var params = Ext.apply({
37264             allowScriptAccess: 'always',
37265             bgcolor: this.backgroundColor,
37266             wmode: this.wmode
37267         }, this.flashParams), vars = Ext.apply({
37268             allowedDomain: document.location.hostname,
37269             YUISwfId: this.getId(),
37270             YUIBridgeCallback: 'Ext.FlashEventProxy.onEvent'
37271         }, this.flashVars);
37272
37273         new swfobject.embedSWF(this.url, this.id, this.swfWidth, this.swfHeight, this.flashVersion,
37274             this.expressInstall ? Ext.FlashComponent.EXPRESS_INSTALL_URL : undefined, vars, params);
37275
37276         this.swf = Ext.getDom(this.id);
37277         this.el = Ext.get(this.swf);
37278     },
37279
37280     getSwfId : function(){
37281         return this.swfId || (this.swfId = "extswf" + (++Ext.Component.AUTO_ID));
37282     },
37283
37284     getId : function(){
37285         return this.id || (this.id = "extflashcmp" + (++Ext.Component.AUTO_ID));
37286     },
37287
37288     onFlashEvent : function(e){
37289         switch(e.type){
37290             case "swfReady":
37291                 this.initSwf();
37292                 return;
37293             case "log":
37294                 return;
37295         }
37296         e.component = this;
37297         this.fireEvent(e.type.toLowerCase().replace(/event$/, ''), e);
37298     },
37299
37300     initSwf : function(){
37301         this.onSwfReady(!!this.isInitialized);
37302         this.isInitialized = true;
37303         this.fireEvent('initialize', this);
37304     },
37305
37306     beforeDestroy: function(){
37307         if(this.rendered){
37308             swfobject.removeSWF(this.swf.id);
37309         }
37310         Ext.FlashComponent.superclass.beforeDestroy.call(this);
37311     },
37312
37313     onSwfReady : Ext.emptyFn
37314 });
37315
37316
37317 Ext.FlashComponent.EXPRESS_INSTALL_URL = 'http:/' + '/swfobject.googlecode.com/svn/trunk/swfobject/expressInstall.swf';
37318
37319 Ext.reg('flash', Ext.FlashComponent);
37320 Ext.FlashEventProxy = {
37321     onEvent : function(id, e){
37322         var fp = Ext.getCmp(id);
37323         if(fp){
37324             fp.onFlashEvent(e);
37325         }else{
37326             arguments.callee.defer(10, this, [id, e]);
37327         }
37328     }
37329 };
37330
37331  Ext.chart.Chart = Ext.extend(Ext.FlashComponent, {
37332     refreshBuffer: 100,
37333
37334     
37335
37336     
37337     chartStyle: {
37338         padding: 10,
37339         animationEnabled: true,
37340         font: {
37341             name: 'Tahoma',
37342             color: 0x444444,
37343             size: 11
37344         },
37345         dataTip: {
37346             padding: 5,
37347             border: {
37348                 color: 0x99bbe8,
37349                 size:1
37350             },
37351             background: {
37352                 color: 0xDAE7F6,
37353                 alpha: .9
37354             },
37355             font: {
37356                 name: 'Tahoma',
37357                 color: 0x15428B,
37358                 size: 10,
37359                 bold: true
37360             }
37361         }
37362     },
37363
37364     
37365
37366     
37367     extraStyle: null,
37368
37369     
37370     seriesStyles: null,
37371
37372     
37373     disableCaching: Ext.isIE || Ext.isOpera,
37374     disableCacheParam: '_dc',
37375
37376     initComponent : function(){
37377         Ext.chart.Chart.superclass.initComponent.call(this);
37378         if(!this.url){
37379             this.url = Ext.chart.Chart.CHART_URL;
37380         }
37381         if(this.disableCaching){
37382             this.url = Ext.urlAppend(this.url, String.format('{0}={1}', this.disableCacheParam, new Date().getTime()));
37383         }
37384         this.addEvents(
37385             'itemmouseover',
37386             'itemmouseout',
37387             'itemclick',
37388             'itemdoubleclick',
37389             'itemdragstart',
37390             'itemdrag',
37391             'itemdragend',
37392             
37393             'beforerefresh',
37394             
37395             'refresh'
37396         );
37397         this.store = Ext.StoreMgr.lookup(this.store);
37398     },
37399
37400     
37401      setStyle: function(name, value){
37402          this.swf.setStyle(name, Ext.encode(value));
37403      },
37404
37405     
37406     setStyles: function(styles){
37407         this.swf.setStyles(Ext.encode(styles));
37408     },
37409
37410     
37411     setSeriesStyles: function(styles){
37412         this.seriesStyles = styles;
37413         var s = [];
37414         Ext.each(styles, function(style){
37415             s.push(Ext.encode(style));
37416         });
37417         this.swf.setSeriesStyles(s);
37418     },
37419
37420     setCategoryNames : function(names){
37421         this.swf.setCategoryNames(names);
37422     },
37423
37424     setLegendRenderer : function(fn, scope){
37425         var chart = this;
37426         scope = scope || chart;
37427         chart.removeFnProxy(chart.legendFnName);
37428         chart.legendFnName = chart.createFnProxy(function(name){
37429             return fn.call(scope, name);
37430         });
37431         chart.swf.setLegendLabelFunction(chart.legendFnName);
37432     },
37433
37434     setTipRenderer : function(fn, scope){
37435         var chart = this;
37436         scope = scope || chart;
37437         chart.removeFnProxy(chart.tipFnName);
37438         chart.tipFnName = chart.createFnProxy(function(item, index, series){
37439             var record = chart.store.getAt(index);
37440             return fn.call(scope, chart, record, index, series);
37441         });
37442         chart.swf.setDataTipFunction(chart.tipFnName);
37443     },
37444
37445     setSeries : function(series){
37446         this.series = series;
37447         this.refresh();
37448     },
37449
37450     
37451     bindStore : function(store, initial){
37452         if(!initial && this.store){
37453             if(store !== this.store && this.store.autoDestroy){
37454                 this.store.destroy();
37455             }else{
37456                 this.store.un("datachanged", this.refresh, this);
37457                 this.store.un("add", this.delayRefresh, this);
37458                 this.store.un("remove", this.delayRefresh, this);
37459                 this.store.un("update", this.delayRefresh, this);
37460                 this.store.un("clear", this.refresh, this);
37461             }
37462         }
37463         if(store){
37464             store = Ext.StoreMgr.lookup(store);
37465             store.on({
37466                 scope: this,
37467                 datachanged: this.refresh,
37468                 add: this.delayRefresh,
37469                 remove: this.delayRefresh,
37470                 update: this.delayRefresh,
37471                 clear: this.refresh
37472             });
37473         }
37474         this.store = store;
37475         if(store && !initial){
37476             this.refresh();
37477         }
37478     },
37479
37480     onSwfReady : function(isReset){
37481         Ext.chart.Chart.superclass.onSwfReady.call(this, isReset);
37482         var ref;
37483         this.swf.setType(this.type);
37484
37485         if(this.chartStyle){
37486             this.setStyles(Ext.apply({}, this.extraStyle, this.chartStyle));
37487         }
37488
37489         if(this.categoryNames){
37490             this.setCategoryNames(this.categoryNames);
37491         }
37492
37493         if(this.tipRenderer){
37494             ref = this.getFunctionRef(this.tipRenderer);
37495             this.setTipRenderer(ref.fn, ref.scope);
37496         }
37497         if(this.legendRenderer){
37498             ref = this.getFunctionRef(this.legendRenderer);
37499             this.setLegendRenderer(ref.fn, ref.scope);
37500         }
37501         if(!isReset){
37502             this.bindStore(this.store, true);
37503         }
37504         this.refresh.defer(10, this);
37505     },
37506
37507     delayRefresh : function(){
37508         if(!this.refreshTask){
37509             this.refreshTask = new Ext.util.DelayedTask(this.refresh, this);
37510         }
37511         this.refreshTask.delay(this.refreshBuffer);
37512     },
37513
37514     refresh : function(){
37515         if(this.fireEvent('beforerefresh', this) !== false){
37516             var styleChanged = false;
37517             
37518             var data = [], rs = this.store.data.items;
37519             for(var j = 0, len = rs.length; j < len; j++){
37520                 data[j] = rs[j].data;
37521             }
37522             
37523             
37524             var dataProvider = [];
37525             var seriesCount = 0;
37526             var currentSeries = null;
37527             var i = 0;
37528             if(this.series){
37529                 seriesCount = this.series.length;
37530                 for(i = 0; i < seriesCount; i++){
37531                     currentSeries = this.series[i];
37532                     var clonedSeries = {};
37533                     for(var prop in currentSeries){
37534                         if(prop == "style" && currentSeries.style !== null){
37535                             clonedSeries.style = Ext.encode(currentSeries.style);
37536                             styleChanged = true;
37537                             
37538                             
37539                             
37540                             
37541                         } else{
37542                             clonedSeries[prop] = currentSeries[prop];
37543                         }
37544                     }
37545                     dataProvider.push(clonedSeries);
37546                 }
37547             }
37548
37549             if(seriesCount > 0){
37550                 for(i = 0; i < seriesCount; i++){
37551                     currentSeries = dataProvider[i];
37552                     if(!currentSeries.type){
37553                         currentSeries.type = this.type;
37554                     }
37555                     currentSeries.dataProvider = data;
37556                 }
37557             } else{
37558                 dataProvider.push({type: this.type, dataProvider: data});
37559             }
37560             this.swf.setDataProvider(dataProvider);
37561             if(this.seriesStyles){
37562                 this.setSeriesStyles(this.seriesStyles);
37563             }
37564             this.fireEvent('refresh', this);
37565         }
37566     },
37567
37568     
37569     createFnProxy : function(fn){
37570         var fnName = 'extFnProxy' + (++Ext.chart.Chart.PROXY_FN_ID);
37571         Ext.chart.Chart.proxyFunction[fnName] = fn;
37572         return 'Ext.chart.Chart.proxyFunction.' + fnName;
37573     },
37574
37575     
37576     removeFnProxy : function(fn){
37577         if(!Ext.isEmpty(fn)){
37578             fn = fn.replace('Ext.chart.Chart.proxyFunction.', '');
37579             delete Ext.chart.Chart.proxyFunction[fn];
37580         }
37581     },
37582
37583     
37584     getFunctionRef : function(val){
37585         if(Ext.isFunction(val)){
37586             return {
37587                 fn: val,
37588                 scope: this
37589             };
37590         }else{
37591             return {
37592                 fn: val.fn,
37593                 scope: val.scope || this
37594             };
37595         }
37596     },
37597
37598     
37599     onDestroy: function(){
37600         if (this.refreshTask && this.refreshTask.cancel){
37601             this.refreshTask.cancel();
37602         }
37603         Ext.chart.Chart.superclass.onDestroy.call(this);
37604         this.bindStore(null);
37605         this.removeFnProxy(this.tipFnName);
37606         this.removeFnProxy(this.legendFnName);
37607     }
37608 });
37609 Ext.reg('chart', Ext.chart.Chart);
37610 Ext.chart.Chart.PROXY_FN_ID = 0;
37611 Ext.chart.Chart.proxyFunction = {};
37612
37613
37614 Ext.chart.Chart.CHART_URL = 'http:/' + '/yui.yahooapis.com/2.8.0/build/charts/assets/charts.swf';
37615
37616
37617 Ext.chart.PieChart = Ext.extend(Ext.chart.Chart, {
37618     type: 'pie',
37619
37620     onSwfReady : function(isReset){
37621         Ext.chart.PieChart.superclass.onSwfReady.call(this, isReset);
37622
37623         this.setDataField(this.dataField);
37624         this.setCategoryField(this.categoryField);
37625     },
37626
37627     setDataField : function(field){
37628         this.dataField = field;
37629         this.swf.setDataField(field);
37630     },
37631
37632     setCategoryField : function(field){
37633         this.categoryField = field;
37634         this.swf.setCategoryField(field);
37635     }
37636 });
37637 Ext.reg('piechart', Ext.chart.PieChart);
37638
37639
37640 Ext.chart.CartesianChart = Ext.extend(Ext.chart.Chart, {
37641     onSwfReady : function(isReset){
37642         Ext.chart.CartesianChart.superclass.onSwfReady.call(this, isReset);
37643         this.labelFn = [];
37644         if(this.xField){
37645             this.setXField(this.xField);
37646         }
37647         if(this.yField){
37648             this.setYField(this.yField);
37649         }
37650         if(this.xAxis){
37651             this.setXAxis(this.xAxis);
37652         }
37653         if(this.xAxes){
37654             this.setXAxes(this.xAxes);
37655         }
37656         if(this.yAxis){
37657             this.setYAxis(this.yAxis);
37658         }
37659         if(this.yAxes){
37660             this.setYAxes(this.yAxes);
37661         }
37662         if(Ext.isDefined(this.constrainViewport)){
37663             this.swf.setConstrainViewport(this.constrainViewport);
37664         }
37665     },
37666
37667     setXField : function(value){
37668         this.xField = value;
37669         this.swf.setHorizontalField(value);
37670     },
37671
37672     setYField : function(value){
37673         this.yField = value;
37674         this.swf.setVerticalField(value);
37675     },
37676
37677     setXAxis : function(value){
37678         this.xAxis = this.createAxis('xAxis', value);
37679         this.swf.setHorizontalAxis(this.xAxis);
37680     },
37681
37682     setXAxes : function(value){
37683         var axis;
37684         for(var i = 0; i < value.length; i++) {
37685             axis = this.createAxis('xAxis' + i, value[i]);
37686             this.swf.setHorizontalAxis(axis);
37687         }
37688     },
37689
37690     setYAxis : function(value){
37691         this.yAxis = this.createAxis('yAxis', value);
37692         this.swf.setVerticalAxis(this.yAxis);
37693     },
37694
37695     setYAxes : function(value){
37696         var axis;
37697         for(var i = 0; i < value.length; i++) {
37698             axis = this.createAxis('yAxis' + i, value[i]);
37699             this.swf.setVerticalAxis(axis);
37700         }
37701     },
37702
37703     createAxis : function(axis, value){
37704         var o = Ext.apply({}, value),
37705             ref,
37706             old;
37707
37708         if(this[axis]){
37709             old = this[axis].labelFunction;
37710             this.removeFnProxy(old);
37711             this.labelFn.remove(old);
37712         }
37713         if(o.labelRenderer){
37714             ref = this.getFunctionRef(o.labelRenderer);
37715             o.labelFunction = this.createFnProxy(function(v){
37716                 return ref.fn.call(ref.scope, v);
37717             });
37718             delete o.labelRenderer;
37719             this.labelFn.push(o.labelFunction);
37720         }
37721         if(axis.indexOf('xAxis') > -1 && o.position == 'left'){
37722             o.position = 'bottom';
37723         }
37724         return o;
37725     },
37726
37727     onDestroy : function(){
37728         Ext.chart.CartesianChart.superclass.onDestroy.call(this);
37729         Ext.each(this.labelFn, function(fn){
37730             this.removeFnProxy(fn);
37731         }, this);
37732     }
37733 });
37734 Ext.reg('cartesianchart', Ext.chart.CartesianChart);
37735
37736
37737 Ext.chart.LineChart = Ext.extend(Ext.chart.CartesianChart, {
37738     type: 'line'
37739 });
37740 Ext.reg('linechart', Ext.chart.LineChart);
37741
37742
37743 Ext.chart.ColumnChart = Ext.extend(Ext.chart.CartesianChart, {
37744     type: 'column'
37745 });
37746 Ext.reg('columnchart', Ext.chart.ColumnChart);
37747
37748
37749 Ext.chart.StackedColumnChart = Ext.extend(Ext.chart.CartesianChart, {
37750     type: 'stackcolumn'
37751 });
37752 Ext.reg('stackedcolumnchart', Ext.chart.StackedColumnChart);
37753
37754
37755 Ext.chart.BarChart = Ext.extend(Ext.chart.CartesianChart, {
37756     type: 'bar'
37757 });
37758 Ext.reg('barchart', Ext.chart.BarChart);
37759
37760
37761 Ext.chart.StackedBarChart = Ext.extend(Ext.chart.CartesianChart, {
37762     type: 'stackbar'
37763 });
37764 Ext.reg('stackedbarchart', Ext.chart.StackedBarChart);
37765
37766
37767
37768
37769 Ext.chart.Axis = function(config){
37770     Ext.apply(this, config);
37771 };
37772
37773 Ext.chart.Axis.prototype =
37774 {
37775     
37776     type: null,
37777
37778     
37779     orientation: "horizontal",
37780
37781     
37782     reverse: false,
37783
37784     
37785     labelFunction: null,
37786
37787     
37788     hideOverlappingLabels: true,
37789
37790     
37791     labelSpacing: 2
37792 };
37793
37794
37795 Ext.chart.NumericAxis = Ext.extend(Ext.chart.Axis, {
37796     type: "numeric",
37797
37798     
37799     minimum: NaN,
37800
37801     
37802     maximum: NaN,
37803
37804     
37805     majorUnit: NaN,
37806
37807     
37808     minorUnit: NaN,
37809
37810     
37811     snapToUnits: true,
37812
37813     
37814     alwaysShowZero: true,
37815
37816     
37817     scale: "linear",
37818
37819     
37820     roundMajorUnit: true,
37821
37822     
37823     calculateByLabelSize: true,
37824
37825     
37826     position: 'left',
37827
37828     
37829     adjustMaximumByMajorUnit: true,
37830
37831     
37832     adjustMinimumByMajorUnit: true
37833
37834 });
37835
37836
37837 Ext.chart.TimeAxis = Ext.extend(Ext.chart.Axis, {
37838     type: "time",
37839
37840     
37841     minimum: null,
37842
37843     
37844     maximum: null,
37845
37846     
37847     majorUnit: NaN,
37848
37849     
37850     majorTimeUnit: null,
37851
37852     
37853     minorUnit: NaN,
37854
37855     
37856     minorTimeUnit: null,
37857
37858     
37859     snapToUnits: true,
37860
37861     
37862     stackingEnabled: false,
37863
37864     
37865     calculateByLabelSize: true
37866
37867 });
37868
37869
37870 Ext.chart.CategoryAxis = Ext.extend(Ext.chart.Axis, {
37871     type: "category",
37872
37873     
37874     categoryNames: null,
37875
37876     
37877     calculateCategoryCount: false
37878
37879 });
37880
37881
37882 Ext.chart.Series = function(config) { Ext.apply(this, config); };
37883
37884 Ext.chart.Series.prototype =
37885 {
37886     
37887     type: null,
37888
37889     
37890     displayName: null
37891 };
37892
37893
37894 Ext.chart.CartesianSeries = Ext.extend(Ext.chart.Series, {
37895     
37896     xField: null,
37897
37898     
37899     yField: null,
37900
37901     
37902     showInLegend: true,
37903
37904     
37905     axis: 'primary'
37906 });
37907
37908
37909 Ext.chart.ColumnSeries = Ext.extend(Ext.chart.CartesianSeries, {
37910     type: "column"
37911 });
37912
37913
37914 Ext.chart.LineSeries = Ext.extend(Ext.chart.CartesianSeries, {
37915     type: "line"
37916 });
37917
37918
37919 Ext.chart.BarSeries = Ext.extend(Ext.chart.CartesianSeries, {
37920     type: "bar"
37921 });
37922
37923
37924
37925 Ext.chart.PieSeries = Ext.extend(Ext.chart.Series, {
37926     type: "pie",
37927     dataField: null,
37928     categoryField: null
37929 });
37930 Ext.menu.Menu = Ext.extend(Ext.Container, {
37931     
37932     
37933     
37934     minWidth : 120,
37935     
37936     shadow : 'sides',
37937     
37938     subMenuAlign : 'tl-tr?',
37939     
37940     defaultAlign : 'tl-bl?',
37941     
37942     allowOtherMenus : false,
37943     
37944     ignoreParentClicks : false,
37945     
37946     enableScrolling : true,
37947     
37948     maxHeight : null,
37949     
37950     scrollIncrement : 24,
37951     
37952     showSeparator : true,
37953     
37954     defaultOffsets : [0, 0],
37955
37956     
37957     plain : false,
37958
37959     
37960     floating : true,
37961
37962
37963     
37964     zIndex: 15000,
37965
37966     
37967     hidden : true,
37968
37969     
37970     layout : 'menu',
37971     hideMode : 'offsets',    
37972     scrollerHeight : 8,
37973     autoLayout : true,       
37974     defaultType : 'menuitem',
37975     bufferResize : false,
37976
37977     initComponent : function(){
37978         if(Ext.isArray(this.initialConfig)){
37979             Ext.apply(this, {items:this.initialConfig});
37980         }
37981         this.addEvents(
37982             
37983             'click',
37984             
37985             'mouseover',
37986             
37987             'mouseout',
37988             
37989             'itemclick'
37990         );
37991         Ext.menu.MenuMgr.register(this);
37992         if(this.floating){
37993             Ext.EventManager.onWindowResize(this.hide, this);
37994         }else{
37995             if(this.initialConfig.hidden !== false){
37996                 this.hidden = false;
37997             }
37998             this.internalDefaults = {hideOnClick: false};
37999         }
38000         Ext.menu.Menu.superclass.initComponent.call(this);
38001         if(this.autoLayout){
38002             var fn = this.doLayout.createDelegate(this, []);
38003             this.on({
38004                 add: fn,
38005                 remove: fn
38006             });
38007         }
38008     },
38009
38010     
38011     getLayoutTarget : function() {
38012         return this.ul;
38013     },
38014
38015     
38016     onRender : function(ct, position){
38017         if(!ct){
38018             ct = Ext.getBody();
38019         }
38020
38021         var dh = {
38022             id: this.getId(),
38023             cls: 'x-menu ' + ((this.floating) ? 'x-menu-floating x-layer ' : '') + (this.cls || '') + (this.plain ? ' x-menu-plain' : '') + (this.showSeparator ? '' : ' x-menu-nosep'),
38024             style: this.style,
38025             cn: [
38026                 {tag: 'a', cls: 'x-menu-focus', href: '#', onclick: 'return false;', tabIndex: '-1'},
38027                 {tag: 'ul', cls: 'x-menu-list'}
38028             ]
38029         };
38030         if(this.floating){
38031             this.el = new Ext.Layer({
38032                 shadow: this.shadow,
38033                 dh: dh,
38034                 constrain: false,
38035                 parentEl: ct,
38036                 zindex: this.zIndex
38037             });
38038         }else{
38039             this.el = ct.createChild(dh);
38040         }
38041         Ext.menu.Menu.superclass.onRender.call(this, ct, position);
38042
38043         if(!this.keyNav){
38044             this.keyNav = new Ext.menu.MenuNav(this);
38045         }
38046         
38047         this.focusEl = this.el.child('a.x-menu-focus');
38048         this.ul = this.el.child('ul.x-menu-list');
38049         this.mon(this.ul, {
38050             scope: this,
38051             click: this.onClick,
38052             mouseover: this.onMouseOver,
38053             mouseout: this.onMouseOut
38054         });
38055         if(this.enableScrolling){
38056             this.mon(this.el, {
38057                 scope: this,
38058                 delegate: '.x-menu-scroller',
38059                 click: this.onScroll,
38060                 mouseover: this.deactivateActive
38061             });
38062         }
38063     },
38064
38065     
38066     findTargetItem : function(e){
38067         var t = e.getTarget('.x-menu-list-item', this.ul, true);
38068         if(t && t.menuItemId){
38069             return this.items.get(t.menuItemId);
38070         }
38071     },
38072
38073     
38074     onClick : function(e){
38075         var t = this.findTargetItem(e);
38076         if(t){
38077             if(t.isFormField){
38078                 this.setActiveItem(t);
38079             }else if(t instanceof Ext.menu.BaseItem){
38080                 if(t.menu && this.ignoreParentClicks){
38081                     t.expandMenu();
38082                     e.preventDefault();
38083                 }else if(t.onClick){
38084                     t.onClick(e);
38085                     this.fireEvent('click', this, t, e);
38086                 }
38087             }
38088         }
38089     },
38090
38091     
38092     setActiveItem : function(item, autoExpand){
38093         if(item != this.activeItem){
38094             this.deactivateActive();
38095             if((this.activeItem = item).isFormField){
38096                 item.focus();
38097             }else{
38098                 item.activate(autoExpand);
38099             }
38100         }else if(autoExpand){
38101             item.expandMenu();
38102         }
38103     },
38104
38105     deactivateActive : function(){
38106         var a = this.activeItem;
38107         if(a){
38108             if(a.isFormField){
38109                 
38110                 if(a.collapse){
38111                     a.collapse();
38112                 }
38113             }else{
38114                 a.deactivate();
38115             }
38116             delete this.activeItem;
38117         }
38118     },
38119
38120     
38121     tryActivate : function(start, step){
38122         var items = this.items;
38123         for(var i = start, len = items.length; i >= 0 && i < len; i+= step){
38124             var item = items.get(i);
38125             if(item.isVisible() && !item.disabled && (item.canActivate || item.isFormField)){
38126                 this.setActiveItem(item, false);
38127                 return item;
38128             }
38129         }
38130         return false;
38131     },
38132
38133     
38134     onMouseOver : function(e){
38135         var t = this.findTargetItem(e);
38136         if(t){
38137             if(t.canActivate && !t.disabled){
38138                 this.setActiveItem(t, true);
38139             }
38140         }
38141         this.over = true;
38142         this.fireEvent('mouseover', this, e, t);
38143     },
38144
38145     
38146     onMouseOut : function(e){
38147         var t = this.findTargetItem(e);
38148         if(t){
38149             if(t == this.activeItem && t.shouldDeactivate && t.shouldDeactivate(e)){
38150                 this.activeItem.deactivate();
38151                 delete this.activeItem;
38152             }
38153         }
38154         this.over = false;
38155         this.fireEvent('mouseout', this, e, t);
38156     },
38157
38158     
38159     onScroll : function(e, t){
38160         if(e){
38161             e.stopEvent();
38162         }
38163         var ul = this.ul.dom, top = Ext.fly(t).is('.x-menu-scroller-top');
38164         ul.scrollTop += this.scrollIncrement * (top ? -1 : 1);
38165         if(top ? ul.scrollTop <= 0 : ul.scrollTop + this.activeMax >= ul.scrollHeight){
38166            this.onScrollerOut(null, t);
38167         }
38168     },
38169
38170     
38171     onScrollerIn : function(e, t){
38172         var ul = this.ul.dom, top = Ext.fly(t).is('.x-menu-scroller-top');
38173         if(top ? ul.scrollTop > 0 : ul.scrollTop + this.activeMax < ul.scrollHeight){
38174             Ext.fly(t).addClass(['x-menu-item-active', 'x-menu-scroller-active']);
38175         }
38176     },
38177
38178     
38179     onScrollerOut : function(e, t){
38180         Ext.fly(t).removeClass(['x-menu-item-active', 'x-menu-scroller-active']);
38181     },
38182
38183     
38184     show : function(el, pos, parentMenu){
38185         if(this.floating){
38186             this.parentMenu = parentMenu;
38187             if(!this.el){
38188                 this.render();
38189                 this.doLayout(false, true);
38190             }
38191             this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign, this.defaultOffsets), parentMenu);
38192         }else{
38193             Ext.menu.Menu.superclass.show.call(this);
38194         }
38195     },
38196
38197     
38198     showAt : function(xy, parentMenu){
38199         if(this.fireEvent('beforeshow', this) !== false){
38200             this.parentMenu = parentMenu;
38201             if(!this.el){
38202                 this.render();
38203             }
38204             if(this.enableScrolling){
38205                 
38206                 this.el.setXY(xy);
38207                 
38208                 xy[1] = this.constrainScroll(xy[1]);
38209                 xy = [this.el.adjustForConstraints(xy)[0], xy[1]];
38210             }else{
38211                 
38212                 xy = this.el.adjustForConstraints(xy);
38213             }
38214             this.el.setXY(xy);
38215             this.el.show();
38216             Ext.menu.Menu.superclass.onShow.call(this);
38217             if(Ext.isIE){
38218                 
38219                 this.fireEvent('autosize', this);
38220                 if(!Ext.isIE8){
38221                     this.el.repaint();
38222                 }
38223             }
38224             this.hidden = false;
38225             this.focus();
38226             this.fireEvent('show', this);
38227         }
38228     },
38229
38230     constrainScroll : function(y){
38231         var max, full = this.ul.setHeight('auto').getHeight(),
38232             returnY = y, normalY, parentEl, scrollTop, viewHeight;
38233         if(this.floating){
38234             parentEl = Ext.fly(this.el.dom.parentNode);
38235             scrollTop = parentEl.getScroll().top;
38236             viewHeight = parentEl.getViewSize().height;
38237             
38238             
38239             normalY = y - scrollTop;
38240             max = this.maxHeight ? this.maxHeight : viewHeight - normalY;
38241             if(full > viewHeight) {
38242                 max = viewHeight;
38243                 
38244                 returnY = y - normalY;
38245             } else if(max < full) {
38246                 returnY = y - (full - max);
38247                 max = full;
38248             }
38249         }else{
38250             max = this.getHeight();
38251         }
38252         
38253         if (this.maxHeight){
38254             max = Math.min(this.maxHeight, max);
38255         }
38256         if(full > max && max > 0){
38257             this.activeMax = max - this.scrollerHeight * 2 - this.el.getFrameWidth('tb') - Ext.num(this.el.shadowOffset, 0);
38258             this.ul.setHeight(this.activeMax);
38259             this.createScrollers();
38260             this.el.select('.x-menu-scroller').setDisplayed('');
38261         }else{
38262             this.ul.setHeight(full);
38263             this.el.select('.x-menu-scroller').setDisplayed('none');
38264         }
38265         this.ul.dom.scrollTop = 0;
38266         return returnY;
38267     },
38268
38269     createScrollers : function(){
38270         if(!this.scroller){
38271             this.scroller = {
38272                 pos: 0,
38273                 top: this.el.insertFirst({
38274                     tag: 'div',
38275                     cls: 'x-menu-scroller x-menu-scroller-top',
38276                     html: '&#160;'
38277                 }),
38278                 bottom: this.el.createChild({
38279                     tag: 'div',
38280                     cls: 'x-menu-scroller x-menu-scroller-bottom',
38281                     html: '&#160;'
38282                 })
38283             };
38284             this.scroller.top.hover(this.onScrollerIn, this.onScrollerOut, this);
38285             this.scroller.topRepeater = new Ext.util.ClickRepeater(this.scroller.top, {
38286                 listeners: {
38287                     click: this.onScroll.createDelegate(this, [null, this.scroller.top], false)
38288                 }
38289             });
38290             this.scroller.bottom.hover(this.onScrollerIn, this.onScrollerOut, this);
38291             this.scroller.bottomRepeater = new Ext.util.ClickRepeater(this.scroller.bottom, {
38292                 listeners: {
38293                     click: this.onScroll.createDelegate(this, [null, this.scroller.bottom], false)
38294                 }
38295             });
38296         }
38297     },
38298
38299     onLayout : function(){
38300         if(this.isVisible()){
38301             if(this.enableScrolling){
38302                 this.constrainScroll(this.el.getTop());
38303             }
38304             if(this.floating){
38305                 this.el.sync();
38306             }
38307         }
38308     },
38309
38310     focus : function(){
38311         if(!this.hidden){
38312             this.doFocus.defer(50, this);
38313         }
38314     },
38315
38316     doFocus : function(){
38317         if(!this.hidden){
38318             this.focusEl.focus();
38319         }
38320     },
38321
38322     
38323     hide : function(deep){
38324         if (!this.isDestroyed) {
38325             this.deepHide = deep;
38326             Ext.menu.Menu.superclass.hide.call(this);
38327             delete this.deepHide;
38328         }
38329     },
38330
38331     
38332     onHide : function(){
38333         Ext.menu.Menu.superclass.onHide.call(this);
38334         this.deactivateActive();
38335         if(this.el && this.floating){
38336             this.el.hide();
38337         }
38338         var pm = this.parentMenu;
38339         if(this.deepHide === true && pm){
38340             if(pm.floating){
38341                 pm.hide(true);
38342             }else{
38343                 pm.deactivateActive();
38344             }
38345         }
38346     },
38347
38348     
38349     lookupComponent : function(c){
38350          if(Ext.isString(c)){
38351             c = (c == 'separator' || c == '-') ? new Ext.menu.Separator() : new Ext.menu.TextItem(c);
38352              this.applyDefaults(c);
38353          }else{
38354             if(Ext.isObject(c)){
38355                 c = this.getMenuItem(c);
38356             }else if(c.tagName || c.el){ 
38357                 c = new Ext.BoxComponent({
38358                     el: c
38359                 });
38360             }
38361          }
38362          return c;
38363     },
38364
38365     applyDefaults : function(c) {
38366         if (!Ext.isString(c)) {
38367             c = Ext.menu.Menu.superclass.applyDefaults.call(this, c);
38368             var d = this.internalDefaults;
38369             if(d){
38370                 if(c.events){
38371                     Ext.applyIf(c.initialConfig, d);
38372                     Ext.apply(c, d);
38373                 }else{
38374                     Ext.applyIf(c, d);
38375                 }
38376             }
38377         }
38378         return c;
38379     },
38380
38381     
38382     getMenuItem : function(config) {
38383         if (!config.isXType) {
38384             if (!config.xtype && Ext.isBoolean(config.checked)) {
38385                 return new Ext.menu.CheckItem(config);
38386             }
38387             return Ext.create(config, this.defaultType);
38388         }
38389         return config;
38390     },
38391
38392     
38393     addSeparator : function() {
38394         return this.add(new Ext.menu.Separator());
38395     },
38396
38397     
38398     addElement : function(el) {
38399         return this.add(new Ext.menu.BaseItem({
38400             el: el
38401         }));
38402     },
38403
38404     
38405     addItem : function(item) {
38406         return this.add(item);
38407     },
38408
38409     
38410     addMenuItem : function(config) {
38411         return this.add(this.getMenuItem(config));
38412     },
38413
38414     
38415     addText : function(text){
38416         return this.add(new Ext.menu.TextItem(text));
38417     },
38418
38419     
38420     onDestroy : function(){
38421         Ext.EventManager.removeResizeListener(this.hide, this);
38422         var pm = this.parentMenu;
38423         if(pm && pm.activeChild == this){
38424             delete pm.activeChild;
38425         }
38426         delete this.parentMenu;
38427         Ext.menu.Menu.superclass.onDestroy.call(this);
38428         Ext.menu.MenuMgr.unregister(this);
38429         if(this.keyNav) {
38430             this.keyNav.disable();
38431         }
38432         var s = this.scroller;
38433         if(s){
38434             Ext.destroy(s.topRepeater, s.bottomRepeater, s.top, s.bottom);
38435         }
38436         Ext.destroy(
38437             this.el,
38438             this.focusEl,
38439             this.ul
38440         );
38441     }
38442 });
38443
38444 Ext.reg('menu', Ext.menu.Menu);
38445
38446
38447 Ext.menu.MenuNav = Ext.extend(Ext.KeyNav, function(){
38448     function up(e, m){
38449         if(!m.tryActivate(m.items.indexOf(m.activeItem)-1, -1)){
38450             m.tryActivate(m.items.length-1, -1);
38451         }
38452     }
38453     function down(e, m){
38454         if(!m.tryActivate(m.items.indexOf(m.activeItem)+1, 1)){
38455             m.tryActivate(0, 1);
38456         }
38457     }
38458     return {
38459         constructor : function(menu){
38460             Ext.menu.MenuNav.superclass.constructor.call(this, menu.el);
38461             this.scope = this.menu = menu;
38462         },
38463
38464         doRelay : function(e, h){
38465             var k = e.getKey();
38466
38467             if (this.menu.activeItem && this.menu.activeItem.isFormField && k != e.TAB) {
38468                 return false;
38469             }
38470             if(!this.menu.activeItem && e.isNavKeyPress() && k != e.SPACE && k != e.RETURN){
38471                 this.menu.tryActivate(0, 1);
38472                 return false;
38473             }
38474             return h.call(this.scope || this, e, this.menu);
38475         },
38476
38477         tab: function(e, m) {
38478             e.stopEvent();
38479             if (e.shiftKey) {
38480                 up(e, m);
38481             } else {
38482                 down(e, m);
38483             }
38484         },
38485
38486         up : up,
38487
38488         down : down,
38489
38490         right : function(e, m){
38491             if(m.activeItem){
38492                 m.activeItem.expandMenu(true);
38493             }
38494         },
38495
38496         left : function(e, m){
38497             m.hide();
38498             if(m.parentMenu && m.parentMenu.activeItem){
38499                 m.parentMenu.activeItem.activate();
38500             }
38501         },
38502
38503         enter : function(e, m){
38504             if(m.activeItem){
38505                 e.stopPropagation();
38506                 m.activeItem.onClick(e);
38507                 m.fireEvent('click', this, m.activeItem);
38508                 return true;
38509             }
38510         }
38511     };
38512 }());
38513
38514 Ext.menu.MenuMgr = function(){
38515    var menus, active, groups = {}, attached = false, lastShow = new Date();
38516
38517    
38518    function init(){
38519        menus = {};
38520        active = new Ext.util.MixedCollection();
38521        Ext.getDoc().addKeyListener(27, function(){
38522            if(active.length > 0){
38523                hideAll();
38524            }
38525        });
38526    }
38527
38528    
38529    function hideAll(){
38530        if(active && active.length > 0){
38531            var c = active.clone();
38532            c.each(function(m){
38533                m.hide();
38534            });
38535            return true;
38536        }
38537        return false;
38538    }
38539
38540    
38541    function onHide(m){
38542        active.remove(m);
38543        if(active.length < 1){
38544            Ext.getDoc().un("mousedown", onMouseDown);
38545            attached = false;
38546        }
38547    }
38548
38549    
38550    function onShow(m){
38551        var last = active.last();
38552        lastShow = new Date();
38553        active.add(m);
38554        if(!attached){
38555            Ext.getDoc().on("mousedown", onMouseDown);
38556            attached = true;
38557        }
38558        if(m.parentMenu){
38559           m.getEl().setZIndex(parseInt(m.parentMenu.getEl().getStyle("z-index"), 10) + 3);
38560           m.parentMenu.activeChild = m;
38561        }else if(last && !last.isDestroyed && last.isVisible()){
38562           m.getEl().setZIndex(parseInt(last.getEl().getStyle("z-index"), 10) + 3);
38563        }
38564    }
38565
38566    
38567    function onBeforeHide(m){
38568        if(m.activeChild){
38569            m.activeChild.hide();
38570        }
38571        if(m.autoHideTimer){
38572            clearTimeout(m.autoHideTimer);
38573            delete m.autoHideTimer;
38574        }
38575    }
38576
38577    
38578    function onBeforeShow(m){
38579        var pm = m.parentMenu;
38580        if(!pm && !m.allowOtherMenus){
38581            hideAll();
38582        }else if(pm && pm.activeChild){
38583            pm.activeChild.hide();
38584        }
38585    }
38586
38587    
38588    function onMouseDown(e){
38589        if(lastShow.getElapsed() > 50 && active.length > 0 && !e.getTarget(".x-menu")){
38590            hideAll();
38591        }
38592    }
38593
38594    return {
38595
38596        
38597        hideAll : function(){
38598             return hideAll();
38599        },
38600
38601        
38602        register : function(menu){
38603            if(!menus){
38604                init();
38605            }
38606            menus[menu.id] = menu;
38607            menu.on({
38608                beforehide: onBeforeHide,
38609                hide: onHide,
38610                beforeshow: onBeforeShow,
38611                show: onShow
38612            });
38613        },
38614
38615         
38616        get : function(menu){
38617            if(typeof menu == "string"){ 
38618                if(!menus){  
38619                    return null;
38620                }
38621                return menus[menu];
38622            }else if(menu.events){  
38623                return menu;
38624            }else if(typeof menu.length == 'number'){ 
38625                return new Ext.menu.Menu({items:menu});
38626            }else{ 
38627                return Ext.create(menu, 'menu');
38628            }
38629        },
38630
38631        
38632        unregister : function(menu){
38633            delete menus[menu.id];
38634            menu.un("beforehide", onBeforeHide);
38635            menu.un("hide", onHide);
38636            menu.un("beforeshow", onBeforeShow);
38637            menu.un("show", onShow);
38638        },
38639
38640        
38641        registerCheckable : function(menuItem){
38642            var g = menuItem.group;
38643            if(g){
38644                if(!groups[g]){
38645                    groups[g] = [];
38646                }
38647                groups[g].push(menuItem);
38648            }
38649        },
38650
38651        
38652        unregisterCheckable : function(menuItem){
38653            var g = menuItem.group;
38654            if(g){
38655                groups[g].remove(menuItem);
38656            }
38657        },
38658        
38659        
38660        onCheckChange: function(item, state){
38661            if(item.group && state){
38662                var group = groups[item.group],
38663                    i = 0,
38664                    len = group.length,
38665                    current;
38666                    
38667                for(; i < len; i++){
38668                    current = group[i];
38669                    if(current != item){
38670                        current.setChecked(false);
38671                    }
38672                }
38673            }
38674        },
38675
38676        getCheckedItem : function(groupId){
38677            var g = groups[groupId];
38678            if(g){
38679                for(var i = 0, l = g.length; i < l; i++){
38680                    if(g[i].checked){
38681                        return g[i];
38682                    }
38683                }
38684            }
38685            return null;
38686        },
38687
38688        setCheckedItem : function(groupId, itemId){
38689            var g = groups[groupId];
38690            if(g){
38691                for(var i = 0, l = g.length; i < l; i++){
38692                    if(g[i].id == itemId){
38693                        g[i].setChecked(true);
38694                    }
38695                }
38696            }
38697            return null;
38698        }
38699    };
38700 }();
38701
38702 Ext.menu.BaseItem = Ext.extend(Ext.Component, {
38703     
38704     
38705     
38706     
38707     canActivate : false,
38708     
38709     activeClass : "x-menu-item-active",
38710     
38711     hideOnClick : true,
38712     
38713     clickHideDelay : 1,
38714
38715     
38716     ctype : "Ext.menu.BaseItem",
38717
38718     
38719     actionMode : "container",
38720
38721     initComponent : function(){
38722         Ext.menu.BaseItem.superclass.initComponent.call(this);
38723         this.addEvents(
38724             
38725             'click',
38726             
38727             'activate',
38728             
38729             'deactivate'
38730         );
38731         if(this.handler){
38732             this.on("click", this.handler, this.scope);
38733         }
38734     },
38735
38736     
38737     onRender : function(container, position){
38738         Ext.menu.BaseItem.superclass.onRender.apply(this, arguments);
38739         if(this.ownerCt && this.ownerCt instanceof Ext.menu.Menu){
38740             this.parentMenu = this.ownerCt;
38741         }else{
38742             this.container.addClass('x-menu-list-item');
38743             this.mon(this.el, {
38744                 scope: this,
38745                 click: this.onClick,
38746                 mouseenter: this.activate,
38747                 mouseleave: this.deactivate
38748             });
38749         }
38750     },
38751
38752     
38753     setHandler : function(handler, scope){
38754         if(this.handler){
38755             this.un("click", this.handler, this.scope);
38756         }
38757         this.on("click", this.handler = handler, this.scope = scope);
38758     },
38759
38760     
38761     onClick : function(e){
38762         if(!this.disabled && this.fireEvent("click", this, e) !== false
38763                 && (this.parentMenu && this.parentMenu.fireEvent("itemclick", this, e) !== false)){
38764             this.handleClick(e);
38765         }else{
38766             e.stopEvent();
38767         }
38768     },
38769
38770     
38771     activate : function(){
38772         if(this.disabled){
38773             return false;
38774         }
38775         var li = this.container;
38776         li.addClass(this.activeClass);
38777         this.region = li.getRegion().adjust(2, 2, -2, -2);
38778         this.fireEvent("activate", this);
38779         return true;
38780     },
38781
38782     
38783     deactivate : function(){
38784         this.container.removeClass(this.activeClass);
38785         this.fireEvent("deactivate", this);
38786     },
38787
38788     
38789     shouldDeactivate : function(e){
38790         return !this.region || !this.region.contains(e.getPoint());
38791     },
38792
38793     
38794     handleClick : function(e){
38795         var pm = this.parentMenu;
38796         if(this.hideOnClick){
38797             if(pm.floating){
38798                 pm.hide.defer(this.clickHideDelay, pm, [true]);
38799             }else{
38800                 pm.deactivateActive();
38801             }
38802         }
38803     },
38804
38805     
38806     expandMenu : Ext.emptyFn,
38807
38808     
38809     hideMenu : Ext.emptyFn
38810 });
38811 Ext.reg('menubaseitem', Ext.menu.BaseItem);
38812 Ext.menu.TextItem = Ext.extend(Ext.menu.BaseItem, {
38813     
38814     
38815     hideOnClick : false,
38816     
38817     itemCls : "x-menu-text",
38818     
38819     constructor : function(config) {
38820         if (typeof config == 'string') {
38821             config = {
38822                 text: config
38823             };
38824         }
38825         Ext.menu.TextItem.superclass.constructor.call(this, config);
38826     },
38827
38828     
38829     onRender : function() {
38830         var s = document.createElement("span");
38831         s.className = this.itemCls;
38832         s.innerHTML = this.text;
38833         this.el = s;
38834         Ext.menu.TextItem.superclass.onRender.apply(this, arguments);
38835     }
38836 });
38837 Ext.reg('menutextitem', Ext.menu.TextItem);
38838 Ext.menu.Separator = Ext.extend(Ext.menu.BaseItem, {
38839     
38840     itemCls : "x-menu-sep",
38841     
38842     hideOnClick : false,
38843     
38844     
38845     activeClass: '',
38846
38847     
38848     onRender : function(li){
38849         var s = document.createElement("span");
38850         s.className = this.itemCls;
38851         s.innerHTML = "&#160;";
38852         this.el = s;
38853         li.addClass("x-menu-sep-li");
38854         Ext.menu.Separator.superclass.onRender.apply(this, arguments);
38855     }
38856 });
38857 Ext.reg('menuseparator', Ext.menu.Separator);
38858 Ext.menu.Item = Ext.extend(Ext.menu.BaseItem, {
38859     
38860     
38861     
38862     
38863     
38864     
38865     
38866     
38867     itemCls : 'x-menu-item',
38868     
38869     canActivate : true,
38870     
38871     showDelay: 200,
38872     
38873     
38874     altText: '',
38875     
38876     
38877     hideDelay: 200,
38878
38879     
38880     ctype: 'Ext.menu.Item',
38881
38882     initComponent : function(){
38883         Ext.menu.Item.superclass.initComponent.call(this);
38884         if(this.menu){
38885             this.menu = Ext.menu.MenuMgr.get(this.menu);
38886             this.menu.ownerCt = this;
38887         }
38888     },
38889
38890     
38891     onRender : function(container, position){
38892         if (!this.itemTpl) {
38893             this.itemTpl = Ext.menu.Item.prototype.itemTpl = new Ext.XTemplate(
38894                 '<a id="{id}" class="{cls}" hidefocus="true" unselectable="on" href="{href}"',
38895                     '<tpl if="hrefTarget">',
38896                         ' target="{hrefTarget}"',
38897                     '</tpl>',
38898                  '>',
38899                      '<img alt="{altText}" src="{icon}" class="x-menu-item-icon {iconCls}"/>',
38900                      '<span class="x-menu-item-text">{text}</span>',
38901                  '</a>'
38902              );
38903         }
38904         var a = this.getTemplateArgs();
38905         this.el = position ? this.itemTpl.insertBefore(position, a, true) : this.itemTpl.append(container, a, true);
38906         this.iconEl = this.el.child('img.x-menu-item-icon');
38907         this.textEl = this.el.child('.x-menu-item-text');
38908         if(!this.href) { 
38909             this.mon(this.el, 'click', Ext.emptyFn, null, { preventDefault: true });
38910         }
38911         Ext.menu.Item.superclass.onRender.call(this, container, position);
38912     },
38913
38914     getTemplateArgs: function() {
38915         return {
38916             id: this.id,
38917             cls: this.itemCls + (this.menu ?  ' x-menu-item-arrow' : '') + (this.cls ?  ' ' + this.cls : ''),
38918             href: this.href || '#',
38919             hrefTarget: this.hrefTarget,
38920             icon: this.icon || Ext.BLANK_IMAGE_URL,
38921             iconCls: this.iconCls || '',
38922             text: this.itemText||this.text||'&#160;',
38923             altText: this.altText || ''
38924         };
38925     },
38926
38927     
38928     setText : function(text){
38929         this.text = text||'&#160;';
38930         if(this.rendered){
38931             this.textEl.update(this.text);
38932             this.parentMenu.layout.doAutoSize();
38933         }
38934     },
38935
38936     
38937     setIconClass : function(cls){
38938         var oldCls = this.iconCls;
38939         this.iconCls = cls;
38940         if(this.rendered){
38941             this.iconEl.replaceClass(oldCls, this.iconCls);
38942         }
38943     },
38944
38945     
38946     beforeDestroy: function(){
38947         if (this.menu){
38948             delete this.menu.ownerCt;
38949             this.menu.destroy();
38950         }
38951         Ext.menu.Item.superclass.beforeDestroy.call(this);
38952     },
38953
38954     
38955     handleClick : function(e){
38956         if(!this.href){ 
38957             e.stopEvent();
38958         }
38959         Ext.menu.Item.superclass.handleClick.apply(this, arguments);
38960     },
38961
38962     
38963     activate : function(autoExpand){
38964         if(Ext.menu.Item.superclass.activate.apply(this, arguments)){
38965             this.focus();
38966             if(autoExpand){
38967                 this.expandMenu();
38968             }
38969         }
38970         return true;
38971     },
38972
38973     
38974     shouldDeactivate : function(e){
38975         if(Ext.menu.Item.superclass.shouldDeactivate.call(this, e)){
38976             if(this.menu && this.menu.isVisible()){
38977                 return !this.menu.getEl().getRegion().contains(e.getPoint());
38978             }
38979             return true;
38980         }
38981         return false;
38982     },
38983
38984     
38985     deactivate : function(){
38986         Ext.menu.Item.superclass.deactivate.apply(this, arguments);
38987         this.hideMenu();
38988     },
38989
38990     
38991     expandMenu : function(autoActivate){
38992         if(!this.disabled && this.menu){
38993             clearTimeout(this.hideTimer);
38994             delete this.hideTimer;
38995             if(!this.menu.isVisible() && !this.showTimer){
38996                 this.showTimer = this.deferExpand.defer(this.showDelay, this, [autoActivate]);
38997             }else if (this.menu.isVisible() && autoActivate){
38998                 this.menu.tryActivate(0, 1);
38999             }
39000         }
39001     },
39002
39003     
39004     deferExpand : function(autoActivate){
39005         delete this.showTimer;
39006         this.menu.show(this.container, this.parentMenu.subMenuAlign || 'tl-tr?', this.parentMenu);
39007         if(autoActivate){
39008             this.menu.tryActivate(0, 1);
39009         }
39010     },
39011
39012     
39013     hideMenu : function(){
39014         clearTimeout(this.showTimer);
39015         delete this.showTimer;
39016         if(!this.hideTimer && this.menu && this.menu.isVisible()){
39017             this.hideTimer = this.deferHide.defer(this.hideDelay, this);
39018         }
39019     },
39020
39021     
39022     deferHide : function(){
39023         delete this.hideTimer;
39024         if(this.menu.over){
39025             this.parentMenu.setActiveItem(this, false);
39026         }else{
39027             this.menu.hide();
39028         }
39029     }
39030 });
39031 Ext.reg('menuitem', Ext.menu.Item);
39032 Ext.menu.CheckItem = Ext.extend(Ext.menu.Item, {
39033     
39034     
39035     itemCls : "x-menu-item x-menu-check-item",
39036     
39037     groupClass : "x-menu-group-item",
39038
39039     
39040     checked: false,
39041
39042     
39043     ctype: "Ext.menu.CheckItem",
39044     
39045     initComponent : function(){
39046         Ext.menu.CheckItem.superclass.initComponent.call(this);
39047             this.addEvents(
39048                 
39049                 "beforecheckchange" ,
39050                 
39051                 "checkchange"
39052             );
39053             
39054             if(this.checkHandler){
39055                 this.on('checkchange', this.checkHandler, this.scope);
39056             }
39057             Ext.menu.MenuMgr.registerCheckable(this);
39058     },
39059
39060     
39061     onRender : function(c){
39062         Ext.menu.CheckItem.superclass.onRender.apply(this, arguments);
39063         if(this.group){
39064             this.el.addClass(this.groupClass);
39065         }
39066         if(this.checked){
39067             this.checked = false;
39068             this.setChecked(true, true);
39069         }
39070     },
39071
39072     
39073     destroy : function(){
39074         Ext.menu.MenuMgr.unregisterCheckable(this);
39075         Ext.menu.CheckItem.superclass.destroy.apply(this, arguments);
39076     },
39077
39078     
39079     setChecked : function(state, suppressEvent){
39080         var suppress = suppressEvent === true;
39081         if(this.checked != state && (suppress || this.fireEvent("beforecheckchange", this, state) !== false)){
39082             Ext.menu.MenuMgr.onCheckChange(this, state);
39083             if(this.container){
39084                 this.container[state ? "addClass" : "removeClass"]("x-menu-item-checked");
39085             }
39086             this.checked = state;
39087             if(!suppress){
39088                 this.fireEvent("checkchange", this, state);
39089             }
39090         }
39091     },
39092
39093     
39094     handleClick : function(e){
39095        if(!this.disabled && !(this.checked && this.group)){
39096            this.setChecked(!this.checked);
39097        }
39098        Ext.menu.CheckItem.superclass.handleClick.apply(this, arguments);
39099     }
39100 });
39101 Ext.reg('menucheckitem', Ext.menu.CheckItem);
39102  Ext.menu.DateMenu = Ext.extend(Ext.menu.Menu, {
39103     
39104     enableScrolling : false,
39105     
39106         
39107     
39108     hideOnClick : true,
39109     
39110     
39111     pickerId : null,
39112     
39113     
39114     
39115     
39116     cls : 'x-date-menu',
39117     
39118     
39119     
39120     
39121
39122     initComponent : function(){
39123         this.on('beforeshow', this.onBeforeShow, this);
39124         if(this.strict = (Ext.isIE7 && Ext.isStrict)){
39125             this.on('show', this.onShow, this, {single: true, delay: 20});
39126         }
39127         Ext.apply(this, {
39128             plain: true,
39129             showSeparator: false,
39130             items: this.picker = new Ext.DatePicker(Ext.applyIf({
39131                 internalRender: this.strict || !Ext.isIE,
39132                 ctCls: 'x-menu-date-item',
39133                 id: this.pickerId
39134             }, this.initialConfig))
39135         });
39136         this.picker.purgeListeners();
39137         Ext.menu.DateMenu.superclass.initComponent.call(this);
39138         
39139         this.relayEvents(this.picker, ['select']);
39140         this.on('show', this.picker.focus, this.picker);
39141         this.on('select', this.menuHide, this);
39142         if(this.handler){
39143             this.on('select', this.handler, this.scope || this);
39144         }
39145     },
39146
39147     menuHide : function() {
39148         if(this.hideOnClick){
39149             this.hide(true);
39150         }
39151     },
39152
39153     onBeforeShow : function(){
39154         if(this.picker){
39155             this.picker.hideMonthPicker(true);
39156         }
39157     },
39158
39159     onShow : function(){
39160         var el = this.picker.getEl();
39161         el.setWidth(el.getWidth()); 
39162     }
39163  });
39164  Ext.reg('datemenu', Ext.menu.DateMenu);
39165  
39166  Ext.menu.ColorMenu = Ext.extend(Ext.menu.Menu, {
39167     
39168     enableScrolling : false,
39169     
39170         
39171     
39172     
39173     hideOnClick : true,
39174     
39175     cls : 'x-color-menu',
39176     
39177     
39178     paletteId : null,
39179     
39180     
39181     
39182     
39183     
39184     
39185     
39186     
39187     
39188     
39189     initComponent : function(){
39190         Ext.apply(this, {
39191             plain: true,
39192             showSeparator: false,
39193             items: this.palette = new Ext.ColorPalette(Ext.applyIf({
39194                 id: this.paletteId
39195             }, this.initialConfig))
39196         });
39197         this.palette.purgeListeners();
39198         Ext.menu.ColorMenu.superclass.initComponent.call(this);
39199         
39200         this.relayEvents(this.palette, ['select']);
39201         this.on('select', this.menuHide, this);
39202         if(this.handler){
39203             this.on('select', this.handler, this.scope || this);
39204         }
39205     },
39206
39207     menuHide : function(){
39208         if(this.hideOnClick){
39209             this.hide(true);
39210         }
39211     }
39212 });
39213 Ext.reg('colormenu', Ext.menu.ColorMenu);
39214
39215 Ext.form.Field = Ext.extend(Ext.BoxComponent,  {
39216     
39217     
39218     
39219     
39220     
39221     
39222
39223     
39224     invalidClass : 'x-form-invalid',
39225     
39226     invalidText : 'The value in this field is invalid',
39227     
39228     focusClass : 'x-form-focus',
39229     
39230     
39231     validationEvent : 'keyup',
39232     
39233     validateOnBlur : true,
39234     
39235     validationDelay : 250,
39236     
39237     defaultAutoCreate : {tag: 'input', type: 'text', size: '20', autocomplete: 'off'},
39238     
39239     fieldClass : 'x-form-field',
39240     
39241     msgTarget : 'qtip',
39242     
39243     msgFx : 'normal',
39244     
39245     readOnly : false,
39246     
39247     disabled : false,
39248     
39249     submitValue: true,
39250
39251     
39252     isFormField : true,
39253
39254     
39255     msgDisplay: '',
39256
39257     
39258     hasFocus : false,
39259
39260     
39261     initComponent : function(){
39262         Ext.form.Field.superclass.initComponent.call(this);
39263         this.addEvents(
39264             
39265             'focus',
39266             
39267             'blur',
39268             
39269             'specialkey',
39270             
39271             'change',
39272             
39273             'invalid',
39274             
39275             'valid'
39276         );
39277     },
39278
39279     
39280     getName : function(){
39281         return this.rendered && this.el.dom.name ? this.el.dom.name : this.name || this.id || '';
39282     },
39283
39284     
39285     onRender : function(ct, position){
39286         if(!this.el){
39287             var cfg = this.getAutoCreate();
39288
39289             if(!cfg.name){
39290                 cfg.name = this.name || this.id;
39291             }
39292             if(this.inputType){
39293                 cfg.type = this.inputType;
39294             }
39295             this.autoEl = cfg;
39296         }
39297         Ext.form.Field.superclass.onRender.call(this, ct, position);
39298         if(this.submitValue === false){
39299             this.el.dom.removeAttribute('name');
39300         }
39301         var type = this.el.dom.type;
39302         if(type){
39303             if(type == 'password'){
39304                 type = 'text';
39305             }
39306             this.el.addClass('x-form-'+type);
39307         }
39308         if(this.readOnly){
39309             this.setReadOnly(true);
39310         }
39311         if(this.tabIndex !== undefined){
39312             this.el.dom.setAttribute('tabIndex', this.tabIndex);
39313         }
39314
39315         this.el.addClass([this.fieldClass, this.cls]);
39316     },
39317
39318     
39319     getItemCt : function(){
39320         return this.itemCt;
39321     },
39322
39323     
39324     initValue : function(){
39325         if(this.value !== undefined){
39326             this.setValue(this.value);
39327         }else if(!Ext.isEmpty(this.el.dom.value) && this.el.dom.value != this.emptyText){
39328             this.setValue(this.el.dom.value);
39329         }
39330         
39331         this.originalValue = this.getValue();
39332     },
39333
39334     
39335     isDirty : function() {
39336         if(this.disabled || !this.rendered) {
39337             return false;
39338         }
39339         return String(this.getValue()) !== String(this.originalValue);
39340     },
39341
39342     
39343     setReadOnly : function(readOnly){
39344         if(this.rendered){
39345             this.el.dom.readOnly = readOnly;
39346         }
39347         this.readOnly = readOnly;
39348     },
39349
39350     
39351     afterRender : function(){
39352         Ext.form.Field.superclass.afterRender.call(this);
39353         this.initEvents();
39354         this.initValue();
39355     },
39356
39357     
39358     fireKey : function(e){
39359         if(e.isSpecialKey()){
39360             this.fireEvent('specialkey', this, e);
39361         }
39362     },
39363
39364     
39365     reset : function(){
39366         this.setValue(this.originalValue);
39367         this.clearInvalid();
39368     },
39369
39370     
39371     initEvents : function(){
39372         this.mon(this.el, Ext.EventManager.getKeyEvent(), this.fireKey,  this);
39373         this.mon(this.el, 'focus', this.onFocus, this);
39374
39375         
39376         
39377         this.mon(this.el, 'blur', this.onBlur, this, this.inEditor ? {buffer:10} : null);
39378     },
39379
39380     
39381     preFocus: Ext.emptyFn,
39382
39383     
39384     onFocus : function(){
39385         this.preFocus();
39386         if(this.focusClass){
39387             this.el.addClass(this.focusClass);
39388         }
39389         if(!this.hasFocus){
39390             this.hasFocus = true;
39391             
39392             this.startValue = this.getValue();
39393             this.fireEvent('focus', this);
39394         }
39395     },
39396
39397     
39398     beforeBlur : Ext.emptyFn,
39399
39400     
39401     onBlur : function(){
39402         this.beforeBlur();
39403         if(this.focusClass){
39404             this.el.removeClass(this.focusClass);
39405         }
39406         this.hasFocus = false;
39407         if(this.validationEvent !== false && (this.validateOnBlur || this.validationEvent == 'blur')){
39408             this.validate();
39409         }
39410         var v = this.getValue();
39411         if(String(v) !== String(this.startValue)){
39412             this.fireEvent('change', this, v, this.startValue);
39413         }
39414         this.fireEvent('blur', this);
39415         this.postBlur();
39416     },
39417
39418     
39419     postBlur : Ext.emptyFn,
39420
39421     
39422     isValid : function(preventMark){
39423         if(this.disabled){
39424             return true;
39425         }
39426         var restore = this.preventMark;
39427         this.preventMark = preventMark === true;
39428         var v = this.validateValue(this.processValue(this.getRawValue()));
39429         this.preventMark = restore;
39430         return v;
39431     },
39432
39433     
39434     validate : function(){
39435         if(this.disabled || this.validateValue(this.processValue(this.getRawValue()))){
39436             this.clearInvalid();
39437             return true;
39438         }
39439         return false;
39440     },
39441
39442     
39443     processValue : function(value){
39444         return value;
39445     },
39446
39447     
39448      validateValue : function(value) {
39449          
39450          var error = this.getErrors(value)[0];
39451
39452          if (error == undefined) {
39453              return true;
39454          } else {
39455              this.markInvalid(error);
39456              return false;
39457          }
39458      },
39459     
39460     
39461     getErrors: function() {
39462         return [];
39463     },
39464
39465     
39466     getActiveError : function(){
39467         return this.activeError || '';
39468     },
39469
39470     
39471     markInvalid : function(msg){
39472         
39473         if (this.rendered && !this.preventMark) {
39474             msg = msg || this.invalidText;
39475
39476             var mt = this.getMessageHandler();
39477             if(mt){
39478                 mt.mark(this, msg);
39479             }else if(this.msgTarget){
39480                 this.el.addClass(this.invalidClass);
39481                 var t = Ext.getDom(this.msgTarget);
39482                 if(t){
39483                     t.innerHTML = msg;
39484                     t.style.display = this.msgDisplay;
39485                 }
39486             }
39487         }
39488         
39489         this.setActiveError(msg);
39490     },
39491     
39492     
39493     clearInvalid : function(){
39494         
39495         if (this.rendered && !this.preventMark) {
39496             this.el.removeClass(this.invalidClass);
39497             var mt = this.getMessageHandler();
39498             if(mt){
39499                 mt.clear(this);
39500             }else if(this.msgTarget){
39501                 this.el.removeClass(this.invalidClass);
39502                 var t = Ext.getDom(this.msgTarget);
39503                 if(t){
39504                     t.innerHTML = '';
39505                     t.style.display = 'none';
39506                 }
39507             }
39508         }
39509         
39510         this.unsetActiveError();
39511     },
39512
39513     
39514     setActiveError: function(msg, suppressEvent) {
39515         this.activeError = msg;
39516         if (suppressEvent !== true) this.fireEvent('invalid', this, msg);
39517     },
39518     
39519     
39520     unsetActiveError: function(suppressEvent) {
39521         delete this.activeError;
39522         if (suppressEvent !== true) this.fireEvent('valid', this);
39523     },
39524
39525     
39526     getMessageHandler : function(){
39527         return Ext.form.MessageTargets[this.msgTarget];
39528     },
39529
39530     
39531     getErrorCt : function(){
39532         return this.el.findParent('.x-form-element', 5, true) || 
39533             this.el.findParent('.x-form-field-wrap', 5, true);   
39534     },
39535
39536     
39537     alignErrorEl : function(){
39538         this.errorEl.setWidth(this.getErrorCt().getWidth(true) - 20);
39539     },
39540
39541     
39542     alignErrorIcon : function(){
39543         this.errorIcon.alignTo(this.el, 'tl-tr', [2, 0]);
39544     },
39545
39546     
39547     getRawValue : function(){
39548         var v = this.rendered ? this.el.getValue() : Ext.value(this.value, '');
39549         if(v === this.emptyText){
39550             v = '';
39551         }
39552         return v;
39553     },
39554
39555     
39556     getValue : function(){
39557         if(!this.rendered) {
39558             return this.value;
39559         }
39560         var v = this.el.getValue();
39561         if(v === this.emptyText || v === undefined){
39562             v = '';
39563         }
39564         return v;
39565     },
39566
39567     
39568     setRawValue : function(v){
39569         return this.rendered ? (this.el.dom.value = (Ext.isEmpty(v) ? '' : v)) : '';
39570     },
39571
39572     
39573     setValue : function(v){
39574         this.value = v;
39575         if(this.rendered){
39576             this.el.dom.value = (Ext.isEmpty(v) ? '' : v);
39577             this.validate();
39578         }
39579         return this;
39580     },
39581
39582     
39583     append : function(v){
39584          this.setValue([this.getValue(), v].join(''));
39585     }
39586
39587     
39588     
39589
39590     
39591 });
39592
39593
39594 Ext.form.MessageTargets = {
39595     'qtip' : {
39596         mark: function(field, msg){
39597             field.el.addClass(field.invalidClass);
39598             field.el.dom.qtip = msg;
39599             field.el.dom.qclass = 'x-form-invalid-tip';
39600             if(Ext.QuickTips){ 
39601                 Ext.QuickTips.enable();
39602             }
39603         },
39604         clear: function(field){
39605             field.el.removeClass(field.invalidClass);
39606             field.el.dom.qtip = '';
39607         }
39608     },
39609     'title' : {
39610         mark: function(field, msg){
39611             field.el.addClass(field.invalidClass);
39612             field.el.dom.title = msg;
39613         },
39614         clear: function(field){
39615             field.el.dom.title = '';
39616         }
39617     },
39618     'under' : {
39619         mark: function(field, msg){
39620             field.el.addClass(field.invalidClass);
39621             if(!field.errorEl){
39622                 var elp = field.getErrorCt();
39623                 if(!elp){ 
39624                     field.el.dom.title = msg;
39625                     return;
39626                 }
39627                 field.errorEl = elp.createChild({cls:'x-form-invalid-msg'});
39628                 field.on('resize', field.alignErrorEl, field);
39629                 field.on('destroy', function(){
39630                     Ext.destroy(this.errorEl);
39631                 }, field);
39632             }
39633             field.alignErrorEl();
39634             field.errorEl.update(msg);
39635             Ext.form.Field.msgFx[field.msgFx].show(field.errorEl, field);
39636         },
39637         clear: function(field){
39638             field.el.removeClass(field.invalidClass);
39639             if(field.errorEl){
39640                 Ext.form.Field.msgFx[field.msgFx].hide(field.errorEl, field);
39641             }else{
39642                 field.el.dom.title = '';
39643             }
39644         }
39645     },
39646     'side' : {
39647         mark: function(field, msg){
39648             field.el.addClass(field.invalidClass);
39649             if(!field.errorIcon){
39650                 var elp = field.getErrorCt();
39651                 
39652                 if(!elp){
39653                     field.el.dom.title = msg;
39654                     return;
39655                 }
39656                 field.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});
39657                 if (field.ownerCt) {
39658                     field.ownerCt.on('afterlayout', field.alignErrorIcon, field);
39659                     field.ownerCt.on('expand', field.alignErrorIcon, field);
39660                 }
39661                 field.on('resize', field.alignErrorIcon, field);
39662                 field.on('destroy', function(){
39663                     Ext.destroy(this.errorIcon);
39664                 }, field);
39665             }
39666             field.alignErrorIcon();
39667             field.errorIcon.dom.qtip = msg;
39668             field.errorIcon.dom.qclass = 'x-form-invalid-tip';
39669             field.errorIcon.show();
39670         },
39671         clear: function(field){
39672             field.el.removeClass(field.invalidClass);
39673             if(field.errorIcon){
39674                 field.errorIcon.dom.qtip = '';
39675                 field.errorIcon.hide();
39676             }else{
39677                 field.el.dom.title = '';
39678             }
39679         }
39680     }
39681 };
39682
39683
39684 Ext.form.Field.msgFx = {
39685     normal : {
39686         show: function(msgEl, f){
39687             msgEl.setDisplayed('block');
39688         },
39689
39690         hide : function(msgEl, f){
39691             msgEl.setDisplayed(false).update('');
39692         }
39693     },
39694
39695     slide : {
39696         show: function(msgEl, f){
39697             msgEl.slideIn('t', {stopFx:true});
39698         },
39699
39700         hide : function(msgEl, f){
39701             msgEl.slideOut('t', {stopFx:true,useDisplay:true});
39702         }
39703     },
39704
39705     slideRight : {
39706         show: function(msgEl, f){
39707             msgEl.fixDisplay();
39708             msgEl.alignTo(f.el, 'tl-tr');
39709             msgEl.slideIn('l', {stopFx:true});
39710         },
39711
39712         hide : function(msgEl, f){
39713             msgEl.slideOut('l', {stopFx:true,useDisplay:true});
39714         }
39715     }
39716 };
39717 Ext.reg('field', Ext.form.Field);
39718
39719 Ext.form.TextField = Ext.extend(Ext.form.Field,  {
39720     
39721     
39722     
39723     grow : false,
39724     
39725     growMin : 30,
39726     
39727     growMax : 800,
39728     
39729     vtype : null,
39730     
39731     maskRe : null,
39732     
39733     disableKeyFilter : false,
39734     
39735     allowBlank : true,
39736     
39737     minLength : 0,
39738     
39739     maxLength : Number.MAX_VALUE,
39740     
39741     minLengthText : 'The minimum length for this field is {0}',
39742     
39743     maxLengthText : 'The maximum length for this field is {0}',
39744     
39745     selectOnFocus : false,
39746     
39747     blankText : 'This field is required',
39748     
39749     validator : null,
39750     
39751     regex : null,
39752     
39753     regexText : '',
39754     
39755     emptyText : null,
39756     
39757     emptyClass : 'x-form-empty-field',
39758
39759     
39760
39761     initComponent : function(){
39762         Ext.form.TextField.superclass.initComponent.call(this);
39763         this.addEvents(
39764             
39765             'autosize',
39766
39767             
39768             'keydown',
39769             
39770             'keyup',
39771             
39772             'keypress'
39773         );
39774     },
39775
39776     
39777     initEvents : function(){
39778         Ext.form.TextField.superclass.initEvents.call(this);
39779         if(this.validationEvent == 'keyup'){
39780             this.validationTask = new Ext.util.DelayedTask(this.validate, this);
39781             this.mon(this.el, 'keyup', this.filterValidation, this);
39782         }
39783         else if(this.validationEvent !== false && this.validationEvent != 'blur'){
39784                 this.mon(this.el, this.validationEvent, this.validate, this, {buffer: this.validationDelay});
39785         }
39786         if(this.selectOnFocus || this.emptyText){            
39787             this.mon(this.el, 'mousedown', this.onMouseDown, this);
39788             
39789             if(this.emptyText){
39790                 this.applyEmptyText();
39791             }
39792         }
39793         if(this.maskRe || (this.vtype && this.disableKeyFilter !== true && (this.maskRe = Ext.form.VTypes[this.vtype+'Mask']))){
39794                 this.mon(this.el, 'keypress', this.filterKeys, this);
39795         }
39796         if(this.grow){
39797                 this.mon(this.el, 'keyup', this.onKeyUpBuffered, this, {buffer: 50});
39798                         this.mon(this.el, 'click', this.autoSize, this);
39799         }
39800         if(this.enableKeyEvents){
39801             this.mon(this.el, {
39802                 scope: this,
39803                 keyup: this.onKeyUp,
39804                 keydown: this.onKeyDown,
39805                 keypress: this.onKeyPress
39806             });
39807         }
39808     },
39809     
39810     onMouseDown: function(e){
39811         if(!this.hasFocus){
39812             this.mon(this.el, 'mouseup', Ext.emptyFn, this, { single: true, preventDefault: true });
39813         }
39814     },
39815
39816     processValue : function(value){
39817         if(this.stripCharsRe){
39818             var newValue = value.replace(this.stripCharsRe, '');
39819             if(newValue !== value){
39820                 this.setRawValue(newValue);
39821                 return newValue;
39822             }
39823         }
39824         return value;
39825     },
39826
39827     filterValidation : function(e){
39828         if(!e.isNavKeyPress()){
39829             this.validationTask.delay(this.validationDelay);
39830         }
39831     },
39832     
39833     
39834     onDisable: function(){
39835         Ext.form.TextField.superclass.onDisable.call(this);
39836         if(Ext.isIE){
39837             this.el.dom.unselectable = 'on';
39838         }
39839     },
39840     
39841     
39842     onEnable: function(){
39843         Ext.form.TextField.superclass.onEnable.call(this);
39844         if(Ext.isIE){
39845             this.el.dom.unselectable = '';
39846         }
39847     },
39848
39849     
39850     onKeyUpBuffered : function(e){
39851         if(this.doAutoSize(e)){
39852             this.autoSize();
39853         }
39854     },
39855     
39856     
39857     doAutoSize : function(e){
39858         return !e.isNavKeyPress();
39859     },
39860
39861     
39862     onKeyUp : function(e){
39863         this.fireEvent('keyup', this, e);
39864     },
39865
39866     
39867     onKeyDown : function(e){
39868         this.fireEvent('keydown', this, e);
39869     },
39870
39871     
39872     onKeyPress : function(e){
39873         this.fireEvent('keypress', this, e);
39874     },
39875
39876     
39877     reset : function(){
39878         Ext.form.TextField.superclass.reset.call(this);
39879         this.applyEmptyText();
39880     },
39881
39882     applyEmptyText : function(){
39883         if(this.rendered && this.emptyText && this.getRawValue().length < 1 && !this.hasFocus){
39884             this.setRawValue(this.emptyText);
39885             this.el.addClass(this.emptyClass);
39886         }
39887     },
39888
39889     
39890     preFocus : function(){
39891         var el = this.el,
39892             isEmpty;
39893         if(this.emptyText){
39894             if(el.dom.value == this.emptyText){
39895                 this.setRawValue('');
39896                 isEmpty = true;
39897             }
39898             el.removeClass(this.emptyClass);
39899         }
39900         if(this.selectOnFocus || isEmpty){
39901             el.dom.select();
39902         }
39903     },
39904
39905     
39906     postBlur : function(){
39907         this.applyEmptyText();
39908     },
39909
39910     
39911     filterKeys : function(e){
39912         if(e.ctrlKey){
39913             return;
39914         }
39915         var k = e.getKey();
39916         if(Ext.isGecko && (e.isNavKeyPress() || k == e.BACKSPACE || (k == e.DELETE && e.button == -1))){
39917             return;
39918         }
39919         var cc = String.fromCharCode(e.getCharCode());
39920         if(!Ext.isGecko && e.isSpecialKey() && !cc){
39921             return;
39922         }
39923         if(!this.maskRe.test(cc)){
39924             e.stopEvent();
39925         }
39926     },
39927
39928     setValue : function(v){
39929         if(this.emptyText && this.el && !Ext.isEmpty(v)){
39930             this.el.removeClass(this.emptyClass);
39931         }
39932         Ext.form.TextField.superclass.setValue.apply(this, arguments);
39933         this.applyEmptyText();
39934         this.autoSize();
39935         return this;
39936     },
39937
39938     
39939     getErrors: function(value) {
39940         var errors = Ext.form.TextField.superclass.getErrors.apply(this, arguments);
39941         
39942         value = Ext.isDefined(value) ? value : this.processValue(this.getRawValue());        
39943         
39944         if (Ext.isFunction(this.validator)) {
39945             var msg = this.validator(value);
39946             if (msg !== true) {
39947                 errors.push(msg);
39948             }
39949         }
39950         
39951         if (value.length < 1 || value === this.emptyText) {
39952             if (this.allowBlank) {
39953                 
39954                 return errors;
39955             } else {
39956                 errors.push(this.blankText);
39957             }
39958         }
39959         
39960         if (!this.allowBlank && (value.length < 1 || value === this.emptyText)) { 
39961             errors.push(this.blankText);
39962         }
39963         
39964         if (value.length < this.minLength) {
39965             errors.push(String.format(this.minLengthText, this.minLength));
39966         }
39967         
39968         if (value.length > this.maxLength) {
39969             errors.push(String.format(this.maxLengthText, this.maxLength));
39970         }
39971         
39972         if (this.vtype) {
39973             var vt = Ext.form.VTypes;
39974             if(!vt[this.vtype](value, this)){
39975                 errors.push(this.vtypeText || vt[this.vtype +'Text']);
39976             }
39977         }
39978         
39979         if (this.regex && !this.regex.test(value)) {
39980             errors.push(this.regexText);
39981         }
39982         
39983         return errors;
39984     },
39985
39986     
39987     selectText : function(start, end){
39988         var v = this.getRawValue();
39989         var doFocus = false;
39990         if(v.length > 0){
39991             start = start === undefined ? 0 : start;
39992             end = end === undefined ? v.length : end;
39993             var d = this.el.dom;
39994             if(d.setSelectionRange){
39995                 d.setSelectionRange(start, end);
39996             }else if(d.createTextRange){
39997                 var range = d.createTextRange();
39998                 range.moveStart('character', start);
39999                 range.moveEnd('character', end-v.length);
40000                 range.select();
40001             }
40002             doFocus = Ext.isGecko || Ext.isOpera;
40003         }else{
40004             doFocus = true;
40005         }
40006         if(doFocus){
40007             this.focus();
40008         }
40009     },
40010
40011     
40012     autoSize : function(){
40013         if(!this.grow || !this.rendered){
40014             return;
40015         }
40016         if(!this.metrics){
40017             this.metrics = Ext.util.TextMetrics.createInstance(this.el);
40018         }
40019         var el = this.el;
40020         var v = el.dom.value;
40021         var d = document.createElement('div');
40022         d.appendChild(document.createTextNode(v));
40023         v = d.innerHTML;
40024         Ext.removeNode(d);
40025         d = null;
40026         v += '&#160;';
40027         var w = Math.min(this.growMax, Math.max(this.metrics.getWidth(v) +  10, this.growMin));
40028         this.el.setWidth(w);
40029         this.fireEvent('autosize', this, w);
40030     },
40031         
40032         onDestroy: function(){
40033                 if(this.validationTask){
40034                         this.validationTask.cancel();
40035                         this.validationTask = null;
40036                 }
40037                 Ext.form.TextField.superclass.onDestroy.call(this);
40038         }
40039 });
40040 Ext.reg('textfield', Ext.form.TextField);
40041
40042 Ext.form.TriggerField = Ext.extend(Ext.form.TextField,  {
40043     
40044     
40045     
40046     defaultAutoCreate : {tag: "input", type: "text", size: "16", autocomplete: "off"},
40047     
40048     hideTrigger:false,
40049     
40050     editable: true,
40051     
40052     readOnly: false,
40053     
40054     wrapFocusClass: 'x-trigger-wrap-focus',
40055     
40056     autoSize: Ext.emptyFn,
40057     
40058     monitorTab : true,
40059     
40060     deferHeight : true,
40061     
40062     mimicing : false,
40063
40064     actionMode: 'wrap',
40065
40066     defaultTriggerWidth: 17,
40067
40068     
40069     onResize : function(w, h){
40070         Ext.form.TriggerField.superclass.onResize.call(this, w, h);
40071         var tw = this.getTriggerWidth();
40072         if(Ext.isNumber(w)){
40073             this.el.setWidth(w - tw);
40074         }
40075         this.wrap.setWidth(this.el.getWidth() + tw);
40076     },
40077
40078     getTriggerWidth: function(){
40079         var tw = this.trigger.getWidth();
40080         if(!this.hideTrigger && !this.readOnly && tw === 0){
40081             tw = this.defaultTriggerWidth;
40082         }
40083         return tw;
40084     },
40085
40086     
40087     alignErrorIcon : function(){
40088         if(this.wrap){
40089             this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);
40090         }
40091     },
40092
40093     
40094     onRender : function(ct, position){
40095         this.doc = Ext.isIE ? Ext.getBody() : Ext.getDoc();
40096         Ext.form.TriggerField.superclass.onRender.call(this, ct, position);
40097
40098         this.wrap = this.el.wrap({cls: 'x-form-field-wrap x-form-field-trigger-wrap'});
40099         this.trigger = this.wrap.createChild(this.triggerConfig ||
40100                 {tag: "img", src: Ext.BLANK_IMAGE_URL, alt: "", cls: "x-form-trigger " + this.triggerClass});
40101         this.initTrigger();
40102         if(!this.width){
40103             this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth());
40104         }
40105         this.resizeEl = this.positionEl = this.wrap;
40106     },
40107
40108     getWidth: function() {
40109         return(this.el.getWidth() + this.trigger.getWidth());
40110     },
40111
40112     updateEditState: function(){
40113         if(this.rendered){
40114             if (this.readOnly) {
40115                 this.el.dom.readOnly = true;
40116                 this.el.addClass('x-trigger-noedit');
40117                 this.mun(this.el, 'click', this.onTriggerClick, this);
40118                 this.trigger.setDisplayed(false);
40119             } else {
40120                 if (!this.editable) {
40121                     this.el.dom.readOnly = true;
40122                     this.el.addClass('x-trigger-noedit');
40123                     this.mon(this.el, 'click', this.onTriggerClick, this);
40124                 } else {
40125                     this.el.dom.readOnly = false;
40126                     this.el.removeClass('x-trigger-noedit');
40127                     this.mun(this.el, 'click', this.onTriggerClick, this);
40128                 }
40129                 this.trigger.setDisplayed(!this.hideTrigger);
40130             }
40131             this.onResize(this.width || this.wrap.getWidth());
40132         }
40133     },
40134
40135     
40136     setHideTrigger: function(hideTrigger){
40137         if(hideTrigger != this.hideTrigger){
40138             this.hideTrigger = hideTrigger;
40139             this.updateEditState();
40140         }
40141     },
40142
40143     
40144     setEditable: function(editable){
40145         if(editable != this.editable){
40146             this.editable = editable;
40147             this.updateEditState();
40148         }
40149     },
40150
40151     
40152     setReadOnly: function(readOnly){
40153         if(readOnly != this.readOnly){
40154             this.readOnly = readOnly;
40155             this.updateEditState();
40156         }
40157     },
40158
40159     afterRender : function(){
40160         Ext.form.TriggerField.superclass.afterRender.call(this);
40161         this.updateEditState();
40162     },
40163
40164     
40165     initTrigger : function(){
40166         this.mon(this.trigger, 'click', this.onTriggerClick, this, {preventDefault:true});
40167         this.trigger.addClassOnOver('x-form-trigger-over');
40168         this.trigger.addClassOnClick('x-form-trigger-click');
40169     },
40170
40171     
40172     onDestroy : function(){
40173         Ext.destroy(this.trigger, this.wrap);
40174         if (this.mimicing){
40175             this.doc.un('mousedown', this.mimicBlur, this);
40176         }
40177         delete this.doc;
40178         Ext.form.TriggerField.superclass.onDestroy.call(this);
40179     },
40180
40181     
40182     onFocus : function(){
40183         Ext.form.TriggerField.superclass.onFocus.call(this);
40184         if(!this.mimicing){
40185             this.wrap.addClass(this.wrapFocusClass);
40186             this.mimicing = true;
40187             this.doc.on('mousedown', this.mimicBlur, this, {delay: 10});
40188             if(this.monitorTab){
40189                 this.on('specialkey', this.checkTab, this);
40190             }
40191         }
40192     },
40193
40194     
40195     checkTab : function(me, e){
40196         if(e.getKey() == e.TAB){
40197             this.triggerBlur();
40198         }
40199     },
40200
40201     
40202     onBlur : Ext.emptyFn,
40203
40204     
40205     mimicBlur : function(e){
40206         if(!this.isDestroyed && !this.wrap.contains(e.target) && this.validateBlur(e)){
40207             this.triggerBlur();
40208         }
40209     },
40210
40211     
40212     triggerBlur : function(){
40213         this.mimicing = false;
40214         this.doc.un('mousedown', this.mimicBlur, this);
40215         if(this.monitorTab && this.el){
40216             this.un('specialkey', this.checkTab, this);
40217         }
40218         Ext.form.TriggerField.superclass.onBlur.call(this);
40219         if(this.wrap){
40220             this.wrap.removeClass(this.wrapFocusClass);
40221         }
40222     },
40223
40224     beforeBlur : Ext.emptyFn,
40225
40226     
40227     
40228     validateBlur : function(e){
40229         return true;
40230     },
40231
40232     
40233     onTriggerClick : Ext.emptyFn
40234
40235     
40236     
40237     
40238 });
40239
40240
40241 Ext.form.TwinTriggerField = Ext.extend(Ext.form.TriggerField, {
40242     
40243     
40244     
40245
40246     initComponent : function(){
40247         Ext.form.TwinTriggerField.superclass.initComponent.call(this);
40248
40249         this.triggerConfig = {
40250             tag:'span', cls:'x-form-twin-triggers', cn:[
40251             {tag: "img", src: Ext.BLANK_IMAGE_URL, alt: "", cls: "x-form-trigger " + this.trigger1Class},
40252             {tag: "img", src: Ext.BLANK_IMAGE_URL, alt: "", cls: "x-form-trigger " + this.trigger2Class}
40253         ]};
40254     },
40255
40256     getTrigger : function(index){
40257         return this.triggers[index];
40258     },
40259     
40260     afterRender: function(){
40261         Ext.form.TwinTriggerField.superclass.afterRender.call(this);
40262         var triggers = this.triggers,
40263             i = 0,
40264             len = triggers.length;
40265             
40266         for(; i < len; ++i){
40267             if(this['hideTrigger' + (i + 1)]){
40268                     triggers[i].hide();
40269                 }
40270
40271         }    
40272     },
40273
40274     initTrigger : function(){
40275         var ts = this.trigger.select('.x-form-trigger', true),
40276             triggerField = this;
40277             
40278         ts.each(function(t, all, index){
40279             var triggerIndex = 'Trigger'+(index+1);
40280             t.hide = function(){
40281                 var w = triggerField.wrap.getWidth();
40282                 this.dom.style.display = 'none';
40283                 triggerField.el.setWidth(w-triggerField.trigger.getWidth());
40284                 triggerField['hidden' + triggerIndex] = true;
40285             };
40286             t.show = function(){
40287                 var w = triggerField.wrap.getWidth();
40288                 this.dom.style.display = '';
40289                 triggerField.el.setWidth(w-triggerField.trigger.getWidth());
40290                 triggerField['hidden' + triggerIndex] = false;
40291             };
40292             this.mon(t, 'click', this['on'+triggerIndex+'Click'], this, {preventDefault:true});
40293             t.addClassOnOver('x-form-trigger-over');
40294             t.addClassOnClick('x-form-trigger-click');
40295         }, this);
40296         this.triggers = ts.elements;
40297     },
40298
40299     getTriggerWidth: function(){
40300         var tw = 0;
40301         Ext.each(this.triggers, function(t, index){
40302             var triggerIndex = 'Trigger' + (index + 1),
40303                 w = t.getWidth();
40304             if(w === 0 && !this['hidden' + triggerIndex]){
40305                 tw += this.defaultTriggerWidth;
40306             }else{
40307                 tw += w;
40308             }
40309         }, this);
40310         return tw;
40311     },
40312
40313     
40314     onDestroy : function() {
40315         Ext.destroy(this.triggers);
40316         Ext.form.TwinTriggerField.superclass.onDestroy.call(this);
40317     },
40318
40319     
40320     onTrigger1Click : Ext.emptyFn,
40321     
40322     onTrigger2Click : Ext.emptyFn
40323 });
40324 Ext.reg('trigger', Ext.form.TriggerField);
40325
40326 Ext.form.TextArea = Ext.extend(Ext.form.TextField,  {
40327     
40328     growMin : 60,
40329     
40330     growMax: 1000,
40331     growAppend : '&#160;\n&#160;',
40332
40333     enterIsSpecial : false,
40334
40335     
40336     preventScrollbars: false,
40337     
40338
40339     
40340     onRender : function(ct, position){
40341         if(!this.el){
40342             this.defaultAutoCreate = {
40343                 tag: "textarea",
40344                 style:"width:100px;height:60px;",
40345                 autocomplete: "off"
40346             };
40347         }
40348         Ext.form.TextArea.superclass.onRender.call(this, ct, position);
40349         if(this.grow){
40350             this.textSizeEl = Ext.DomHelper.append(document.body, {
40351                 tag: "pre", cls: "x-form-grow-sizer"
40352             });
40353             if(this.preventScrollbars){
40354                 this.el.setStyle("overflow", "hidden");
40355             }
40356             this.el.setHeight(this.growMin);
40357         }
40358     },
40359
40360     onDestroy : function(){
40361         Ext.removeNode(this.textSizeEl);
40362         Ext.form.TextArea.superclass.onDestroy.call(this);
40363     },
40364
40365     fireKey : function(e){
40366         if(e.isSpecialKey() && (this.enterIsSpecial || (e.getKey() != e.ENTER || e.hasModifier()))){
40367             this.fireEvent("specialkey", this, e);
40368         }
40369     },
40370     
40371     
40372     doAutoSize : function(e){
40373         return !e.isNavKeyPress() || e.getKey() == e.ENTER;
40374     },
40375     
40376     
40377     filterValidation: function(e) {            
40378         if(!e.isNavKeyPress() || (!this.enterIsSpecial && e.keyCode == e.ENTER)){
40379             this.validationTask.delay(this.validationDelay);
40380         }
40381     },
40382
40383     
40384     autoSize: function(){
40385         if(!this.grow || !this.textSizeEl){
40386             return;
40387         }
40388         var el = this.el,
40389             v = Ext.util.Format.htmlEncode(el.dom.value),
40390             ts = this.textSizeEl,
40391             h;
40392             
40393         Ext.fly(ts).setWidth(this.el.getWidth());
40394         if(v.length < 1){
40395             v = "&#160;&#160;";
40396         }else{
40397             v += this.growAppend;
40398             if(Ext.isIE){
40399                 v = v.replace(/\n/g, '&#160;<br />');
40400             }
40401         }
40402         ts.innerHTML = v;
40403         h = Math.min(this.growMax, Math.max(ts.offsetHeight, this.growMin));
40404         if(h != this.lastHeight){
40405             this.lastHeight = h;
40406             this.el.setHeight(h);
40407             this.fireEvent("autosize", this, h);
40408         }
40409     }
40410 });
40411 Ext.reg('textarea', Ext.form.TextArea);
40412 Ext.form.NumberField = Ext.extend(Ext.form.TextField,  {
40413     
40414     
40415     
40416     fieldClass: "x-form-field x-form-num-field",
40417     
40418     
40419     allowDecimals : true,
40420     
40421     
40422     decimalSeparator : ".",
40423     
40424     
40425     decimalPrecision : 2,
40426     
40427     
40428     allowNegative : true,
40429     
40430     
40431     minValue : Number.NEGATIVE_INFINITY,
40432     
40433     
40434     maxValue : Number.MAX_VALUE,
40435     
40436     
40437     minText : "The minimum value for this field is {0}",
40438     
40439     
40440     maxText : "The maximum value for this field is {0}",
40441     
40442     
40443     nanText : "{0} is not a valid number",
40444     
40445     
40446     baseChars : "0123456789",
40447     
40448     
40449     autoStripChars: false,
40450
40451     
40452     initEvents : function() {
40453         var allowed = this.baseChars + '';
40454         if (this.allowDecimals) {
40455             allowed += this.decimalSeparator;
40456         }
40457         if (this.allowNegative) {
40458             allowed += '-';
40459         }
40460         allowed = Ext.escapeRe(allowed);
40461         this.maskRe = new RegExp('[' + allowed + ']');
40462         if (this.autoStripChars) {
40463             this.stripCharsRe = new RegExp('[^' + allowed + ']', 'gi');
40464         }
40465         
40466         Ext.form.NumberField.superclass.initEvents.call(this);
40467     },
40468     
40469     
40470     getErrors: function(value) {
40471         var errors = Ext.form.NumberField.superclass.getErrors.apply(this, arguments);
40472         
40473         value = Ext.isDefined(value) ? value : this.processValue(this.getRawValue());
40474         
40475         if (value.length < 1) { 
40476              return errors;
40477         }
40478         
40479         value = String(value).replace(this.decimalSeparator, ".");
40480         
40481         if(isNaN(value)){
40482             errors.push(String.format(this.nanText, value));
40483         }
40484         
40485         var num = this.parseValue(value);
40486         
40487         if (num < this.minValue) {
40488             errors.push(String.format(this.minText, this.minValue));
40489         }
40490         
40491         if (num > this.maxValue) {
40492             errors.push(String.format(this.maxText, this.maxValue));
40493         }
40494         
40495         return errors;
40496     },
40497
40498     getValue : function() {
40499         return this.fixPrecision(this.parseValue(Ext.form.NumberField.superclass.getValue.call(this)));
40500     },
40501
40502     setValue : function(v) {
40503         v = this.fixPrecision(v);
40504         v = Ext.isNumber(v) ? v : parseFloat(String(v).replace(this.decimalSeparator, "."));
40505         v = isNaN(v) ? '' : String(v).replace(".", this.decimalSeparator);
40506         return Ext.form.NumberField.superclass.setValue.call(this, v);
40507     },
40508     
40509     
40510     setMinValue : function(value) {
40511         this.minValue = Ext.num(value, Number.NEGATIVE_INFINITY);
40512     },
40513     
40514     
40515     setMaxValue : function(value) {
40516         this.maxValue = Ext.num(value, Number.MAX_VALUE);    
40517     },
40518
40519     
40520     parseValue : function(value) {
40521         value = parseFloat(String(value).replace(this.decimalSeparator, "."));
40522         return isNaN(value) ? '' : value;
40523     },
40524
40525     
40526     fixPrecision : function(value) {
40527         var nan = isNaN(value);
40528         
40529         if (!this.allowDecimals || this.decimalPrecision == -1 || nan || !value) {
40530             return nan ? '' : value;
40531         }
40532         
40533         return parseFloat(parseFloat(value).toFixed(this.decimalPrecision));
40534     },
40535
40536     beforeBlur : function() {
40537         var v = this.parseValue(this.getRawValue());
40538         
40539         if (!Ext.isEmpty(v)) {
40540             this.setValue(v);
40541         }
40542     }
40543 });
40544
40545 Ext.reg('numberfield', Ext.form.NumberField);
40546
40547 Ext.form.DateField = Ext.extend(Ext.form.TriggerField,  {
40548     
40549     format : "m/d/Y",
40550     
40551     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",
40552     
40553     disabledDaysText : "Disabled",
40554     
40555     disabledDatesText : "Disabled",
40556     
40557     minText : "The date in this field must be equal to or after {0}",
40558     
40559     maxText : "The date in this field must be equal to or before {0}",
40560     
40561     invalidText : "{0} is not a valid date - it must be in the format {1}",
40562     
40563     triggerClass : 'x-form-date-trigger',
40564     
40565     showToday : true,
40566     
40567     
40568     startDay : 0,
40569     
40570     
40571     
40572     
40573     
40574     
40575
40576     
40577     defaultAutoCreate : {tag: "input", type: "text", size: "10", autocomplete: "off"},
40578
40579     
40580     
40581     initTime: '12', 
40582
40583     initTimeFormat: 'H',
40584
40585     
40586     safeParse : function(value, format) {
40587         if (/[gGhH]/.test(format.replace(/(\\.)/g, ''))) {
40588             
40589             return Date.parseDate(value, format);
40590         } else {
40591             
40592             var parsedDate = Date.parseDate(value + ' ' + this.initTime, format + ' ' + this.initTimeFormat);
40593
40594             if (parsedDate) {
40595                 return parsedDate.clearTime();
40596             }
40597         }
40598     },
40599
40600     initComponent : function(){
40601         Ext.form.DateField.superclass.initComponent.call(this);
40602
40603         this.addEvents(
40604             
40605             'select'
40606         );
40607
40608         if(Ext.isString(this.minValue)){
40609             this.minValue = this.parseDate(this.minValue);
40610         }
40611         if(Ext.isString(this.maxValue)){
40612             this.maxValue = this.parseDate(this.maxValue);
40613         }
40614         this.disabledDatesRE = null;
40615         this.initDisabledDays();
40616     },
40617
40618     initEvents: function() {
40619         Ext.form.DateField.superclass.initEvents.call(this);
40620         this.keyNav = new Ext.KeyNav(this.el, {
40621             "down": function(e) {
40622                 this.onTriggerClick();
40623             },
40624             scope: this,
40625             forceKeyDown: true
40626         });
40627     },
40628
40629
40630     
40631     initDisabledDays : function(){
40632         if(this.disabledDates){
40633             var dd = this.disabledDates,
40634                 len = dd.length - 1,
40635                 re = "(?:";
40636
40637             Ext.each(dd, function(d, i){
40638                 re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];
40639                 if(i != len){
40640                     re += '|';
40641                 }
40642             }, this);
40643             this.disabledDatesRE = new RegExp(re + ')');
40644         }
40645     },
40646
40647     
40648     setDisabledDates : function(dd){
40649         this.disabledDates = dd;
40650         this.initDisabledDays();
40651         if(this.menu){
40652             this.menu.picker.setDisabledDates(this.disabledDatesRE);
40653         }
40654     },
40655
40656     
40657     setDisabledDays : function(dd){
40658         this.disabledDays = dd;
40659         if(this.menu){
40660             this.menu.picker.setDisabledDays(dd);
40661         }
40662     },
40663
40664     
40665     setMinValue : function(dt){
40666         this.minValue = (Ext.isString(dt) ? this.parseDate(dt) : dt);
40667         if(this.menu){
40668             this.menu.picker.setMinDate(this.minValue);
40669         }
40670     },
40671
40672     
40673     setMaxValue : function(dt){
40674         this.maxValue = (Ext.isString(dt) ? this.parseDate(dt) : dt);
40675         if(this.menu){
40676             this.menu.picker.setMaxDate(this.maxValue);
40677         }
40678     },
40679
40680     
40681     getErrors: function(value) {
40682         var errors = Ext.form.DateField.superclass.getErrors.apply(this, arguments);
40683
40684         value = this.formatDate(value || this.processValue(this.getRawValue()));
40685
40686         if (value.length < 1) { 
40687              return errors;
40688         }
40689
40690         var svalue = value;
40691         value = this.parseDate(value);
40692         if (!value) {
40693             errors.push(String.format(this.invalidText, svalue, this.format));
40694             return errors;
40695         }
40696
40697         var time = value.getTime();
40698         if (this.minValue && time < this.minValue.clearTime().getTime()) {
40699             errors.push(String.format(this.minText, this.formatDate(this.minValue)));
40700         }
40701
40702         if (this.maxValue && time > this.maxValue.clearTime().getTime()) {
40703             errors.push(String.format(this.maxText, this.formatDate(this.maxValue)));
40704         }
40705
40706         if (this.disabledDays) {
40707             var day = value.getDay();
40708
40709             for(var i = 0; i < this.disabledDays.length; i++) {
40710                 if (day === this.disabledDays[i]) {
40711                     errors.push(this.disabledDaysText);
40712                     break;
40713                 }
40714             }
40715         }
40716
40717         var fvalue = this.formatDate(value);
40718         if (this.disabledDatesRE && this.disabledDatesRE.test(fvalue)) {
40719             errors.push(String.format(this.disabledDatesText, fvalue));
40720         }
40721
40722         return errors;
40723     },
40724
40725     
40726     
40727     validateBlur : function(){
40728         return !this.menu || !this.menu.isVisible();
40729     },
40730
40731     
40732     getValue : function(){
40733         return this.parseDate(Ext.form.DateField.superclass.getValue.call(this)) || "";
40734     },
40735
40736     
40737     setValue : function(date){
40738         return Ext.form.DateField.superclass.setValue.call(this, this.formatDate(this.parseDate(date)));
40739     },
40740
40741     
40742     parseDate : function(value) {
40743         if(!value || Ext.isDate(value)){
40744             return value;
40745         }
40746
40747         var v = this.safeParse(value, this.format),
40748             af = this.altFormats,
40749             afa = this.altFormatsArray;
40750
40751         if (!v && af) {
40752             afa = afa || af.split("|");
40753
40754             for (var i = 0, len = afa.length; i < len && !v; i++) {
40755                 v = this.safeParse(value, afa[i]);
40756             }
40757         }
40758         return v;
40759     },
40760
40761     
40762     onDestroy : function(){
40763         Ext.destroy(this.menu, this.keyNav);
40764         Ext.form.DateField.superclass.onDestroy.call(this);
40765     },
40766
40767     
40768     formatDate : function(date){
40769         return Ext.isDate(date) ? date.dateFormat(this.format) : date;
40770     },
40771
40772     
40773     
40774     
40775     onTriggerClick : function(){
40776         if(this.disabled){
40777             return;
40778         }
40779         if(this.menu == null){
40780             this.menu = new Ext.menu.DateMenu({
40781                 hideOnClick: false,
40782                 focusOnSelect: false
40783             });
40784         }
40785         this.onFocus();
40786         Ext.apply(this.menu.picker,  {
40787             minDate : this.minValue,
40788             maxDate : this.maxValue,
40789             disabledDatesRE : this.disabledDatesRE,
40790             disabledDatesText : this.disabledDatesText,
40791             disabledDays : this.disabledDays,
40792             disabledDaysText : this.disabledDaysText,
40793             format : this.format,
40794             showToday : this.showToday,
40795             startDay: this.startDay,
40796             minText : String.format(this.minText, this.formatDate(this.minValue)),
40797             maxText : String.format(this.maxText, this.formatDate(this.maxValue))
40798         });
40799         this.menu.picker.setValue(this.getValue() || new Date());
40800         this.menu.show(this.el, "tl-bl?");
40801         this.menuEvents('on');
40802     },
40803
40804     
40805     menuEvents: function(method){
40806         this.menu[method]('select', this.onSelect, this);
40807         this.menu[method]('hide', this.onMenuHide, this);
40808         this.menu[method]('show', this.onFocus, this);
40809     },
40810
40811     onSelect: function(m, d){
40812         this.setValue(d);
40813         this.fireEvent('select', this, d);
40814         this.menu.hide();
40815     },
40816
40817     onMenuHide: function(){
40818         this.focus(false, 60);
40819         this.menuEvents('un');
40820     },
40821
40822     
40823     beforeBlur : function(){
40824         var v = this.parseDate(this.getRawValue());
40825         if(v){
40826             this.setValue(v);
40827         }
40828     }
40829
40830     
40831     
40832     
40833     
40834 });
40835 Ext.reg('datefield', Ext.form.DateField);
40836
40837 Ext.form.DisplayField = Ext.extend(Ext.form.Field,  {
40838     validationEvent : false,
40839     validateOnBlur : false,
40840     defaultAutoCreate : {tag: "div"},
40841     
40842     fieldClass : "x-form-display-field",
40843     
40844     htmlEncode: false,
40845
40846     
40847     initEvents : Ext.emptyFn,
40848
40849     isValid : function(){
40850         return true;
40851     },
40852
40853     validate : function(){
40854         return true;
40855     },
40856
40857     getRawValue : function(){
40858         var v = this.rendered ? this.el.dom.innerHTML : Ext.value(this.value, '');
40859         if(v === this.emptyText){
40860             v = '';
40861         }
40862         if(this.htmlEncode){
40863             v = Ext.util.Format.htmlDecode(v);
40864         }
40865         return v;
40866     },
40867
40868     getValue : function(){
40869         return this.getRawValue();
40870     },
40871     
40872     getName: function() {
40873         return this.name;
40874     },
40875
40876     setRawValue : function(v){
40877         if(this.htmlEncode){
40878             v = Ext.util.Format.htmlEncode(v);
40879         }
40880         return this.rendered ? (this.el.dom.innerHTML = (Ext.isEmpty(v) ? '' : v)) : (this.value = v);
40881     },
40882
40883     setValue : function(v){
40884         this.setRawValue(v);
40885         return this;
40886     }
40887     
40888     
40889     
40890     
40891     
40892     
40893 });
40894
40895 Ext.reg('displayfield', Ext.form.DisplayField);
40896
40897 Ext.form.ComboBox = Ext.extend(Ext.form.TriggerField, {
40898     
40899     
40900     
40901     
40902     
40903
40904     
40905     defaultAutoCreate : {tag: "input", type: "text", size: "24", autocomplete: "off"},
40906     
40907     
40908     
40909     
40910     
40911     
40912     
40913     listClass : '',
40914     
40915     selectedClass : 'x-combo-selected',
40916     
40917     listEmptyText: '',
40918     
40919     triggerClass : 'x-form-arrow-trigger',
40920     
40921     shadow : 'sides',
40922     
40923     listAlign : 'tl-bl?',
40924     
40925     maxHeight : 300,
40926     
40927     minHeight : 90,
40928     
40929     triggerAction : 'query',
40930     
40931     minChars : 4,
40932     
40933     autoSelect : true,
40934     
40935     typeAhead : false,
40936     
40937     queryDelay : 500,
40938     
40939     pageSize : 0,
40940     
40941     selectOnFocus : false,
40942     
40943     queryParam : 'query',
40944     
40945     loadingText : 'Loading...',
40946     
40947     resizable : false,
40948     
40949     handleHeight : 8,
40950     
40951     allQuery: '',
40952     
40953     mode: 'remote',
40954     
40955     minListWidth : 70,
40956     
40957     forceSelection : false,
40958     
40959     typeAheadDelay : 250,
40960     
40961
40962     
40963     lazyInit : true,
40964
40965     
40966     clearFilterOnReset : true,
40967
40968     
40969     submitValue: undefined,
40970
40971     
40972
40973     
40974     initComponent : function(){
40975         Ext.form.ComboBox.superclass.initComponent.call(this);
40976         this.addEvents(
40977             
40978             'expand',
40979             
40980             'collapse',
40981
40982             
40983             'beforeselect',
40984             
40985             'select',
40986             
40987             'beforequery'
40988         );
40989         if(this.transform){
40990             var s = Ext.getDom(this.transform);
40991             if(!this.hiddenName){
40992                 this.hiddenName = s.name;
40993             }
40994             if(!this.store){
40995                 this.mode = 'local';
40996                 var d = [], opts = s.options;
40997                 for(var i = 0, len = opts.length;i < len; i++){
40998                     var o = opts[i],
40999                         value = (o.hasAttribute ? o.hasAttribute('value') : o.getAttributeNode('value').specified) ? o.value : o.text;
41000                     if(o.selected && Ext.isEmpty(this.value, true)) {
41001                         this.value = value;
41002                     }
41003                     d.push([value, o.text]);
41004                 }
41005                 this.store = new Ext.data.ArrayStore({
41006                     idIndex: 0,
41007                     fields: ['value', 'text'],
41008                     data : d,
41009                     autoDestroy: true
41010                 });
41011                 this.valueField = 'value';
41012                 this.displayField = 'text';
41013             }
41014             s.name = Ext.id(); 
41015             if(!this.lazyRender){
41016                 this.target = true;
41017                 this.el = Ext.DomHelper.insertBefore(s, this.autoCreate || this.defaultAutoCreate);
41018                 this.render(this.el.parentNode, s);
41019             }
41020             Ext.removeNode(s);
41021         }
41022         
41023         else if(this.store){
41024             this.store = Ext.StoreMgr.lookup(this.store);
41025             if(this.store.autoCreated){
41026                 this.displayField = this.valueField = 'field1';
41027                 if(!this.store.expandData){
41028                     this.displayField = 'field2';
41029                 }
41030                 this.mode = 'local';
41031             }
41032         }
41033
41034         this.selectedIndex = -1;
41035         if(this.mode == 'local'){
41036             if(!Ext.isDefined(this.initialConfig.queryDelay)){
41037                 this.queryDelay = 10;
41038             }
41039             if(!Ext.isDefined(this.initialConfig.minChars)){
41040                 this.minChars = 0;
41041             }
41042         }
41043     },
41044
41045     
41046     onRender : function(ct, position){
41047         if(this.hiddenName && !Ext.isDefined(this.submitValue)){
41048             this.submitValue = false;
41049         }
41050         Ext.form.ComboBox.superclass.onRender.call(this, ct, position);
41051         if(this.hiddenName){
41052             this.hiddenField = this.el.insertSibling({tag:'input', type:'hidden', name: this.hiddenName,
41053                     id: (this.hiddenId || Ext.id())}, 'before', true);
41054
41055         }
41056         if(Ext.isGecko){
41057             this.el.dom.setAttribute('autocomplete', 'off');
41058         }
41059
41060         if(!this.lazyInit){
41061             this.initList();
41062         }else{
41063             this.on('focus', this.initList, this, {single: true});
41064         }
41065     },
41066
41067     
41068     initValue : function(){
41069         Ext.form.ComboBox.superclass.initValue.call(this);
41070         if(this.hiddenField){
41071             this.hiddenField.value =
41072                 Ext.value(Ext.isDefined(this.hiddenValue) ? this.hiddenValue : this.value, '');
41073         }
41074     },
41075
41076     getParentZIndex : function(){
41077         var zindex;
41078         if (this.ownerCt){
41079             this.findParentBy(function(ct){
41080                 zindex = parseInt(ct.getPositionEl().getStyle('z-index'), 10);
41081                 return !!zindex;
41082             });
41083         }
41084         return zindex;
41085     },
41086     
41087     getZIndex : function(listParent){
41088         listParent = listParent || Ext.getDom(this.getListParent() || Ext.getBody());
41089         var zindex = parseInt(Ext.fly(listParent).getStyle('z-index'), 10);
41090         if(!zindex){
41091             zindex = this.getParentZIndex();
41092         }
41093         return (zindex || 12000) + 5;
41094     },
41095
41096     
41097     initList : function(){
41098         if(!this.list){
41099             var cls = 'x-combo-list',
41100                 listParent = Ext.getDom(this.getListParent() || Ext.getBody());
41101
41102             this.list = new Ext.Layer({
41103                 parentEl: listParent,
41104                 shadow: this.shadow,
41105                 cls: [cls, this.listClass].join(' '),
41106                 constrain:false,
41107                 zindex: this.getZIndex(listParent)
41108             });
41109
41110             var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);
41111             this.list.setSize(lw, 0);
41112             this.list.swallowEvent('mousewheel');
41113             this.assetHeight = 0;
41114             if(this.syncFont !== false){
41115                 this.list.setStyle('font-size', this.el.getStyle('font-size'));
41116             }
41117             if(this.title){
41118                 this.header = this.list.createChild({cls:cls+'-hd', html: this.title});
41119                 this.assetHeight += this.header.getHeight();
41120             }
41121
41122             this.innerList = this.list.createChild({cls:cls+'-inner'});
41123             this.mon(this.innerList, 'mouseover', this.onViewOver, this);
41124             this.mon(this.innerList, 'mousemove', this.onViewMove, this);
41125             this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
41126
41127             if(this.pageSize){
41128                 this.footer = this.list.createChild({cls:cls+'-ft'});
41129                 this.pageTb = new Ext.PagingToolbar({
41130                     store: this.store,
41131                     pageSize: this.pageSize,
41132                     renderTo:this.footer
41133                 });
41134                 this.assetHeight += this.footer.getHeight();
41135             }
41136
41137             if(!this.tpl){
41138                 
41139                 this.tpl = '<tpl for="."><div class="'+cls+'-item">{' + this.displayField + '}</div></tpl>';
41140                 
41141             }
41142
41143             
41144             this.view = new Ext.DataView({
41145                 applyTo: this.innerList,
41146                 tpl: this.tpl,
41147                 singleSelect: true,
41148                 selectedClass: this.selectedClass,
41149                 itemSelector: this.itemSelector || '.' + cls + '-item',
41150                 emptyText: this.listEmptyText,
41151                 deferEmptyText: false
41152             });
41153
41154             this.mon(this.view, {
41155                 containerclick : this.onViewClick,
41156                 click : this.onViewClick,
41157                 scope :this
41158             });
41159
41160             this.bindStore(this.store, true);
41161
41162             if(this.resizable){
41163                 this.resizer = new Ext.Resizable(this.list,  {
41164                    pinned:true, handles:'se'
41165                 });
41166                 this.mon(this.resizer, 'resize', function(r, w, h){
41167                     this.maxHeight = h-this.handleHeight-this.list.getFrameWidth('tb')-this.assetHeight;
41168                     this.listWidth = w;
41169                     this.innerList.setWidth(w - this.list.getFrameWidth('lr'));
41170                     this.restrictHeight();
41171                 }, this);
41172
41173                 this[this.pageSize?'footer':'innerList'].setStyle('margin-bottom', this.handleHeight+'px');
41174             }
41175         }
41176     },
41177
41178     
41179     getListParent : function() {
41180         return document.body;
41181     },
41182
41183     
41184     getStore : function(){
41185         return this.store;
41186     },
41187
41188     
41189     bindStore : function(store, initial){
41190         if(this.store && !initial){
41191             if(this.store !== store && this.store.autoDestroy){
41192                 this.store.destroy();
41193             }else{
41194                 this.store.un('beforeload', this.onBeforeLoad, this);
41195                 this.store.un('load', this.onLoad, this);
41196                 this.store.un('exception', this.collapse, this);
41197             }
41198             if(!store){
41199                 this.store = null;
41200                 if(this.view){
41201                     this.view.bindStore(null);
41202                 }
41203                 if(this.pageTb){
41204                     this.pageTb.bindStore(null);
41205                 }
41206             }
41207         }
41208         if(store){
41209             if(!initial) {
41210                 this.lastQuery = null;
41211                 if(this.pageTb) {
41212                     this.pageTb.bindStore(store);
41213                 }
41214             }
41215
41216             this.store = Ext.StoreMgr.lookup(store);
41217             this.store.on({
41218                 scope: this,
41219                 beforeload: this.onBeforeLoad,
41220                 load: this.onLoad,
41221                 exception: this.collapse
41222             });
41223
41224             if(this.view){
41225                 this.view.bindStore(store);
41226             }
41227         }
41228     },
41229
41230     reset : function(){
41231         if(this.clearFilterOnReset && this.mode == 'local'){
41232             this.store.clearFilter();
41233         }
41234         Ext.form.ComboBox.superclass.reset.call(this);
41235     },
41236
41237     
41238     initEvents : function(){
41239         Ext.form.ComboBox.superclass.initEvents.call(this);
41240
41241         
41242         this.keyNav = new Ext.KeyNav(this.el, {
41243             "up" : function(e){
41244                 this.inKeyMode = true;
41245                 this.selectPrev();
41246             },
41247
41248             "down" : function(e){
41249                 if(!this.isExpanded()){
41250                     this.onTriggerClick();
41251                 }else{
41252                     this.inKeyMode = true;
41253                     this.selectNext();
41254                 }
41255             },
41256
41257             "enter" : function(e){
41258                 this.onViewClick();
41259             },
41260
41261             "esc" : function(e){
41262                 this.collapse();
41263             },
41264
41265             "tab" : function(e){
41266                 if (this.forceSelection === true) {
41267                     this.collapse();
41268                 } else {
41269                     this.onViewClick(false);
41270                 }
41271                 return true;
41272             },
41273
41274             scope : this,
41275
41276             doRelay : function(e, h, hname){
41277                 if(hname == 'down' || this.scope.isExpanded()){
41278                     
41279                     var relay = Ext.KeyNav.prototype.doRelay.apply(this, arguments);
41280                     if(!Ext.isIE && Ext.EventManager.useKeydown){
41281                         
41282                         this.scope.fireKey(e);
41283                     }
41284                     return relay;
41285                 }
41286                 return true;
41287             },
41288
41289             forceKeyDown : true,
41290             defaultEventAction: 'stopEvent'
41291         });
41292         this.queryDelay = Math.max(this.queryDelay || 10,
41293                 this.mode == 'local' ? 10 : 250);
41294         this.dqTask = new Ext.util.DelayedTask(this.initQuery, this);
41295         if(this.typeAhead){
41296             this.taTask = new Ext.util.DelayedTask(this.onTypeAhead, this);
41297         }
41298         if(!this.enableKeyEvents){
41299             this.mon(this.el, 'keyup', this.onKeyUp, this);
41300         }
41301     },
41302
41303
41304     
41305     onDestroy : function(){
41306         if (this.dqTask){
41307             this.dqTask.cancel();
41308             this.dqTask = null;
41309         }
41310         this.bindStore(null);
41311         Ext.destroy(
41312             this.resizer,
41313             this.view,
41314             this.pageTb,
41315             this.list
41316         );
41317         Ext.destroyMembers(this, 'hiddenField');
41318         Ext.form.ComboBox.superclass.onDestroy.call(this);
41319     },
41320
41321     
41322     fireKey : function(e){
41323         if (!this.isExpanded()) {
41324             Ext.form.ComboBox.superclass.fireKey.call(this, e);
41325         }
41326     },
41327
41328     
41329     onResize : function(w, h){
41330         Ext.form.ComboBox.superclass.onResize.apply(this, arguments);
41331         if(!isNaN(w) && this.isVisible() && this.list){
41332             this.doResize(w);
41333         }else{
41334             this.bufferSize = w;
41335         }
41336     },
41337
41338     doResize: function(w){
41339         if(!Ext.isDefined(this.listWidth)){
41340             var lw = Math.max(w, this.minListWidth);
41341             this.list.setWidth(lw);
41342             this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
41343         }
41344     },
41345
41346     
41347     onEnable : function(){
41348         Ext.form.ComboBox.superclass.onEnable.apply(this, arguments);
41349         if(this.hiddenField){
41350             this.hiddenField.disabled = false;
41351         }
41352     },
41353
41354     
41355     onDisable : function(){
41356         Ext.form.ComboBox.superclass.onDisable.apply(this, arguments);
41357         if(this.hiddenField){
41358             this.hiddenField.disabled = true;
41359         }
41360     },
41361
41362     
41363     onBeforeLoad : function(){
41364         if(!this.hasFocus){
41365             return;
41366         }
41367         this.innerList.update(this.loadingText ?
41368                '<div class="loading-indicator">'+this.loadingText+'</div>' : '');
41369         this.restrictHeight();
41370         this.selectedIndex = -1;
41371     },
41372
41373     
41374     onLoad : function(){
41375         if(!this.hasFocus){
41376             return;
41377         }
41378         if(this.store.getCount() > 0 || this.listEmptyText){
41379             this.expand();
41380             this.restrictHeight();
41381             if(this.lastQuery == this.allQuery){
41382                 if(this.editable){
41383                     this.el.dom.select();
41384                 }
41385
41386                 if(this.autoSelect !== false && !this.selectByValue(this.value, true)){
41387                     this.select(0, true);
41388                 }
41389             }else{
41390                 if(this.autoSelect !== false){
41391                     this.selectNext();
41392                 }
41393                 if(this.typeAhead && this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE){
41394                     this.taTask.delay(this.typeAheadDelay);
41395                 }
41396             }
41397         }else{
41398             this.collapse();
41399         }
41400
41401     },
41402
41403     
41404     onTypeAhead : function(){
41405         if(this.store.getCount() > 0){
41406             var r = this.store.getAt(0);
41407             var newValue = r.data[this.displayField];
41408             var len = newValue.length;
41409             var selStart = this.getRawValue().length;
41410             if(selStart != len){
41411                 this.setRawValue(newValue);
41412                 this.selectText(selStart, newValue.length);
41413             }
41414         }
41415     },
41416
41417     
41418     assertValue  : function(){
41419         var val = this.getRawValue(),
41420             rec = this.findRecord(this.displayField, val);
41421
41422         if(!rec && this.forceSelection){
41423             if(val.length > 0 && val != this.emptyText){
41424                 this.el.dom.value = Ext.value(this.lastSelectionText, '');
41425                 this.applyEmptyText();
41426             }else{
41427                 this.clearValue();
41428             }
41429         }else{
41430             if(rec){
41431                 
41432                 
41433                 
41434                 if (val == rec.get(this.displayField) && this.value == rec.get(this.valueField)){
41435                     return;
41436                 }
41437                 val = rec.get(this.valueField || this.displayField);
41438             }
41439             this.setValue(val);
41440         }
41441     },
41442
41443     
41444     onSelect : function(record, index){
41445         if(this.fireEvent('beforeselect', this, record, index) !== false){
41446             this.setValue(record.data[this.valueField || this.displayField]);
41447             this.collapse();
41448             this.fireEvent('select', this, record, index);
41449         }
41450     },
41451
41452     
41453     getName: function(){
41454         var hf = this.hiddenField;
41455         return hf && hf.name ? hf.name : this.hiddenName || Ext.form.ComboBox.superclass.getName.call(this);
41456     },
41457
41458     
41459     getValue : function(){
41460         if(this.valueField){
41461             return Ext.isDefined(this.value) ? this.value : '';
41462         }else{
41463             return Ext.form.ComboBox.superclass.getValue.call(this);
41464         }
41465     },
41466
41467     
41468     clearValue : function(){
41469         if(this.hiddenField){
41470             this.hiddenField.value = '';
41471         }
41472         this.setRawValue('');
41473         this.lastSelectionText = '';
41474         this.applyEmptyText();
41475         this.value = '';
41476     },
41477
41478     
41479     setValue : function(v){
41480         var text = v;
41481         if(this.valueField){
41482             var r = this.findRecord(this.valueField, v);
41483             if(r){
41484                 text = r.data[this.displayField];
41485             }else if(Ext.isDefined(this.valueNotFoundText)){
41486                 text = this.valueNotFoundText;
41487             }
41488         }
41489         this.lastSelectionText = text;
41490         if(this.hiddenField){
41491             this.hiddenField.value = Ext.value(v, '');
41492         }
41493         Ext.form.ComboBox.superclass.setValue.call(this, text);
41494         this.value = v;
41495         return this;
41496     },
41497
41498     
41499     findRecord : function(prop, value){
41500         var record;
41501         if(this.store.getCount() > 0){
41502             this.store.each(function(r){
41503                 if(r.data[prop] == value){
41504                     record = r;
41505                     return false;
41506                 }
41507             });
41508         }
41509         return record;
41510     },
41511
41512     
41513     onViewMove : function(e, t){
41514         this.inKeyMode = false;
41515     },
41516
41517     
41518     onViewOver : function(e, t){
41519         if(this.inKeyMode){ 
41520             return;
41521         }
41522         var item = this.view.findItemFromChild(t);
41523         if(item){
41524             var index = this.view.indexOf(item);
41525             this.select(index, false);
41526         }
41527     },
41528
41529     
41530     onViewClick : function(doFocus){
41531         var index = this.view.getSelectedIndexes()[0],
41532             s = this.store,
41533             r = s.getAt(index);
41534         if(r){
41535             this.onSelect(r, index);
41536         }else {
41537             this.collapse();
41538         }
41539         if(doFocus !== false){
41540             this.el.focus();
41541         }
41542     },
41543
41544
41545     
41546     restrictHeight : function(){
41547         this.innerList.dom.style.height = '';
41548         var inner = this.innerList.dom,
41549             pad = this.list.getFrameWidth('tb') + (this.resizable ? this.handleHeight : 0) + this.assetHeight,
41550             h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight),
41551             ha = this.getPosition()[1]-Ext.getBody().getScroll().top,
41552             hb = Ext.lib.Dom.getViewHeight()-ha-this.getSize().height,
41553             space = Math.max(ha, hb, this.minHeight || 0)-this.list.shadowOffset-pad-5;
41554
41555         h = Math.min(h, space, this.maxHeight);
41556
41557         this.innerList.setHeight(h);
41558         this.list.beginUpdate();
41559         this.list.setHeight(h+pad);
41560         this.list.alignTo.apply(this.list, [this.el].concat(this.listAlign));
41561         this.list.endUpdate();
41562     },
41563
41564     
41565     isExpanded : function(){
41566         return this.list && this.list.isVisible();
41567     },
41568
41569     
41570     selectByValue : function(v, scrollIntoView){
41571         if(!Ext.isEmpty(v, true)){
41572             var r = this.findRecord(this.valueField || this.displayField, v);
41573             if(r){
41574                 this.select(this.store.indexOf(r), scrollIntoView);
41575                 return true;
41576             }
41577         }
41578         return false;
41579     },
41580
41581     
41582     select : function(index, scrollIntoView){
41583         this.selectedIndex = index;
41584         this.view.select(index);
41585         if(scrollIntoView !== false){
41586             var el = this.view.getNode(index);
41587             if(el){
41588                 this.innerList.scrollChildIntoView(el, false);
41589             }
41590         }
41591
41592     },
41593
41594     
41595     selectNext : function(){
41596         var ct = this.store.getCount();
41597         if(ct > 0){
41598             if(this.selectedIndex == -1){
41599                 this.select(0);
41600             }else if(this.selectedIndex < ct-1){
41601                 this.select(this.selectedIndex+1);
41602             }
41603         }
41604     },
41605
41606     
41607     selectPrev : function(){
41608         var ct = this.store.getCount();
41609         if(ct > 0){
41610             if(this.selectedIndex == -1){
41611                 this.select(0);
41612             }else if(this.selectedIndex !== 0){
41613                 this.select(this.selectedIndex-1);
41614             }
41615         }
41616     },
41617
41618     
41619     onKeyUp : function(e){
41620         var k = e.getKey();
41621         if(this.editable !== false && this.readOnly !== true && (k == e.BACKSPACE || !e.isSpecialKey())){
41622
41623             this.lastKey = k;
41624             this.dqTask.delay(this.queryDelay);
41625         }
41626         Ext.form.ComboBox.superclass.onKeyUp.call(this, e);
41627     },
41628
41629     
41630     validateBlur : function(){
41631         return !this.list || !this.list.isVisible();
41632     },
41633
41634     
41635     initQuery : function(){
41636         this.doQuery(this.getRawValue());
41637     },
41638
41639     
41640     beforeBlur : function(){
41641         this.assertValue();
41642     },
41643
41644     
41645     postBlur  : function(){
41646         Ext.form.ComboBox.superclass.postBlur.call(this);
41647         this.collapse();
41648         this.inKeyMode = false;
41649     },
41650
41651     
41652     doQuery : function(q, forceAll){
41653         q = Ext.isEmpty(q) ? '' : q;
41654         var qe = {
41655             query: q,
41656             forceAll: forceAll,
41657             combo: this,
41658             cancel:false
41659         };
41660         if(this.fireEvent('beforequery', qe)===false || qe.cancel){
41661             return false;
41662         }
41663         q = qe.query;
41664         forceAll = qe.forceAll;
41665         if(forceAll === true || (q.length >= this.minChars)){
41666             if(this.lastQuery !== q){
41667                 this.lastQuery = q;
41668                 if(this.mode == 'local'){
41669                     this.selectedIndex = -1;
41670                     if(forceAll){
41671                         this.store.clearFilter();
41672                     }else{
41673                         this.store.filter(this.displayField, q);
41674                     }
41675                     this.onLoad();
41676                 }else{
41677                     this.store.baseParams[this.queryParam] = q;
41678                     this.store.load({
41679                         params: this.getParams(q)
41680                     });
41681                     this.expand();
41682                 }
41683             }else{
41684                 this.selectedIndex = -1;
41685                 this.onLoad();
41686             }
41687         }
41688     },
41689
41690     
41691     getParams : function(q){
41692         var params = {},
41693             paramNames = this.store.paramNames;
41694         if(this.pageSize){
41695             params[paramNames.start] = 0;
41696             params[paramNames.limit] = this.pageSize;
41697         }
41698         return params;
41699     },
41700
41701     
41702     collapse : function(){
41703         if(!this.isExpanded()){
41704             return;
41705         }
41706         this.list.hide();
41707         Ext.getDoc().un('mousewheel', this.collapseIf, this);
41708         Ext.getDoc().un('mousedown', this.collapseIf, this);
41709         this.fireEvent('collapse', this);
41710     },
41711
41712     
41713     collapseIf : function(e){
41714         if(!this.isDestroyed && !e.within(this.wrap) && !e.within(this.list)){
41715             this.collapse();
41716         }
41717     },
41718
41719     
41720     expand : function(){
41721         if(this.isExpanded() || !this.hasFocus){
41722             return;
41723         }
41724
41725         if(this.title || this.pageSize){
41726             this.assetHeight = 0;
41727             if(this.title){
41728                 this.assetHeight += this.header.getHeight();
41729             }
41730             if(this.pageSize){
41731                 this.assetHeight += this.footer.getHeight();
41732             }
41733         }
41734
41735         if(this.bufferSize){
41736             this.doResize(this.bufferSize);
41737             delete this.bufferSize;
41738         }
41739         this.list.alignTo.apply(this.list, [this.el].concat(this.listAlign));
41740
41741         
41742         this.list.setZIndex(this.getZIndex());
41743         this.list.show();
41744         if(Ext.isGecko2){
41745             this.innerList.setOverflow('auto'); 
41746         }
41747         this.mon(Ext.getDoc(), {
41748             scope: this,
41749             mousewheel: this.collapseIf,
41750             mousedown: this.collapseIf
41751         });
41752         this.fireEvent('expand', this);
41753     },
41754
41755     
41756     
41757     
41758     onTriggerClick : function(){
41759         if(this.readOnly || this.disabled){
41760             return;
41761         }
41762         if(this.isExpanded()){
41763             this.collapse();
41764             this.el.focus();
41765         }else {
41766             this.onFocus({});
41767             if(this.triggerAction == 'all') {
41768                 this.doQuery(this.allQuery, true);
41769             } else {
41770                 this.doQuery(this.getRawValue());
41771             }
41772             this.el.focus();
41773         }
41774     }
41775
41776     
41777     
41778     
41779     
41780
41781 });
41782 Ext.reg('combo', Ext.form.ComboBox);
41783
41784 Ext.form.Checkbox = Ext.extend(Ext.form.Field,  {
41785     
41786     focusClass : undefined,
41787     
41788     fieldClass : 'x-form-field',
41789     
41790     checked : false,
41791     
41792     boxLabel: '&#160;',
41793     
41794     defaultAutoCreate : { tag: 'input', type: 'checkbox', autocomplete: 'off'},
41795     
41796     
41797     
41798     
41799
41800     
41801     actionMode : 'wrap',
41802
41803         
41804     initComponent : function(){
41805         Ext.form.Checkbox.superclass.initComponent.call(this);
41806         this.addEvents(
41807             
41808             'check'
41809         );
41810     },
41811
41812     
41813     onResize : function(){
41814         Ext.form.Checkbox.superclass.onResize.apply(this, arguments);
41815         if(!this.boxLabel && !this.fieldLabel){
41816             this.el.alignTo(this.wrap, 'c-c');
41817         }
41818     },
41819
41820     
41821     initEvents : function(){
41822         Ext.form.Checkbox.superclass.initEvents.call(this);
41823         this.mon(this.el, {
41824             scope: this,
41825             click: this.onClick,
41826             change: this.onClick
41827         });
41828     },
41829
41830     
41831     markInvalid : Ext.emptyFn,
41832     
41833     clearInvalid : Ext.emptyFn,
41834
41835     
41836     onRender : function(ct, position){
41837         Ext.form.Checkbox.superclass.onRender.call(this, ct, position);
41838         if(this.inputValue !== undefined){
41839             this.el.dom.value = this.inputValue;
41840         }
41841         this.wrap = this.el.wrap({cls: 'x-form-check-wrap'});
41842         if(this.boxLabel){
41843             this.wrap.createChild({tag: 'label', htmlFor: this.el.id, cls: 'x-form-cb-label', html: this.boxLabel});
41844         }
41845         if(this.checked){
41846             this.setValue(true);
41847         }else{
41848             this.checked = this.el.dom.checked;
41849         }
41850         
41851         if (Ext.isIE && !Ext.isStrict) {
41852             this.wrap.repaint();
41853         }
41854         this.resizeEl = this.positionEl = this.wrap;
41855     },
41856
41857     
41858     onDestroy : function(){
41859         Ext.destroy(this.wrap);
41860         Ext.form.Checkbox.superclass.onDestroy.call(this);
41861     },
41862
41863     
41864     initValue : function() {
41865         this.originalValue = this.getValue();
41866     },
41867
41868     
41869     getValue : function(){
41870         if(this.rendered){
41871             return this.el.dom.checked;
41872         }
41873         return this.checked;
41874     },
41875
41876         
41877     onClick : function(){
41878         if(this.el.dom.checked != this.checked){
41879             this.setValue(this.el.dom.checked);
41880         }
41881     },
41882
41883     
41884     setValue : function(v){
41885         var checked = this.checked,
41886             inputVal = this.inputValue;
41887             
41888         this.checked = (v === true || v === 'true' || v == '1' || (inputVal ? v == inputVal : String(v).toLowerCase() == 'on'));
41889         if(this.rendered){
41890             this.el.dom.checked = this.checked;
41891             this.el.dom.defaultChecked = this.checked;
41892         }
41893         if(checked != this.checked){
41894             this.fireEvent('check', this, this.checked);
41895             if(this.handler){
41896                 this.handler.call(this.scope || this, this, this.checked);
41897             }
41898         }
41899         return this;
41900     }
41901 });
41902 Ext.reg('checkbox', Ext.form.Checkbox);
41903
41904 Ext.form.CheckboxGroup = Ext.extend(Ext.form.Field, {
41905     
41906     
41907     columns : 'auto',
41908     
41909     vertical : false,
41910     
41911     allowBlank : true,
41912     
41913     blankText : "You must select at least one item in this group",
41914
41915     
41916     defaultType : 'checkbox',
41917
41918     
41919     groupCls : 'x-form-check-group',
41920
41921     
41922     initComponent: function(){
41923         this.addEvents(
41924             
41925             'change'
41926         );
41927         this.on('change', this.validate, this);
41928         Ext.form.CheckboxGroup.superclass.initComponent.call(this);
41929     },
41930
41931     
41932     onRender : function(ct, position){
41933         if(!this.el){
41934             var panelCfg = {
41935                 autoEl: {
41936                     id: this.id
41937                 },
41938                 cls: this.groupCls,
41939                 layout: 'column',
41940                 renderTo: ct,
41941                 bufferResize: false 
41942             };
41943             var colCfg = {
41944                 xtype: 'container',
41945                 defaultType: this.defaultType,
41946                 layout: 'form',
41947                 defaults: {
41948                     hideLabel: true,
41949                     anchor: '100%'
41950                 }
41951             };
41952
41953             if(this.items[0].items){
41954
41955                 
41956
41957                 Ext.apply(panelCfg, {
41958                     layoutConfig: {columns: this.items.length},
41959                     defaults: this.defaults,
41960                     items: this.items
41961                 });
41962                 for(var i=0, len=this.items.length; i<len; i++){
41963                     Ext.applyIf(this.items[i], colCfg);
41964                 }
41965
41966             }else{
41967
41968                 
41969                 
41970
41971                 var numCols, cols = [];
41972
41973                 if(typeof this.columns == 'string'){ 
41974                     this.columns = this.items.length;
41975                 }
41976                 if(!Ext.isArray(this.columns)){
41977                     var cs = [];
41978                     for(var i=0; i<this.columns; i++){
41979                         cs.push((100/this.columns)*.01); 
41980                     }
41981                     this.columns = cs;
41982                 }
41983
41984                 numCols = this.columns.length;
41985
41986                 
41987                 for(var i=0; i<numCols; i++){
41988                     var cc = Ext.apply({items:[]}, colCfg);
41989                     cc[this.columns[i] <= 1 ? 'columnWidth' : 'width'] = this.columns[i];
41990                     if(this.defaults){
41991                         cc.defaults = Ext.apply(cc.defaults || {}, this.defaults);
41992                     }
41993                     cols.push(cc);
41994                 };
41995
41996                 
41997                 if(this.vertical){
41998                     var rows = Math.ceil(this.items.length / numCols), ri = 0;
41999                     for(var i=0, len=this.items.length; i<len; i++){
42000                         if(i>0 && i%rows==0){
42001                             ri++;
42002                         }
42003                         if(this.items[i].fieldLabel){
42004                             this.items[i].hideLabel = false;
42005                         }
42006                         cols[ri].items.push(this.items[i]);
42007                     };
42008                 }else{
42009                     for(var i=0, len=this.items.length; i<len; i++){
42010                         var ci = i % numCols;
42011                         if(this.items[i].fieldLabel){
42012                             this.items[i].hideLabel = false;
42013                         }
42014                         cols[ci].items.push(this.items[i]);
42015                     };
42016                 }
42017
42018                 Ext.apply(panelCfg, {
42019                     layoutConfig: {columns: numCols},
42020                     items: cols
42021                 });
42022             }
42023
42024             this.panel = new Ext.Container(panelCfg);
42025             this.panel.ownerCt = this;
42026             this.el = this.panel.getEl();
42027
42028             if(this.forId && this.itemCls){
42029                 var l = this.el.up(this.itemCls).child('label', true);
42030                 if(l){
42031                     l.setAttribute('htmlFor', this.forId);
42032                 }
42033             }
42034
42035             var fields = this.panel.findBy(function(c){
42036                 return c.isFormField;
42037             }, this);
42038
42039             this.items = new Ext.util.MixedCollection();
42040             this.items.addAll(fields);
42041         }
42042         Ext.form.CheckboxGroup.superclass.onRender.call(this, ct, position);
42043     },
42044
42045     initValue : function(){
42046         if(this.value){
42047             this.setValue.apply(this, this.buffered ? this.value : [this.value]);
42048             delete this.buffered;
42049             delete this.value;
42050         }
42051     },
42052
42053     afterRender : function(){
42054         Ext.form.CheckboxGroup.superclass.afterRender.call(this);
42055         this.eachItem(function(item){
42056             item.on('check', this.fireChecked, this);
42057             item.inGroup = true;
42058         });
42059     },
42060
42061     
42062     doLayout: function(){
42063         
42064         if(this.rendered){
42065             this.panel.forceLayout = this.ownerCt.forceLayout;
42066             this.panel.doLayout();
42067         }
42068     },
42069
42070     
42071     fireChecked: function(){
42072         var arr = [];
42073         this.eachItem(function(item){
42074             if(item.checked){
42075                 arr.push(item);
42076             }
42077         });
42078         this.fireEvent('change', this, arr);
42079     },
42080     
42081     
42082     getErrors: function() {
42083         var errors = Ext.form.CheckboxGroup.superclass.getErrors.apply(this, arguments);
42084         
42085         if (!this.allowBlank) {
42086             var blank = true;
42087             
42088             this.eachItem(function(f){
42089                 if (f.checked) {
42090                     return (blank = false);
42091                 }
42092             });
42093             
42094             if (blank) errors.push(this.blankText);
42095         }
42096         
42097         return errors;
42098     },
42099
42100     
42101     isDirty: function(){
42102         
42103         if (this.disabled || !this.rendered) {
42104             return false;
42105         }
42106
42107         var dirty = false;
42108         
42109         this.eachItem(function(item){
42110             if(item.isDirty()){
42111                 dirty = true;
42112                 return false;
42113             }
42114         });
42115         
42116         return dirty;
42117     },
42118
42119     
42120     setReadOnly : function(readOnly){
42121         if(this.rendered){
42122             this.eachItem(function(item){
42123                 item.setReadOnly(readOnly);
42124             });
42125         }
42126         this.readOnly = readOnly;
42127     },
42128
42129     
42130     onDisable : function(){
42131         this.eachItem(function(item){
42132             item.disable();
42133         });
42134     },
42135
42136     
42137     onEnable : function(){
42138         this.eachItem(function(item){
42139             item.enable();
42140         });
42141     },
42142
42143     
42144     onResize : function(w, h){
42145         this.panel.setSize(w, h);
42146         this.panel.doLayout();
42147     },
42148
42149     
42150     reset : function(){
42151         if (this.originalValue) {
42152             
42153             this.eachItem(function(c){
42154                 if(c.setValue){
42155                     c.setValue(false);
42156                     c.originalValue = c.getValue();
42157                 }
42158             });
42159             
42160             
42161             this.resetOriginal = true;
42162             this.setValue(this.originalValue);
42163             delete this.resetOriginal;
42164         } else {
42165             this.eachItem(function(c){
42166                 if(c.reset){
42167                     c.reset();
42168                 }
42169             });
42170         }
42171         
42172         
42173         (function() {
42174             this.clearInvalid();
42175         }).defer(50, this);
42176     },
42177
42178     
42179     setValue: function(){
42180         if(this.rendered){
42181             this.onSetValue.apply(this, arguments);
42182         }else{
42183             this.buffered = true;
42184             this.value = arguments;
42185         }
42186         return this;
42187     },
42188
42189     
42190     onSetValue: function(id, value){
42191         if(arguments.length == 1){
42192             if(Ext.isArray(id)){
42193                 Ext.each(id, function(val, idx){
42194                     if (Ext.isObject(val) && val.setValue){ 
42195                         val.setValue(true);
42196                         if (this.resetOriginal === true) {
42197                             val.originalValue = val.getValue();
42198                         }
42199                     } else { 
42200                         var item = this.items.itemAt(idx);
42201                         if(item){
42202                             item.setValue(val);
42203                         }
42204                     }
42205                 }, this);
42206             }else if(Ext.isObject(id)){
42207                 
42208                 for(var i in id){
42209                     var f = this.getBox(i);
42210                     if(f){
42211                         f.setValue(id[i]);
42212                     }
42213                 }
42214             }else{
42215                 this.setValueForItem(id);
42216             }
42217         }else{
42218             var f = this.getBox(id);
42219             if(f){
42220                 f.setValue(value);
42221             }
42222         }
42223     },
42224
42225     
42226     beforeDestroy: function(){
42227         Ext.destroy(this.panel);
42228         if (!this.rendered) {
42229             Ext.destroy(this.items);
42230         }
42231         Ext.form.CheckboxGroup.superclass.beforeDestroy.call(this);
42232
42233     },
42234
42235     setValueForItem : function(val){
42236         val = String(val).split(',');
42237         this.eachItem(function(item){
42238             if(val.indexOf(item.inputValue)> -1){
42239                 item.setValue(true);
42240             }
42241         });
42242     },
42243
42244     
42245     getBox : function(id){
42246         var box = null;
42247         this.eachItem(function(f){
42248             if(id == f || f.dataIndex == id || f.id == id || f.getName() == id){
42249                 box = f;
42250                 return false;
42251             }
42252         });
42253         return box;
42254     },
42255
42256     
42257     getValue : function(){
42258         var out = [];
42259         this.eachItem(function(item){
42260             if(item.checked){
42261                 out.push(item);
42262             }
42263         });
42264         return out;
42265     },
42266
42267     
42268     eachItem: function(fn, scope) {
42269         if(this.items && this.items.each){
42270             this.items.each(fn, scope || this);
42271         }
42272     },
42273
42274     
42275
42276     
42277     getRawValue : Ext.emptyFn,
42278
42279     
42280     setRawValue : Ext.emptyFn
42281
42282 });
42283
42284 Ext.reg('checkboxgroup', Ext.form.CheckboxGroup);
42285
42286 Ext.form.CompositeField = Ext.extend(Ext.form.Field, {
42287
42288     
42289     defaultMargins: '0 5 0 0',
42290
42291     
42292     skipLastItemMargin: true,
42293
42294     
42295     isComposite: true,
42296
42297     
42298     combineErrors: true,
42299     
42300     
42301     labelConnector: ', ',
42302     
42303     
42304
42305     
42306     
42307     initComponent: function() {
42308         var labels = [],
42309             items  = this.items,
42310             item;
42311
42312         for (var i=0, j = items.length; i < j; i++) {
42313             item = items[i];
42314
42315             labels.push(item.fieldLabel);
42316
42317             
42318             Ext.applyIf(item, this.defaults);
42319
42320             
42321             if (!(i == j - 1 && this.skipLastItemMargin)) {
42322                 Ext.applyIf(item, {margins: this.defaultMargins});
42323             }
42324         }
42325
42326         this.fieldLabel = this.fieldLabel || this.buildLabel(labels);
42327
42328         
42329         this.fieldErrors = new Ext.util.MixedCollection(true, function(item) {
42330             return item.field;
42331         });
42332
42333         this.fieldErrors.on({
42334             scope  : this,
42335             add    : this.updateInvalidMark,
42336             remove : this.updateInvalidMark,
42337             replace: this.updateInvalidMark
42338         });
42339
42340         Ext.form.CompositeField.superclass.initComponent.apply(this, arguments);
42341         
42342         this.innerCt = new Ext.Container({
42343             layout  : 'hbox',
42344             items   : this.items,
42345             cls     : 'x-form-composite',
42346             defaultMargins: '0 3 0 0'
42347         });
42348         
42349         var fields = this.innerCt.findBy(function(c) {
42350             return c.isFormField;
42351         }, this);
42352
42353         
42354         this.items = new Ext.util.MixedCollection();
42355         this.items.addAll(fields);
42356         
42357     },
42358
42359     
42360     onRender: function(ct, position) {
42361         if (!this.el) {
42362             
42363             var innerCt = this.innerCt;
42364             innerCt.render(ct);
42365
42366             this.el = innerCt.getEl();
42367
42368             
42369             
42370             if (this.combineErrors) {
42371                 this.eachItem(function(field) {
42372                     Ext.apply(field, {
42373                         markInvalid : this.onFieldMarkInvalid.createDelegate(this, [field], 0),
42374                         clearInvalid: this.onFieldClearInvalid.createDelegate(this, [field], 0)
42375                     });
42376                 });
42377             }
42378
42379             
42380             var l = this.el.parent().parent().child('label', true);
42381             if (l) {
42382                 l.setAttribute('for', this.items.items[0].id);
42383             }
42384         }
42385
42386         Ext.form.CompositeField.superclass.onRender.apply(this, arguments);
42387     },
42388
42389     
42390     onFieldMarkInvalid: function(field, message) {
42391         var name  = field.getName(),
42392             error = {
42393                 field: name, 
42394                 errorName: field.fieldLabel || name,
42395                 error: message
42396             };
42397
42398         this.fieldErrors.replace(name, error);
42399
42400         field.el.addClass(field.invalidClass);
42401     },
42402
42403     
42404     onFieldClearInvalid: function(field) {
42405         this.fieldErrors.removeKey(field.getName());
42406
42407         field.el.removeClass(field.invalidClass);
42408     },
42409
42410     
42411     updateInvalidMark: function() {
42412         var ieStrict = Ext.isIE6 && Ext.isStrict;
42413
42414         if (this.fieldErrors.length == 0) {
42415             this.clearInvalid();
42416
42417             
42418             if (ieStrict) {
42419                 this.clearInvalid.defer(50, this);
42420             }
42421         } else {
42422             var message = this.buildCombinedErrorMessage(this.fieldErrors.items);
42423
42424             this.sortErrors();
42425             this.markInvalid(message);
42426
42427             
42428             if (ieStrict) {
42429                 this.markInvalid(message);
42430             }
42431         }
42432     },
42433
42434     
42435     validateValue: function() {
42436         var valid = true;
42437
42438         this.eachItem(function(field) {
42439             if (!field.isValid()) valid = false;
42440         });
42441
42442         return valid;
42443     },
42444
42445     
42446     buildCombinedErrorMessage: function(errors) {
42447         var combined = [],
42448             error;
42449
42450         for (var i = 0, j = errors.length; i < j; i++) {
42451             error = errors[i];
42452
42453             combined.push(String.format("{0}: {1}", error.errorName, error.error));
42454         }
42455
42456         return combined.join("<br />");
42457     },
42458
42459     
42460     sortErrors: function() {
42461         var fields = this.items;
42462
42463         this.fieldErrors.sort("ASC", function(a, b) {
42464             var findByName = function(key) {
42465                 return function(field) {
42466                     return field.getName() == key;
42467                 };
42468             };
42469
42470             var aIndex = fields.findIndexBy(findByName(a.field)),
42471                 bIndex = fields.findIndexBy(findByName(b.field));
42472
42473             return aIndex < bIndex ? -1 : 1;
42474         });
42475     },
42476
42477     
42478     reset: function() {
42479         this.eachItem(function(item) {
42480             item.reset();
42481         });
42482
42483         
42484         
42485         (function() {
42486             this.clearInvalid();
42487         }).defer(50, this);
42488     },
42489     
42490     
42491     clearInvalidChildren: function() {
42492         this.eachItem(function(item) {
42493             item.clearInvalid();
42494         });
42495     },
42496
42497     
42498     buildLabel: function(segments) {
42499         return Ext.clean(segments).join(this.labelConnector);
42500     },
42501
42502     
42503     isDirty: function(){
42504         
42505         if (this.disabled || !this.rendered) {
42506             return false;
42507         }
42508
42509         var dirty = false;
42510         this.eachItem(function(item){
42511             if(item.isDirty()){
42512                 dirty = true;
42513                 return false;
42514             }
42515         });
42516         return dirty;
42517     },
42518
42519     
42520     eachItem: function(fn, scope) {
42521         if(this.items && this.items.each){
42522             this.items.each(fn, scope || this);
42523         }
42524     },
42525
42526     
42527     onResize: function(adjWidth, adjHeight, rawWidth, rawHeight) {
42528         var innerCt = this.innerCt;
42529
42530         if (this.rendered && innerCt.rendered) {
42531             innerCt.setSize(adjWidth, adjHeight);
42532         }
42533
42534         Ext.form.CompositeField.superclass.onResize.apply(this, arguments);
42535     },
42536
42537     
42538     doLayout: function(shallow, force) {
42539         if (this.rendered) {
42540             var innerCt = this.innerCt;
42541
42542             innerCt.forceLayout = this.ownerCt.forceLayout;
42543             innerCt.doLayout(shallow, force);
42544         }
42545     },
42546
42547     
42548     beforeDestroy: function(){
42549         Ext.destroy(this.innerCt);
42550
42551         Ext.form.CompositeField.superclass.beforeDestroy.call(this);
42552     },
42553
42554     
42555     setReadOnly : function(readOnly) {
42556         if (readOnly == undefined) {
42557             readOnly = true;
42558         }
42559         readOnly = !!readOnly;
42560
42561         if(this.rendered){
42562             this.eachItem(function(item){
42563                 item.setReadOnly(readOnly);
42564             });
42565         }
42566         this.readOnly = readOnly;
42567     },
42568
42569     onShow : function() {
42570         Ext.form.CompositeField.superclass.onShow.call(this);
42571         this.doLayout();
42572     },
42573
42574     
42575     onDisable : function(){
42576         this.eachItem(function(item){
42577             item.disable();
42578         });
42579     },
42580
42581     
42582     onEnable : function(){
42583         this.eachItem(function(item){
42584             item.enable();
42585         });
42586     }
42587 });
42588
42589 Ext.reg('compositefield', Ext.form.CompositeField);
42590 Ext.form.Radio = Ext.extend(Ext.form.Checkbox, {
42591     inputType: 'radio',
42592
42593     
42594     markInvalid : Ext.emptyFn,
42595     
42596     clearInvalid : Ext.emptyFn,
42597
42598     
42599     getGroupValue : function(){
42600         var p = this.el.up('form') || Ext.getBody();
42601         var c = p.child('input[name='+this.el.dom.name+']:checked', true);
42602         return c ? c.value : null;
42603     },
42604
42605     
42606     setValue : function(v){
42607         var checkEl,
42608             els,
42609             radio;
42610         if (typeof v == 'boolean') {
42611             Ext.form.Radio.superclass.setValue.call(this, v);
42612         } else if (this.rendered) {
42613             checkEl = this.getCheckEl();
42614             radio = checkEl.child('input[name=' + this.el.dom.name + '][value=' + v + ']', true);
42615             if(radio){
42616                 Ext.getCmp(radio.id).setValue(true);
42617             }
42618         }
42619         if(this.rendered && this.checked){
42620             checkEl = checkEl || this.getCheckEl();
42621             els = this.getCheckEl().select('input[name=' + this.el.dom.name + ']');
42622                         els.each(function(el){
42623                                 if(el.dom.id != this.id){
42624                                         Ext.getCmp(el.dom.id).setValue(false);
42625                                 }
42626                         }, this);
42627         }
42628         return this;
42629     },
42630
42631     
42632     getCheckEl: function(){
42633         if(this.inGroup){
42634             return this.el.up('.x-form-radio-group');
42635         }
42636         return this.el.up('form') || Ext.getBody();
42637     }
42638 });
42639 Ext.reg('radio', Ext.form.Radio);
42640
42641 Ext.form.RadioGroup = Ext.extend(Ext.form.CheckboxGroup, {
42642     
42643     
42644     allowBlank : true,
42645     
42646     blankText : 'You must select one item in this group',
42647     
42648     
42649     defaultType : 'radio',
42650     
42651     
42652     groupCls : 'x-form-radio-group',
42653     
42654     
42655     
42656     
42657     getValue : function(){
42658         var out = null;
42659         this.eachItem(function(item){
42660             if(item.checked){
42661                 out = item;
42662                 return false;
42663             }
42664         });
42665         return out;
42666     },
42667     
42668     
42669     onSetValue : function(id, value){
42670         if(arguments.length > 1){
42671             var f = this.getBox(id);
42672             if(f){
42673                 f.setValue(value);
42674                 if(f.checked){
42675                     this.eachItem(function(item){
42676                         if (item !== f){
42677                             item.setValue(false);
42678                         }
42679                     });
42680                 }
42681             }
42682         }else{
42683             this.setValueForItem(id);
42684         }
42685     },
42686     
42687     setValueForItem : function(val){
42688         val = String(val).split(',')[0];
42689         this.eachItem(function(item){
42690             item.setValue(val == item.inputValue);
42691         });
42692     },
42693     
42694     
42695     fireChecked : function(){
42696         if(!this.checkTask){
42697             this.checkTask = new Ext.util.DelayedTask(this.bufferChecked, this);
42698         }
42699         this.checkTask.delay(10);
42700     },
42701     
42702     
42703     bufferChecked : function(){
42704         var out = null;
42705         this.eachItem(function(item){
42706             if(item.checked){
42707                 out = item;
42708                 return false;
42709             }
42710         });
42711         this.fireEvent('change', this, out);
42712     },
42713     
42714     onDestroy : function(){
42715         if(this.checkTask){
42716             this.checkTask.cancel();
42717             this.checkTask = null;
42718         }
42719         Ext.form.RadioGroup.superclass.onDestroy.call(this);
42720     }
42721
42722 });
42723
42724 Ext.reg('radiogroup', Ext.form.RadioGroup);
42725
42726 Ext.form.Hidden = Ext.extend(Ext.form.Field, {
42727     
42728     inputType : 'hidden',
42729     
42730     shouldLayout: false,
42731
42732     
42733     onRender : function(){
42734         Ext.form.Hidden.superclass.onRender.apply(this, arguments);
42735     },
42736
42737     
42738     initEvents : function(){
42739         this.originalValue = this.getValue();
42740     },
42741
42742     
42743     setSize : Ext.emptyFn,
42744     setWidth : Ext.emptyFn,
42745     setHeight : Ext.emptyFn,
42746     setPosition : Ext.emptyFn,
42747     setPagePosition : Ext.emptyFn,
42748     markInvalid : Ext.emptyFn,
42749     clearInvalid : Ext.emptyFn
42750 });
42751 Ext.reg('hidden', Ext.form.Hidden);
42752 Ext.form.BasicForm = Ext.extend(Ext.util.Observable, {
42753
42754     constructor: function(el, config){
42755         Ext.apply(this, config);
42756         if(Ext.isString(this.paramOrder)){
42757             this.paramOrder = this.paramOrder.split(/[\s,|]/);
42758         }
42759         
42760         this.items = new Ext.util.MixedCollection(false, function(o){
42761             return o.getItemId();
42762         });
42763         this.addEvents(
42764             
42765             'beforeaction',
42766             
42767             'actionfailed',
42768             
42769             'actioncomplete'
42770         );
42771
42772         if(el){
42773             this.initEl(el);
42774         }
42775         Ext.form.BasicForm.superclass.constructor.call(this);
42776     },
42777
42778     
42779     
42780     
42781     
42782     
42783     
42784     
42785     timeout: 30,
42786
42787     
42788
42789     
42790     paramOrder: undefined,
42791
42792     
42793     paramsAsHash: false,
42794
42795     
42796     waitTitle: 'Please Wait...',
42797
42798     
42799     activeAction : null,
42800
42801     
42802     trackResetOnLoad : false,
42803
42804     
42805     
42806
42807     
42808     initEl : function(el){
42809         this.el = Ext.get(el);
42810         this.id = this.el.id || Ext.id();
42811         if(!this.standardSubmit){
42812             this.el.on('submit', this.onSubmit, this);
42813         }
42814         this.el.addClass('x-form');
42815     },
42816
42817     
42818     getEl: function(){
42819         return this.el;
42820     },
42821
42822     
42823     onSubmit : function(e){
42824         e.stopEvent();
42825     },
42826
42827     
42828     destroy: function(bound){
42829         if(bound !== true){
42830             this.items.each(function(f){
42831                 Ext.destroy(f);
42832             });
42833             Ext.destroy(this.el);
42834         }
42835         this.items.clear();
42836         this.purgeListeners();
42837     },
42838
42839     
42840     isValid : function(){
42841         var valid = true;
42842         this.items.each(function(f){
42843            if(!f.validate()){
42844                valid = false;
42845            }
42846         });
42847         return valid;
42848     },
42849
42850     
42851     isDirty : function(){
42852         var dirty = false;
42853         this.items.each(function(f){
42854            if(f.isDirty()){
42855                dirty = true;
42856                return false;
42857            }
42858         });
42859         return dirty;
42860     },
42861
42862     
42863     doAction : function(action, options){
42864         if(Ext.isString(action)){
42865             action = new Ext.form.Action.ACTION_TYPES[action](this, options);
42866         }
42867         if(this.fireEvent('beforeaction', this, action) !== false){
42868             this.beforeAction(action);
42869             action.run.defer(100, action);
42870         }
42871         return this;
42872     },
42873
42874     
42875     submit : function(options){
42876         options = options || {};
42877         if(this.standardSubmit){
42878             var v = options.clientValidation === false || this.isValid();
42879             if(v){
42880                 var el = this.el.dom;
42881                 if(this.url && Ext.isEmpty(el.action)){
42882                     el.action = this.url;
42883                 }
42884                 el.submit();
42885             }
42886             return v;
42887         }
42888         var submitAction = String.format('{0}submit', this.api ? 'direct' : '');
42889         this.doAction(submitAction, options);
42890         return this;
42891     },
42892
42893     
42894     load : function(options){
42895         var loadAction = String.format('{0}load', this.api ? 'direct' : '');
42896         this.doAction(loadAction, options);
42897         return this;
42898     },
42899
42900     
42901     updateRecord : function(record){
42902         record.beginEdit();
42903         var fs = record.fields;
42904         fs.each(function(f){
42905             var field = this.findField(f.name);
42906             if(field){
42907                 var value = field.getValue();
42908                 if ( value.getGroupValue ) {
42909                     value = value.getGroupValue();
42910                 } else if ( field.eachItem ) {
42911                     value = [];
42912                     field.eachItem(function(item){
42913                         value.push(item.getValue());
42914                     });
42915                 }
42916                 record.set(f.name, value);
42917             }
42918         }, this);
42919         record.endEdit();
42920         return this;
42921     },
42922
42923     
42924     loadRecord : function(record){
42925         this.setValues(record.data);
42926         return this;
42927     },
42928
42929     
42930     beforeAction : function(action){
42931         
42932         this.items.each(function(f){
42933             if(f.isFormField && f.syncValue){
42934                 f.syncValue();
42935             }
42936         });
42937         var o = action.options;
42938         if(o.waitMsg){
42939             if(this.waitMsgTarget === true){
42940                 this.el.mask(o.waitMsg, 'x-mask-loading');
42941             }else if(this.waitMsgTarget){
42942                 this.waitMsgTarget = Ext.get(this.waitMsgTarget);
42943                 this.waitMsgTarget.mask(o.waitMsg, 'x-mask-loading');
42944             }else{
42945                 Ext.MessageBox.wait(o.waitMsg, o.waitTitle || this.waitTitle);
42946             }
42947         }
42948     },
42949
42950     
42951     afterAction : function(action, success){
42952         this.activeAction = null;
42953         var o = action.options;
42954         if(o.waitMsg){
42955             if(this.waitMsgTarget === true){
42956                 this.el.unmask();
42957             }else if(this.waitMsgTarget){
42958                 this.waitMsgTarget.unmask();
42959             }else{
42960                 Ext.MessageBox.updateProgress(1);
42961                 Ext.MessageBox.hide();
42962             }
42963         }
42964         if(success){
42965             if(o.reset){
42966                 this.reset();
42967             }
42968             Ext.callback(o.success, o.scope, [this, action]);
42969             this.fireEvent('actioncomplete', this, action);
42970         }else{
42971             Ext.callback(o.failure, o.scope, [this, action]);
42972             this.fireEvent('actionfailed', this, action);
42973         }
42974     },
42975
42976     
42977     findField : function(id) {
42978         var field = this.items.get(id);
42979
42980         if (!Ext.isObject(field)) {
42981             
42982             var findMatchingField = function(f) {
42983                 if (f.isFormField) {
42984                     if (f.dataIndex == id || f.id == id || f.getName() == id) {
42985                         field = f;
42986                         return false;
42987                     } else if (f.isComposite) {
42988                         return f.items.each(findMatchingField);
42989                     } else if (f instanceof Ext.form.CheckboxGroup && f.rendered) {
42990                         return f.eachItem(findMatchingField);
42991                     }
42992                 }
42993             };
42994
42995             this.items.each(findMatchingField);
42996         }
42997         return field || null;
42998     },
42999
43000
43001     
43002     markInvalid : function(errors){
43003         if (Ext.isArray(errors)) {
43004             for(var i = 0, len = errors.length; i < len; i++){
43005                 var fieldError = errors[i];
43006                 var f = this.findField(fieldError.id);
43007                 if(f){
43008                     f.markInvalid(fieldError.msg);
43009                 }
43010             }
43011         } else {
43012             var field, id;
43013             for(id in errors){
43014                 if(!Ext.isFunction(errors[id]) && (field = this.findField(id))){
43015                     field.markInvalid(errors[id]);
43016                 }
43017             }
43018         }
43019
43020         return this;
43021     },
43022
43023     
43024     setValues : function(values){
43025         if(Ext.isArray(values)){ 
43026             for(var i = 0, len = values.length; i < len; i++){
43027                 var v = values[i];
43028                 var f = this.findField(v.id);
43029                 if(f){
43030                     f.setValue(v.value);
43031                     if(this.trackResetOnLoad){
43032                         f.originalValue = f.getValue();
43033                     }
43034                 }
43035             }
43036         }else{ 
43037             var field, id;
43038             for(id in values){
43039                 if(!Ext.isFunction(values[id]) && (field = this.findField(id))){
43040                     field.setValue(values[id]);
43041                     if(this.trackResetOnLoad){
43042                         field.originalValue = field.getValue();
43043                     }
43044                 }
43045             }
43046         }
43047         return this;
43048     },
43049
43050     
43051     getValues : function(asString){
43052         var fs = Ext.lib.Ajax.serializeForm(this.el.dom);
43053         if(asString === true){
43054             return fs;
43055         }
43056         return Ext.urlDecode(fs);
43057     },
43058
43059     
43060     getFieldValues : function(dirtyOnly){
43061         var o = {},
43062             n,
43063             key,
43064             val;
43065         this.items.each(function(f) {
43066             if (!f.disabled && (dirtyOnly !== true || f.isDirty())) {
43067                 n = f.getName();
43068                 key = o[n];
43069                 val = f.getValue();
43070
43071                 if(Ext.isDefined(key)){
43072                     if(Ext.isArray(key)){
43073                         o[n].push(val);
43074                     }else{
43075                         o[n] = [key, val];
43076                     }
43077                 }else{
43078                     o[n] = val;
43079                 }
43080             }
43081         });
43082         return o;
43083     },
43084
43085     
43086     clearInvalid : function(){
43087         this.items.each(function(f){
43088            f.clearInvalid();
43089         });
43090         return this;
43091     },
43092
43093     
43094     reset : function(){
43095         this.items.each(function(f){
43096             f.reset();
43097         });
43098         return this;
43099     },
43100
43101     
43102     add : function(){
43103         this.items.addAll(Array.prototype.slice.call(arguments, 0));
43104         return this;
43105     },
43106
43107     
43108     remove : function(field){
43109         this.items.remove(field);
43110         return this;
43111     },
43112
43113     
43114     cleanDestroyed : function() {
43115         this.items.filterBy(function(o) { return !!o.isDestroyed; }).each(this.remove, this);
43116     },
43117
43118     
43119     render : function(){
43120         this.items.each(function(f){
43121             if(f.isFormField && !f.rendered && document.getElementById(f.id)){ 
43122                 f.applyToMarkup(f.id);
43123             }
43124         });
43125         return this;
43126     },
43127
43128     
43129     applyToFields : function(o){
43130         this.items.each(function(f){
43131            Ext.apply(f, o);
43132         });
43133         return this;
43134     },
43135
43136     
43137     applyIfToFields : function(o){
43138         this.items.each(function(f){
43139            Ext.applyIf(f, o);
43140         });
43141         return this;
43142     },
43143
43144     callFieldMethod : function(fnName, args){
43145         args = args || [];
43146         this.items.each(function(f){
43147             if(Ext.isFunction(f[fnName])){
43148                 f[fnName].apply(f, args);
43149             }
43150         });
43151         return this;
43152     }
43153 });
43154
43155
43156 Ext.BasicForm = Ext.form.BasicForm;
43157
43158 Ext.FormPanel = Ext.extend(Ext.Panel, {
43159     
43160     
43161     
43162     
43163     
43164     
43165     
43166
43167
43168     
43169     minButtonWidth : 75,
43170
43171     
43172     labelAlign : 'left',
43173
43174     
43175     monitorValid : false,
43176
43177     
43178     monitorPoll : 200,
43179
43180     
43181     layout : 'form',
43182
43183     
43184     initComponent : function(){
43185         this.form = this.createForm();
43186         Ext.FormPanel.superclass.initComponent.call(this);
43187
43188         this.bodyCfg = {
43189             tag: 'form',
43190             cls: this.baseCls + '-body',
43191             method : this.method || 'POST',
43192             id : this.formId || Ext.id()
43193         };
43194         if(this.fileUpload) {
43195             this.bodyCfg.enctype = 'multipart/form-data';
43196         }
43197         this.initItems();
43198
43199         this.addEvents(
43200             
43201             'clientvalidation'
43202         );
43203
43204         this.relayEvents(this.form, ['beforeaction', 'actionfailed', 'actioncomplete']);
43205     },
43206
43207     
43208     createForm : function(){
43209         var config = Ext.applyIf({listeners: {}}, this.initialConfig);
43210         return new Ext.form.BasicForm(null, config);
43211     },
43212
43213     
43214     initFields : function(){
43215         var f = this.form;
43216         var formPanel = this;
43217         var fn = function(c){
43218             if(formPanel.isField(c)){
43219                 f.add(c);
43220             }else if(c.findBy && c != formPanel){
43221                 formPanel.applySettings(c);
43222                 
43223                 if(c.items && c.items.each){
43224                     c.items.each(fn, this);
43225                 }
43226             }
43227         };
43228         this.items.each(fn, this);
43229     },
43230
43231     
43232     applySettings: function(c){
43233         var ct = c.ownerCt;
43234         Ext.applyIf(c, {
43235             labelAlign: ct.labelAlign,
43236             labelWidth: ct.labelWidth,
43237             itemCls: ct.itemCls
43238         });
43239     },
43240
43241     
43242     getLayoutTarget : function(){
43243         return this.form.el;
43244     },
43245
43246     
43247     getForm : function(){
43248         return this.form;
43249     },
43250
43251     
43252     onRender : function(ct, position){
43253         this.initFields();
43254         Ext.FormPanel.superclass.onRender.call(this, ct, position);
43255         this.form.initEl(this.body);
43256     },
43257
43258     
43259     beforeDestroy : function(){
43260         this.stopMonitoring();
43261         this.form.destroy(true);
43262         Ext.FormPanel.superclass.beforeDestroy.call(this);
43263     },
43264
43265     
43266     isField : function(c) {
43267         return !!c.setValue && !!c.getValue && !!c.markInvalid && !!c.clearInvalid;
43268     },
43269
43270     
43271     initEvents : function(){
43272         Ext.FormPanel.superclass.initEvents.call(this);
43273         
43274         this.on({
43275             scope: this,
43276             add: this.onAddEvent,
43277             remove: this.onRemoveEvent
43278         });
43279         if(this.monitorValid){ 
43280             this.startMonitoring();
43281         }
43282     },
43283
43284     
43285     onAdd: function(c){
43286         Ext.FormPanel.superclass.onAdd.call(this, c);
43287         this.processAdd(c);
43288     },
43289
43290     
43291     onAddEvent: function(ct, c){
43292         if(ct !== this){
43293             this.processAdd(c);
43294         }
43295     },
43296
43297     
43298     processAdd : function(c){
43299         
43300         if(this.isField(c)){
43301             this.form.add(c);
43302         
43303         }else if(c.findBy){
43304             this.applySettings(c);
43305             this.form.add.apply(this.form, c.findBy(this.isField));
43306         }
43307     },
43308
43309     
43310     onRemove: function(c){
43311         Ext.FormPanel.superclass.onRemove.call(this, c);
43312         this.processRemove(c);
43313     },
43314
43315     onRemoveEvent: function(ct, c){
43316         if(ct !== this){
43317             this.processRemove(c);
43318         }
43319     },
43320
43321     
43322     processRemove: function(c){
43323         if(!this.destroying){
43324             
43325             if(this.isField(c)){
43326                 this.form.remove(c);
43327             
43328             }else if (c.findBy){
43329                 Ext.each(c.findBy(this.isField), this.form.remove, this.form);
43330                 
43331                 this.form.cleanDestroyed();
43332             }
43333         }
43334     },
43335
43336     
43337     startMonitoring : function(){
43338         if(!this.validTask){
43339             this.validTask = new Ext.util.TaskRunner();
43340             this.validTask.start({
43341                 run : this.bindHandler,
43342                 interval : this.monitorPoll || 200,
43343                 scope: this
43344             });
43345         }
43346     },
43347
43348     
43349     stopMonitoring : function(){
43350         if(this.validTask){
43351             this.validTask.stopAll();
43352             this.validTask = null;
43353         }
43354     },
43355
43356     
43357     load : function(){
43358         this.form.load.apply(this.form, arguments);
43359     },
43360
43361     
43362     onDisable : function(){
43363         Ext.FormPanel.superclass.onDisable.call(this);
43364         if(this.form){
43365             this.form.items.each(function(){
43366                  this.disable();
43367             });
43368         }
43369     },
43370
43371     
43372     onEnable : function(){
43373         Ext.FormPanel.superclass.onEnable.call(this);
43374         if(this.form){
43375             this.form.items.each(function(){
43376                  this.enable();
43377             });
43378         }
43379     },
43380
43381     
43382     bindHandler : function(){
43383         var valid = true;
43384         this.form.items.each(function(f){
43385             if(!f.isValid(true)){
43386                 valid = false;
43387                 return false;
43388             }
43389         });
43390         if(this.fbar){
43391             var fitems = this.fbar.items.items;
43392             for(var i = 0, len = fitems.length; i < len; i++){
43393                 var btn = fitems[i];
43394                 if(btn.formBind === true && btn.disabled === valid){
43395                     btn.setDisabled(!valid);
43396                 }
43397             }
43398         }
43399         this.fireEvent('clientvalidation', this, valid);
43400     }
43401 });
43402 Ext.reg('form', Ext.FormPanel);
43403
43404 Ext.form.FormPanel = Ext.FormPanel;
43405
43406 Ext.form.FieldSet = Ext.extend(Ext.Panel, {
43407     
43408     
43409     
43410     
43411     
43412     
43413     baseCls : 'x-fieldset',
43414     
43415     layout : 'form',
43416     
43417     animCollapse : false,
43418
43419     
43420     onRender : function(ct, position){
43421         if(!this.el){
43422             this.el = document.createElement('fieldset');
43423             this.el.id = this.id;
43424             if (this.title || this.header || this.checkboxToggle) {
43425                 this.el.appendChild(document.createElement('legend')).className = this.baseCls + '-header';
43426             }
43427         }
43428
43429         Ext.form.FieldSet.superclass.onRender.call(this, ct, position);
43430
43431         if(this.checkboxToggle){
43432             var o = typeof this.checkboxToggle == 'object' ?
43433                     this.checkboxToggle :
43434                     {tag: 'input', type: 'checkbox', name: this.checkboxName || this.id+'-checkbox'};
43435             this.checkbox = this.header.insertFirst(o);
43436             this.checkbox.dom.checked = !this.collapsed;
43437             this.mon(this.checkbox, 'click', this.onCheckClick, this);
43438         }
43439     },
43440
43441     
43442     onCollapse : function(doAnim, animArg){
43443         if(this.checkbox){
43444             this.checkbox.dom.checked = false;
43445         }
43446         Ext.form.FieldSet.superclass.onCollapse.call(this, doAnim, animArg);
43447
43448     },
43449
43450     
43451     onExpand : function(doAnim, animArg){
43452         if(this.checkbox){
43453             this.checkbox.dom.checked = true;
43454         }
43455         Ext.form.FieldSet.superclass.onExpand.call(this, doAnim, animArg);
43456     },
43457
43458     
43459     onCheckClick : function(){
43460         this[this.checkbox.dom.checked ? 'expand' : 'collapse']();
43461     }
43462
43463     
43464     
43465     
43466     
43467     
43468     
43469     
43470     
43471     
43472     
43473     
43474     
43475     
43476     
43477     
43478     
43479     
43480     
43481     
43482     
43483     
43484     
43485     
43486     
43487     
43488     
43489     
43490     
43491     
43492     
43493     
43494     
43495     
43496     
43497 });
43498 Ext.reg('fieldset', Ext.form.FieldSet);
43499
43500 Ext.form.HtmlEditor = Ext.extend(Ext.form.Field, {
43501     
43502     enableFormat : true,
43503     
43504     enableFontSize : true,
43505     
43506     enableColors : true,
43507     
43508     enableAlignments : true,
43509     
43510     enableLists : true,
43511     
43512     enableSourceEdit : true,
43513     
43514     enableLinks : true,
43515     
43516     enableFont : true,
43517     
43518     createLinkText : 'Please enter the URL for the link:',
43519     
43520     defaultLinkValue : 'http:/'+'/',
43521     
43522     fontFamilies : [
43523         'Arial',
43524         'Courier New',
43525         'Tahoma',
43526         'Times New Roman',
43527         'Verdana'
43528     ],
43529     defaultFont: 'tahoma',
43530     
43531     defaultValue: (Ext.isOpera || Ext.isIE6) ? '&#160;' : '&#8203;',
43532
43533     
43534     actionMode: 'wrap',
43535     validationEvent : false,
43536     deferHeight: true,
43537     initialized : false,
43538     activated : false,
43539     sourceEditMode : false,
43540     onFocus : Ext.emptyFn,
43541     iframePad:3,
43542     hideMode:'offsets',
43543     defaultAutoCreate : {
43544         tag: "textarea",
43545         style:"width:500px;height:300px;",
43546         autocomplete: "off"
43547     },
43548
43549     
43550     initComponent : function(){
43551         this.addEvents(
43552             
43553             'initialize',
43554             
43555             'activate',
43556              
43557             'beforesync',
43558              
43559             'beforepush',
43560              
43561             'sync',
43562              
43563             'push',
43564              
43565             'editmodechange'
43566         );
43567         Ext.form.HtmlEditor.superclass.initComponent.call(this);
43568     },
43569
43570     
43571     createFontOptions : function(){
43572         var buf = [], fs = this.fontFamilies, ff, lc;
43573         for(var i = 0, len = fs.length; i< len; i++){
43574             ff = fs[i];
43575             lc = ff.toLowerCase();
43576             buf.push(
43577                 '<option value="',lc,'" style="font-family:',ff,';"',
43578                     (this.defaultFont == lc ? ' selected="true">' : '>'),
43579                     ff,
43580                 '</option>'
43581             );
43582         }
43583         return buf.join('');
43584     },
43585
43586     
43587     createToolbar : function(editor){
43588         var items = [];
43589         var tipsEnabled = Ext.QuickTips && Ext.QuickTips.isEnabled();
43590
43591
43592         function btn(id, toggle, handler){
43593             return {
43594                 itemId : id,
43595                 cls : 'x-btn-icon',
43596                 iconCls: 'x-edit-'+id,
43597                 enableToggle:toggle !== false,
43598                 scope: editor,
43599                 handler:handler||editor.relayBtnCmd,
43600                 clickEvent:'mousedown',
43601                 tooltip: tipsEnabled ? editor.buttonTips[id] || undefined : undefined,
43602                 overflowText: editor.buttonTips[id].title || undefined,
43603                 tabIndex:-1
43604             };
43605         }
43606
43607
43608         if(this.enableFont && !Ext.isSafari2){
43609             var fontSelectItem = new Ext.Toolbar.Item({
43610                autoEl: {
43611                     tag:'select',
43612                     cls:'x-font-select',
43613                     html: this.createFontOptions()
43614                }
43615             });
43616
43617             items.push(
43618                 fontSelectItem,
43619                 '-'
43620             );
43621         }
43622
43623         if(this.enableFormat){
43624             items.push(
43625                 btn('bold'),
43626                 btn('italic'),
43627                 btn('underline')
43628             );
43629         }
43630
43631         if(this.enableFontSize){
43632             items.push(
43633                 '-',
43634                 btn('increasefontsize', false, this.adjustFont),
43635                 btn('decreasefontsize', false, this.adjustFont)
43636             );
43637         }
43638
43639         if(this.enableColors){
43640             items.push(
43641                 '-', {
43642                     itemId:'forecolor',
43643                     cls:'x-btn-icon',
43644                     iconCls: 'x-edit-forecolor',
43645                     clickEvent:'mousedown',
43646                     tooltip: tipsEnabled ? editor.buttonTips.forecolor || undefined : undefined,
43647                     tabIndex:-1,
43648                     menu : new Ext.menu.ColorMenu({
43649                         allowReselect: true,
43650                         focus: Ext.emptyFn,
43651                         value:'000000',
43652                         plain:true,
43653                         listeners: {
43654                             scope: this,
43655                             select: function(cp, color){
43656                                 this.execCmd('forecolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
43657                                 this.deferFocus();
43658                             }
43659                         },
43660                         clickEvent:'mousedown'
43661                     })
43662                 }, {
43663                     itemId:'backcolor',
43664                     cls:'x-btn-icon',
43665                     iconCls: 'x-edit-backcolor',
43666                     clickEvent:'mousedown',
43667                     tooltip: tipsEnabled ? editor.buttonTips.backcolor || undefined : undefined,
43668                     tabIndex:-1,
43669                     menu : new Ext.menu.ColorMenu({
43670                         focus: Ext.emptyFn,
43671                         value:'FFFFFF',
43672                         plain:true,
43673                         allowReselect: true,
43674                         listeners: {
43675                             scope: this,
43676                             select: function(cp, color){
43677                                 if(Ext.isGecko){
43678                                     this.execCmd('useCSS', false);
43679                                     this.execCmd('hilitecolor', color);
43680                                     this.execCmd('useCSS', true);
43681                                     this.deferFocus();
43682                                 }else{
43683                                     this.execCmd(Ext.isOpera ? 'hilitecolor' : 'backcolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
43684                                     this.deferFocus();
43685                                 }
43686                             }
43687                         },
43688                         clickEvent:'mousedown'
43689                     })
43690                 }
43691             );
43692         }
43693
43694         if(this.enableAlignments){
43695             items.push(
43696                 '-',
43697                 btn('justifyleft'),
43698                 btn('justifycenter'),
43699                 btn('justifyright')
43700             );
43701         }
43702
43703         if(!Ext.isSafari2){
43704             if(this.enableLinks){
43705                 items.push(
43706                     '-',
43707                     btn('createlink', false, this.createLink)
43708                 );
43709             }
43710
43711             if(this.enableLists){
43712                 items.push(
43713                     '-',
43714                     btn('insertorderedlist'),
43715                     btn('insertunorderedlist')
43716                 );
43717             }
43718             if(this.enableSourceEdit){
43719                 items.push(
43720                     '-',
43721                     btn('sourceedit', true, function(btn){
43722                         this.toggleSourceEdit(!this.sourceEditMode);
43723                     })
43724                 );
43725             }
43726         }
43727
43728         
43729         var tb = new Ext.Toolbar({
43730             renderTo: this.wrap.dom.firstChild,
43731             items: items
43732         });
43733
43734         if (fontSelectItem) {
43735             this.fontSelect = fontSelectItem.el;
43736
43737             this.mon(this.fontSelect, 'change', function(){
43738                 var font = this.fontSelect.dom.value;
43739                 this.relayCmd('fontname', font);
43740                 this.deferFocus();
43741             }, this);
43742         }
43743
43744         
43745         this.mon(tb.el, 'click', function(e){
43746             e.preventDefault();
43747         });
43748
43749         this.tb = tb;
43750         this.tb.doLayout();
43751     },
43752
43753     onDisable: function(){
43754         this.wrap.mask();
43755         Ext.form.HtmlEditor.superclass.onDisable.call(this);
43756     },
43757
43758     onEnable: function(){
43759         this.wrap.unmask();
43760         Ext.form.HtmlEditor.superclass.onEnable.call(this);
43761     },
43762
43763     setReadOnly: function(readOnly){
43764
43765         Ext.form.HtmlEditor.superclass.setReadOnly.call(this, readOnly);
43766         if(this.initialized){
43767             if(Ext.isIE){
43768                 this.getEditorBody().contentEditable = !readOnly;
43769             }else{
43770                 this.setDesignMode(!readOnly);
43771             }
43772             var bd = this.getEditorBody();
43773             if(bd){
43774                 bd.style.cursor = this.readOnly ? 'default' : 'text';
43775             }
43776             this.disableItems(readOnly);
43777         }
43778     },
43779
43780     
43781     getDocMarkup : function(){
43782         var h = Ext.fly(this.iframe).getHeight() - this.iframePad * 2;
43783         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);
43784     },
43785
43786     
43787     getEditorBody : function(){
43788         var doc = this.getDoc();
43789         return doc.body || doc.documentElement;
43790     },
43791
43792     
43793     getDoc : function(){
43794         return Ext.isIE ? this.getWin().document : (this.iframe.contentDocument || this.getWin().document);
43795     },
43796
43797     
43798     getWin : function(){
43799         return Ext.isIE ? this.iframe.contentWindow : window.frames[this.iframe.name];
43800     },
43801
43802     
43803     onRender : function(ct, position){
43804         Ext.form.HtmlEditor.superclass.onRender.call(this, ct, position);
43805         this.el.dom.style.border = '0 none';
43806         this.el.dom.setAttribute('tabIndex', -1);
43807         this.el.addClass('x-hidden');
43808         if(Ext.isIE){ 
43809             this.el.applyStyles('margin-top:-1px;margin-bottom:-1px;');
43810         }
43811         this.wrap = this.el.wrap({
43812             cls:'x-html-editor-wrap', cn:{cls:'x-html-editor-tb'}
43813         });
43814
43815         this.createToolbar(this);
43816
43817         this.disableItems(true);
43818
43819         this.tb.doLayout();
43820
43821         this.createIFrame();
43822
43823         if(!this.width){
43824             var sz = this.el.getSize();
43825             this.setSize(sz.width, this.height || sz.height);
43826         }
43827         this.resizeEl = this.positionEl = this.wrap;
43828     },
43829
43830     createIFrame: function(){
43831         var iframe = document.createElement('iframe');
43832         iframe.name = Ext.id();
43833         iframe.frameBorder = '0';
43834         iframe.style.overflow = 'auto';
43835         iframe.src = Ext.SSL_SECURE_URL;
43836
43837         this.wrap.dom.appendChild(iframe);
43838         this.iframe = iframe;
43839
43840         this.monitorTask = Ext.TaskMgr.start({
43841             run: this.checkDesignMode,
43842             scope: this,
43843             interval:100
43844         });
43845     },
43846
43847     initFrame : function(){
43848         Ext.TaskMgr.stop(this.monitorTask);
43849         var doc = this.getDoc();
43850         this.win = this.getWin();
43851
43852         doc.open();
43853         doc.write(this.getDocMarkup());
43854         doc.close();
43855
43856         var task = { 
43857             run : function(){
43858                 var doc = this.getDoc();
43859                 if(doc.body || doc.readyState == 'complete'){
43860                     Ext.TaskMgr.stop(task);
43861                     this.setDesignMode(true);
43862                     this.initEditor.defer(10, this);
43863                 }
43864             },
43865             interval : 10,
43866             duration:10000,
43867             scope: this
43868         };
43869         Ext.TaskMgr.start(task);
43870     },
43871
43872
43873     checkDesignMode : function(){
43874         if(this.wrap && this.wrap.dom.offsetWidth){
43875             var doc = this.getDoc();
43876             if(!doc){
43877                 return;
43878             }
43879             if(!doc.editorInitialized || this.getDesignMode() != 'on'){
43880                 this.initFrame();
43881             }
43882         }
43883     },
43884
43885     
43886     setDesignMode : function(mode){
43887         var doc = this.getDoc();
43888         if (doc) {
43889             if(this.readOnly){
43890                 mode = false;
43891             }
43892             doc.designMode = (/on|true/i).test(String(mode).toLowerCase()) ?'on':'off';
43893         }
43894
43895     },
43896
43897     
43898     getDesignMode : function(){
43899         var doc = this.getDoc();
43900         if(!doc){ return ''; }
43901         return String(doc.designMode).toLowerCase();
43902
43903     },
43904
43905     disableItems: function(disabled){
43906         if(this.fontSelect){
43907             this.fontSelect.dom.disabled = disabled;
43908         }
43909         this.tb.items.each(function(item){
43910             if(item.getItemId() != 'sourceedit'){
43911                 item.setDisabled(disabled);
43912             }
43913         });
43914     },
43915
43916     
43917     onResize : function(w, h){
43918         Ext.form.HtmlEditor.superclass.onResize.apply(this, arguments);
43919         if(this.el && this.iframe){
43920             if(Ext.isNumber(w)){
43921                 var aw = w - this.wrap.getFrameWidth('lr');
43922                 this.el.setWidth(aw);
43923                 this.tb.setWidth(aw);
43924                 this.iframe.style.width = Math.max(aw, 0) + 'px';
43925             }
43926             if(Ext.isNumber(h)){
43927                 var ah = h - this.wrap.getFrameWidth('tb') - this.tb.el.getHeight();
43928                 this.el.setHeight(ah);
43929                 this.iframe.style.height = Math.max(ah, 0) + 'px';
43930                 var bd = this.getEditorBody();
43931                 if(bd){
43932                     bd.style.height = Math.max((ah - (this.iframePad*2)), 0) + 'px';
43933                 }
43934             }
43935         }
43936     },
43937
43938     
43939     toggleSourceEdit : function(sourceEditMode){
43940         var iframeHeight,
43941             elHeight;
43942
43943         if (sourceEditMode === undefined) {
43944             sourceEditMode = !this.sourceEditMode;
43945         }
43946         this.sourceEditMode = sourceEditMode === true;
43947         var btn = this.tb.getComponent('sourceedit');
43948
43949         if (btn.pressed !== this.sourceEditMode) {
43950             btn.toggle(this.sourceEditMode);
43951             if (!btn.xtbHidden) {
43952                 return;
43953             }
43954         }
43955         if (this.sourceEditMode) {
43956             
43957             this.previousSize = this.getSize();
43958
43959             iframeHeight = Ext.get(this.iframe).getHeight();
43960
43961             this.disableItems(true);
43962             this.syncValue();
43963             this.iframe.className = 'x-hidden';
43964             this.el.removeClass('x-hidden');
43965             this.el.dom.removeAttribute('tabIndex');
43966             this.el.focus();
43967             this.el.dom.style.height = iframeHeight + 'px';
43968         }
43969         else {
43970             elHeight = parseInt(this.el.dom.style.height, 10);
43971             if (this.initialized) {
43972                 this.disableItems(this.readOnly);
43973             }
43974             this.pushValue();
43975             this.iframe.className = '';
43976             this.el.addClass('x-hidden');
43977             this.el.dom.setAttribute('tabIndex', -1);
43978             this.deferFocus();
43979
43980             this.setSize(this.previousSize);
43981             delete this.previousSize;
43982             this.iframe.style.height = elHeight + 'px';
43983         }
43984         this.fireEvent('editmodechange', this, this.sourceEditMode);
43985     },
43986
43987     
43988     createLink : function() {
43989         var url = prompt(this.createLinkText, this.defaultLinkValue);
43990         if(url && url != 'http:/'+'/'){
43991             this.relayCmd('createlink', url);
43992         }
43993     },
43994
43995     
43996     initEvents : function(){
43997         this.originalValue = this.getValue();
43998     },
43999
44000     
44001     markInvalid : Ext.emptyFn,
44002
44003     
44004     clearInvalid : Ext.emptyFn,
44005
44006     
44007     setValue : function(v){
44008         Ext.form.HtmlEditor.superclass.setValue.call(this, v);
44009         this.pushValue();
44010         return this;
44011     },
44012
44013     
44014     cleanHtml: function(html) {
44015         html = String(html);
44016         if(Ext.isWebKit){ 
44017             html = html.replace(/\sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi, '');
44018         }
44019
44020         
44021         if(html.charCodeAt(0) == this.defaultValue.replace(/\D/g, '')){
44022             html = html.substring(1);
44023         }
44024         return html;
44025     },
44026
44027     
44028     syncValue : function(){
44029         if(this.initialized){
44030             var bd = this.getEditorBody();
44031             var html = bd.innerHTML;
44032             if(Ext.isWebKit){
44033                 var bs = bd.getAttribute('style'); 
44034                 var m = bs.match(/text-align:(.*?);/i);
44035                 if(m && m[1]){
44036                     html = '<div style="'+m[0]+'">' + html + '</div>';
44037                 }
44038             }
44039             html = this.cleanHtml(html);
44040             if(this.fireEvent('beforesync', this, html) !== false){
44041                 this.el.dom.value = html;
44042                 this.fireEvent('sync', this, html);
44043             }
44044         }
44045     },
44046
44047     
44048     getValue : function() {
44049         this[this.sourceEditMode ? 'pushValue' : 'syncValue']();
44050         return Ext.form.HtmlEditor.superclass.getValue.call(this);
44051     },
44052
44053     
44054     pushValue : function(){
44055         if(this.initialized){
44056             var v = this.el.dom.value;
44057             if(!this.activated && v.length < 1){
44058                 v = this.defaultValue;
44059             }
44060             if(this.fireEvent('beforepush', this, v) !== false){
44061                 this.getEditorBody().innerHTML = v;
44062                 if(Ext.isGecko){
44063                     
44064                     this.setDesignMode(false);  
44065                     this.setDesignMode(true);
44066                 }
44067                 this.fireEvent('push', this, v);
44068             }
44069
44070         }
44071     },
44072
44073     
44074     deferFocus : function(){
44075         this.focus.defer(10, this);
44076     },
44077
44078     
44079     focus : function(){
44080         if(this.win && !this.sourceEditMode){
44081             this.win.focus();
44082         }else{
44083             this.el.focus();
44084         }
44085     },
44086
44087     
44088     initEditor : function(){
44089         
44090         try{
44091             var dbody = this.getEditorBody(),
44092                 ss = this.el.getStyles('font-size', 'font-family', 'background-image', 'background-repeat', 'background-color', 'color'),
44093                 doc,
44094                 fn;
44095
44096             ss['background-attachment'] = 'fixed'; 
44097             dbody.bgProperties = 'fixed'; 
44098
44099             Ext.DomHelper.applyStyles(dbody, ss);
44100
44101             doc = this.getDoc();
44102
44103             if(doc){
44104                 try{
44105                     Ext.EventManager.removeAll(doc);
44106                 }catch(e){}
44107             }
44108
44109             
44110             fn = this.onEditorEvent.createDelegate(this);
44111             Ext.EventManager.on(doc, {
44112                 mousedown: fn,
44113                 dblclick: fn,
44114                 click: fn,
44115                 keyup: fn,
44116                 buffer:100
44117             });
44118
44119             if(Ext.isGecko){
44120                 Ext.EventManager.on(doc, 'keypress', this.applyCommand, this);
44121             }
44122             if(Ext.isIE || Ext.isWebKit || Ext.isOpera){
44123                 Ext.EventManager.on(doc, 'keydown', this.fixKeys, this);
44124             }
44125             doc.editorInitialized = true;
44126             this.initialized = true;
44127             this.pushValue();
44128             this.setReadOnly(this.readOnly);
44129             this.fireEvent('initialize', this);
44130         }catch(e){}
44131     },
44132
44133     
44134     beforeDestroy : function(){
44135         if(this.monitorTask){
44136             Ext.TaskMgr.stop(this.monitorTask);
44137         }
44138         if(this.rendered){
44139             Ext.destroy(this.tb);
44140             var doc = this.getDoc();
44141             if(doc){
44142                 try{
44143                     Ext.EventManager.removeAll(doc);
44144                     for (var prop in doc){
44145                         delete doc[prop];
44146                     }
44147                 }catch(e){}
44148             }
44149             if(this.wrap){
44150                 this.wrap.dom.innerHTML = '';
44151                 this.wrap.remove();
44152             }
44153         }
44154         Ext.form.HtmlEditor.superclass.beforeDestroy.call(this);
44155     },
44156
44157     
44158     onFirstFocus : function(){
44159         this.activated = true;
44160         this.disableItems(this.readOnly);
44161         if(Ext.isGecko){ 
44162             this.win.focus();
44163             var s = this.win.getSelection();
44164             if(!s.focusNode || s.focusNode.nodeType != 3){
44165                 var r = s.getRangeAt(0);
44166                 r.selectNodeContents(this.getEditorBody());
44167                 r.collapse(true);
44168                 this.deferFocus();
44169             }
44170             try{
44171                 this.execCmd('useCSS', true);
44172                 this.execCmd('styleWithCSS', false);
44173             }catch(e){}
44174         }
44175         this.fireEvent('activate', this);
44176     },
44177
44178     
44179     adjustFont: function(btn){
44180         var adjust = btn.getItemId() == 'increasefontsize' ? 1 : -1,
44181             doc = this.getDoc(),
44182             v = parseInt(doc.queryCommandValue('FontSize') || 2, 10);
44183         if((Ext.isSafari && !Ext.isSafari2) || Ext.isChrome || Ext.isAir){
44184             
44185             
44186             if(v <= 10){
44187                 v = 1 + adjust;
44188             }else if(v <= 13){
44189                 v = 2 + adjust;
44190             }else if(v <= 16){
44191                 v = 3 + adjust;
44192             }else if(v <= 18){
44193                 v = 4 + adjust;
44194             }else if(v <= 24){
44195                 v = 5 + adjust;
44196             }else {
44197                 v = 6 + adjust;
44198             }
44199             v = v.constrain(1, 6);
44200         }else{
44201             if(Ext.isSafari){ 
44202                 adjust *= 2;
44203             }
44204             v = Math.max(1, v+adjust) + (Ext.isSafari ? 'px' : 0);
44205         }
44206         this.execCmd('FontSize', v);
44207     },
44208
44209     
44210     onEditorEvent : function(e){
44211         this.updateToolbar();
44212     },
44213
44214
44215     
44216     updateToolbar: function(){
44217
44218         if(this.readOnly){
44219             return;
44220         }
44221
44222         if(!this.activated){
44223             this.onFirstFocus();
44224             return;
44225         }
44226
44227         var btns = this.tb.items.map,
44228             doc = this.getDoc();
44229
44230         if(this.enableFont && !Ext.isSafari2){
44231             var name = (doc.queryCommandValue('FontName')||this.defaultFont).toLowerCase();
44232             if(name != this.fontSelect.dom.value){
44233                 this.fontSelect.dom.value = name;
44234             }
44235         }
44236         if(this.enableFormat){
44237             btns.bold.toggle(doc.queryCommandState('bold'));
44238             btns.italic.toggle(doc.queryCommandState('italic'));
44239             btns.underline.toggle(doc.queryCommandState('underline'));
44240         }
44241         if(this.enableAlignments){
44242             btns.justifyleft.toggle(doc.queryCommandState('justifyleft'));
44243             btns.justifycenter.toggle(doc.queryCommandState('justifycenter'));
44244             btns.justifyright.toggle(doc.queryCommandState('justifyright'));
44245         }
44246         if(!Ext.isSafari2 && this.enableLists){
44247             btns.insertorderedlist.toggle(doc.queryCommandState('insertorderedlist'));
44248             btns.insertunorderedlist.toggle(doc.queryCommandState('insertunorderedlist'));
44249         }
44250
44251         Ext.menu.MenuMgr.hideAll();
44252
44253         this.syncValue();
44254     },
44255
44256     
44257     relayBtnCmd : function(btn){
44258         this.relayCmd(btn.getItemId());
44259     },
44260
44261     
44262     relayCmd : function(cmd, value){
44263         (function(){
44264             this.focus();
44265             this.execCmd(cmd, value);
44266             this.updateToolbar();
44267         }).defer(10, this);
44268     },
44269
44270     
44271     execCmd : function(cmd, value){
44272         var doc = this.getDoc();
44273         doc.execCommand(cmd, false, value === undefined ? null : value);
44274         this.syncValue();
44275     },
44276
44277     
44278     applyCommand : function(e){
44279         if(e.ctrlKey){
44280             var c = e.getCharCode(), cmd;
44281             if(c > 0){
44282                 c = String.fromCharCode(c);
44283                 switch(c){
44284                     case 'b':
44285                         cmd = 'bold';
44286                     break;
44287                     case 'i':
44288                         cmd = 'italic';
44289                     break;
44290                     case 'u':
44291                         cmd = 'underline';
44292                     break;
44293                 }
44294                 if(cmd){
44295                     this.win.focus();
44296                     this.execCmd(cmd);
44297                     this.deferFocus();
44298                     e.preventDefault();
44299                 }
44300             }
44301         }
44302     },
44303
44304     
44305     insertAtCursor : function(text){
44306         if(!this.activated){
44307             return;
44308         }
44309         if(Ext.isIE){
44310             this.win.focus();
44311             var doc = this.getDoc(),
44312                 r = doc.selection.createRange();
44313             if(r){
44314                 r.pasteHTML(text);
44315                 this.syncValue();
44316                 this.deferFocus();
44317             }
44318         }else{
44319             this.win.focus();
44320             this.execCmd('InsertHTML', text);
44321             this.deferFocus();
44322         }
44323     },
44324
44325     
44326     fixKeys : function(){ 
44327         if(Ext.isIE){
44328             return function(e){
44329                 var k = e.getKey(),
44330                     doc = this.getDoc(),
44331                         r;
44332                 if(k == e.TAB){
44333                     e.stopEvent();
44334                     r = doc.selection.createRange();
44335                     if(r){
44336                         r.collapse(true);
44337                         r.pasteHTML('&nbsp;&nbsp;&nbsp;&nbsp;');
44338                         this.deferFocus();
44339                     }
44340                 }else if(k == e.ENTER){
44341                     r = doc.selection.createRange();
44342                     if(r){
44343                         var target = r.parentElement();
44344                         if(!target || target.tagName.toLowerCase() != 'li'){
44345                             e.stopEvent();
44346                             r.pasteHTML('<br />');
44347                             r.collapse(false);
44348                             r.select();
44349                         }
44350                     }
44351                 }
44352             };
44353         }else if(Ext.isOpera){
44354             return function(e){
44355                 var k = e.getKey();
44356                 if(k == e.TAB){
44357                     e.stopEvent();
44358                     this.win.focus();
44359                     this.execCmd('InsertHTML','&nbsp;&nbsp;&nbsp;&nbsp;');
44360                     this.deferFocus();
44361                 }
44362             };
44363         }else if(Ext.isWebKit){
44364             return function(e){
44365                 var k = e.getKey();
44366                 if(k == e.TAB){
44367                     e.stopEvent();
44368                     this.execCmd('InsertText','\t');
44369                     this.deferFocus();
44370                 }else if(k == e.ENTER){
44371                     e.stopEvent();
44372                     this.execCmd('InsertHtml','<br /><br />');
44373                     this.deferFocus();
44374                 }
44375              };
44376         }
44377     }(),
44378
44379     
44380     getToolbar : function(){
44381         return this.tb;
44382     },
44383
44384     
44385     buttonTips : {
44386         bold : {
44387             title: 'Bold (Ctrl+B)',
44388             text: 'Make the selected text bold.',
44389             cls: 'x-html-editor-tip'
44390         },
44391         italic : {
44392             title: 'Italic (Ctrl+I)',
44393             text: 'Make the selected text italic.',
44394             cls: 'x-html-editor-tip'
44395         },
44396         underline : {
44397             title: 'Underline (Ctrl+U)',
44398             text: 'Underline the selected text.',
44399             cls: 'x-html-editor-tip'
44400         },
44401         increasefontsize : {
44402             title: 'Grow Text',
44403             text: 'Increase the font size.',
44404             cls: 'x-html-editor-tip'
44405         },
44406         decreasefontsize : {
44407             title: 'Shrink Text',
44408             text: 'Decrease the font size.',
44409             cls: 'x-html-editor-tip'
44410         },
44411         backcolor : {
44412             title: 'Text Highlight Color',
44413             text: 'Change the background color of the selected text.',
44414             cls: 'x-html-editor-tip'
44415         },
44416         forecolor : {
44417             title: 'Font Color',
44418             text: 'Change the color of the selected text.',
44419             cls: 'x-html-editor-tip'
44420         },
44421         justifyleft : {
44422             title: 'Align Text Left',
44423             text: 'Align text to the left.',
44424             cls: 'x-html-editor-tip'
44425         },
44426         justifycenter : {
44427             title: 'Center Text',
44428             text: 'Center text in the editor.',
44429             cls: 'x-html-editor-tip'
44430         },
44431         justifyright : {
44432             title: 'Align Text Right',
44433             text: 'Align text to the right.',
44434             cls: 'x-html-editor-tip'
44435         },
44436         insertunorderedlist : {
44437             title: 'Bullet List',
44438             text: 'Start a bulleted list.',
44439             cls: 'x-html-editor-tip'
44440         },
44441         insertorderedlist : {
44442             title: 'Numbered List',
44443             text: 'Start a numbered list.',
44444             cls: 'x-html-editor-tip'
44445         },
44446         createlink : {
44447             title: 'Hyperlink',
44448             text: 'Make the selected text a hyperlink.',
44449             cls: 'x-html-editor-tip'
44450         },
44451         sourceedit : {
44452             title: 'Source Edit',
44453             text: 'Switch to source editing mode.',
44454             cls: 'x-html-editor-tip'
44455         }
44456     }
44457
44458     
44459     
44460     
44461     
44462     
44463     
44464     
44465     
44466     
44467     
44468     
44469     
44470     
44471     
44472     
44473     
44474     
44475     
44476     
44477     
44478     
44479     
44480     
44481     
44482     
44483     
44484     
44485     
44486     
44487     
44488     
44489     
44490     
44491     
44492 });
44493 Ext.reg('htmleditor', Ext.form.HtmlEditor);
44494
44495 Ext.form.TimeField = Ext.extend(Ext.form.ComboBox, {
44496     
44497     minValue : undefined,
44498     
44499     maxValue : undefined,
44500     
44501     minText : "The time in this field must be equal to or after {0}",
44502     
44503     maxText : "The time in this field must be equal to or before {0}",
44504     
44505     invalidText : "{0} is not a valid time",
44506     
44507     format : "g:i A",
44508     
44509     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",
44510     
44511     increment: 15,
44512
44513     
44514     mode: 'local',
44515     
44516     triggerAction: 'all',
44517     
44518     typeAhead: false,
44519
44520     
44521     
44522     
44523     initDate: '1/1/2008',
44524
44525     initDateFormat: 'j/n/Y',
44526
44527     
44528     initComponent : function(){
44529         if(Ext.isDefined(this.minValue)){
44530             this.setMinValue(this.minValue, true);
44531         }
44532         if(Ext.isDefined(this.maxValue)){
44533             this.setMaxValue(this.maxValue, true);
44534         }
44535         if(!this.store){
44536             this.generateStore(true);
44537         }
44538         Ext.form.TimeField.superclass.initComponent.call(this);
44539     },
44540
44541     
44542     setMinValue: function(value,  initial){
44543         this.setLimit(value, true, initial);
44544         return this;
44545     },
44546
44547     
44548     setMaxValue: function(value,  initial){
44549         this.setLimit(value, false, initial);
44550         return this;
44551     },
44552
44553     
44554     generateStore: function(initial){
44555         var min = this.minValue || new Date(this.initDate).clearTime(),
44556             max = this.maxValue || new Date(this.initDate).clearTime().add('mi', (24 * 60) - 1),
44557             times = [];
44558
44559         while(min <= max){
44560             times.push(min.dateFormat(this.format));
44561             min = min.add('mi', this.increment);
44562         }
44563         this.bindStore(times, initial);
44564     },
44565
44566     
44567     setLimit: function(value, isMin, initial){
44568         var d;
44569         if(Ext.isString(value)){
44570             d = this.parseDate(value);
44571         }else if(Ext.isDate(value)){
44572             d = value;
44573         }
44574         if(d){
44575             var val = new Date(this.initDate).clearTime();
44576             val.setHours(d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds());
44577             this[isMin ? 'minValue' : 'maxValue'] = val;
44578             if(!initial){
44579                 this.generateStore();
44580             }
44581         }
44582     },
44583
44584     
44585     getValue : function(){
44586         var v = Ext.form.TimeField.superclass.getValue.call(this);
44587         return this.formatDate(this.parseDate(v)) || '';
44588     },
44589
44590     
44591     setValue : function(value){
44592         return Ext.form.TimeField.superclass.setValue.call(this, this.formatDate(this.parseDate(value)));
44593     },
44594
44595     
44596     validateValue : Ext.form.DateField.prototype.validateValue,
44597
44598     formatDate : Ext.form.DateField.prototype.formatDate,
44599
44600     parseDate: function(value) {
44601         if (!value || Ext.isDate(value)) {
44602             return value;
44603         }
44604
44605         var id = this.initDate + ' ',
44606             idf = this.initDateFormat + ' ',
44607             v = Date.parseDate(id + value, idf + this.format), 
44608             af = this.altFormats;
44609
44610         if (!v && af) {
44611             if (!this.altFormatsArray) {
44612                 this.altFormatsArray = af.split("|");
44613             }
44614             for (var i = 0, afa = this.altFormatsArray, len = afa.length; i < len && !v; i++) {
44615                 v = Date.parseDate(id + value, idf + afa[i]);
44616             }
44617         }
44618
44619         return v;
44620     }
44621 });
44622 Ext.reg('timefield', Ext.form.TimeField);
44623 Ext.form.SliderField = Ext.extend(Ext.form.Field, {
44624     
44625     
44626     useTips : true,
44627     
44628     
44629     tipText : null,
44630     
44631     
44632     actionMode: 'wrap',
44633     
44634     
44635     initComponent : function() {
44636         var cfg = Ext.copyTo({
44637             id: this.id + '-slider'
44638         }, this.initialConfig, ['vertical', 'minValue', 'maxValue', 'decimalPrecision', 'keyIncrement', 'increment', 'clickToChange', 'animate']);
44639         
44640         
44641         if (this.useTips) {
44642             var plug = this.tipText ? {getText: this.tipText} : {};
44643             cfg.plugins = [new Ext.slider.Tip(plug)];
44644         }
44645         this.slider = new Ext.Slider(cfg);
44646         Ext.form.SliderField.superclass.initComponent.call(this);
44647     },    
44648     
44649     
44650     onRender : function(ct, position){
44651         this.autoCreate = {
44652             id: this.id,
44653             name: this.name,
44654             type: 'hidden',
44655             tag: 'input'    
44656         };
44657         Ext.form.SliderField.superclass.onRender.call(this, ct, position);
44658         this.wrap = this.el.wrap({cls: 'x-form-field-wrap'});
44659         this.resizeEl = this.positionEl = this.wrap;
44660         this.slider.render(this.wrap);
44661     },
44662     
44663     
44664     onResize : function(w, h, aw, ah){
44665         Ext.form.SliderField.superclass.onResize.call(this, w, h, aw, ah);
44666         this.slider.setSize(w, h);    
44667     },
44668     
44669     
44670     initEvents : function(){
44671         Ext.form.SliderField.superclass.initEvents.call(this);
44672         this.slider.on('change', this.onChange, this);   
44673     },
44674     
44675     
44676     onChange : function(slider, v){
44677         this.setValue(v, undefined, true);
44678     },
44679     
44680     
44681     onEnable : function(){
44682         Ext.form.SliderField.superclass.onEnable.call(this);
44683         this.slider.enable();
44684     },
44685     
44686     
44687     onDisable : function(){
44688         Ext.form.SliderField.superclass.onDisable.call(this);
44689         this.slider.disable();    
44690     },
44691     
44692     
44693     beforeDestroy : function(){
44694         Ext.destroy(this.slider);
44695         Ext.form.SliderField.superclass.beforeDestroy.call(this);
44696     },
44697     
44698     
44699     alignErrorIcon : function(){
44700         this.errorIcon.alignTo(this.slider.el, 'tl-tr', [2, 0]);
44701     },
44702     
44703     
44704     setMinValue : function(v){
44705         this.slider.setMinValue(v);
44706         return this;    
44707     },
44708     
44709     
44710     setMaxValue : function(v){
44711         this.slider.setMaxValue(v);
44712         return this;    
44713     },
44714     
44715     
44716     setValue : function(v, animate,  silent){
44717         
44718         
44719         if(!silent){
44720             this.slider.setValue(v, animate);
44721         }
44722         return Ext.form.SliderField.superclass.setValue.call(this, this.slider.getValue());
44723     },
44724     
44725     
44726     getValue : function(){
44727         return this.slider.getValue();    
44728     }
44729 });
44730
44731 Ext.reg('sliderfield', Ext.form.SliderField);
44732 Ext.form.Label = Ext.extend(Ext.BoxComponent, {
44733     
44734     
44735     
44736
44737     
44738     onRender : function(ct, position){
44739         if(!this.el){
44740             this.el = document.createElement('label');
44741             this.el.id = this.getId();
44742             this.el.innerHTML = this.text ? Ext.util.Format.htmlEncode(this.text) : (this.html || '');
44743             if(this.forId){
44744                 this.el.setAttribute('for', this.forId);
44745             }
44746         }
44747         Ext.form.Label.superclass.onRender.call(this, ct, position);
44748     },
44749
44750     
44751     setText : function(t, encode){
44752         var e = encode === false;
44753         this[!e ? 'text' : 'html'] = t;
44754         delete this[e ? 'text' : 'html'];
44755         if(this.rendered){
44756             this.el.dom.innerHTML = encode !== false ? Ext.util.Format.htmlEncode(t) : t;
44757         }
44758         return this;
44759     }
44760 });
44761
44762 Ext.reg('label', Ext.form.Label);
44763 Ext.form.Action = function(form, options){
44764     this.form = form;
44765     this.options = options || {};
44766 };
44767
44768
44769 Ext.form.Action.CLIENT_INVALID = 'client';
44770
44771 Ext.form.Action.SERVER_INVALID = 'server';
44772
44773 Ext.form.Action.CONNECT_FAILURE = 'connect';
44774
44775 Ext.form.Action.LOAD_FAILURE = 'load';
44776
44777 Ext.form.Action.prototype = {
44778
44779
44780
44781
44782
44783
44784
44785
44786
44787
44788
44789
44790
44791
44792     type : 'default',
44793
44794  
44795  
44796
44797     
44798     run : function(options){
44799
44800     },
44801
44802     
44803     success : function(response){
44804
44805     },
44806
44807     
44808     handleResponse : function(response){
44809
44810     },
44811
44812     
44813     failure : function(response){
44814         this.response = response;
44815         this.failureType = Ext.form.Action.CONNECT_FAILURE;
44816         this.form.afterAction(this, false);
44817     },
44818
44819     
44820     
44821     
44822     processResponse : function(response){
44823         this.response = response;
44824         if(!response.responseText && !response.responseXML){
44825             return true;
44826         }
44827         this.result = this.handleResponse(response);
44828         return this.result;
44829     },
44830
44831     
44832     getUrl : function(appendParams){
44833         var url = this.options.url || this.form.url || this.form.el.dom.action;
44834         if(appendParams){
44835             var p = this.getParams();
44836             if(p){
44837                 url = Ext.urlAppend(url, p);
44838             }
44839         }
44840         return url;
44841     },
44842
44843     
44844     getMethod : function(){
44845         return (this.options.method || this.form.method || this.form.el.dom.method || 'POST').toUpperCase();
44846     },
44847
44848     
44849     getParams : function(){
44850         var bp = this.form.baseParams;
44851         var p = this.options.params;
44852         if(p){
44853             if(typeof p == "object"){
44854                 p = Ext.urlEncode(Ext.applyIf(p, bp));
44855             }else if(typeof p == 'string' && bp){
44856                 p += '&' + Ext.urlEncode(bp);
44857             }
44858         }else if(bp){
44859             p = Ext.urlEncode(bp);
44860         }
44861         return p;
44862     },
44863
44864     
44865     createCallback : function(opts){
44866         var opts = opts || {};
44867         return {
44868             success: this.success,
44869             failure: this.failure,
44870             scope: this,
44871             timeout: (opts.timeout*1000) || (this.form.timeout*1000),
44872             upload: this.form.fileUpload ? this.success : undefined
44873         };
44874     }
44875 };
44876
44877
44878 Ext.form.Action.Submit = function(form, options){
44879     Ext.form.Action.Submit.superclass.constructor.call(this, form, options);
44880 };
44881
44882 Ext.extend(Ext.form.Action.Submit, Ext.form.Action, {
44883     
44884     
44885     type : 'submit',
44886
44887     
44888     run : function(){
44889         var o = this.options,
44890             method = this.getMethod(),
44891             isGet = method == 'GET';
44892         if(o.clientValidation === false || this.form.isValid()){
44893             if (o.submitEmptyText === false) {
44894                 var fields = this.form.items,
44895                     emptyFields = [],
44896                     setupEmptyFields = function(f){
44897                         if (f.el.getValue() == f.emptyText) {
44898                             emptyFields.push(f);
44899                             f.el.dom.value = "";
44900                         }
44901                         if(f.isComposite && f.rendered){
44902                             f.items.each(setupEmptyFields);
44903                         }
44904                     };
44905                     
44906                 fields.each(setupEmptyFields);
44907             }
44908             Ext.Ajax.request(Ext.apply(this.createCallback(o), {
44909                 form:this.form.el.dom,
44910                 url:this.getUrl(isGet),
44911                 method: method,
44912                 headers: o.headers,
44913                 params:!isGet ? this.getParams() : null,
44914                 isUpload: this.form.fileUpload
44915             }));
44916             if (o.submitEmptyText === false) {
44917                 Ext.each(emptyFields, function(f) {
44918                     if (f.applyEmptyText) {
44919                         f.applyEmptyText();
44920                     }
44921                 });
44922             }
44923         }else if (o.clientValidation !== false){ 
44924             this.failureType = Ext.form.Action.CLIENT_INVALID;
44925             this.form.afterAction(this, false);
44926         }
44927     },
44928
44929     
44930     success : function(response){
44931         var result = this.processResponse(response);
44932         if(result === true || result.success){
44933             this.form.afterAction(this, true);
44934             return;
44935         }
44936         if(result.errors){
44937             this.form.markInvalid(result.errors);
44938         }
44939         this.failureType = Ext.form.Action.SERVER_INVALID;
44940         this.form.afterAction(this, false);
44941     },
44942
44943     
44944     handleResponse : function(response){
44945         if(this.form.errorReader){
44946             var rs = this.form.errorReader.read(response);
44947             var errors = [];
44948             if(rs.records){
44949                 for(var i = 0, len = rs.records.length; i < len; i++) {
44950                     var r = rs.records[i];
44951                     errors[i] = r.data;
44952                 }
44953             }
44954             if(errors.length < 1){
44955                 errors = null;
44956             }
44957             return {
44958                 success : rs.success,
44959                 errors : errors
44960             };
44961         }
44962         return Ext.decode(response.responseText);
44963     }
44964 });
44965
44966
44967
44968 Ext.form.Action.Load = function(form, options){
44969     Ext.form.Action.Load.superclass.constructor.call(this, form, options);
44970     this.reader = this.form.reader;
44971 };
44972
44973 Ext.extend(Ext.form.Action.Load, Ext.form.Action, {
44974     
44975     type : 'load',
44976
44977     
44978     run : function(){
44979         Ext.Ajax.request(Ext.apply(
44980                 this.createCallback(this.options), {
44981                     method:this.getMethod(),
44982                     url:this.getUrl(false),
44983                     headers: this.options.headers,
44984                     params:this.getParams()
44985         }));
44986     },
44987
44988     
44989     success : function(response){
44990         var result = this.processResponse(response);
44991         if(result === true || !result.success || !result.data){
44992             this.failureType = Ext.form.Action.LOAD_FAILURE;
44993             this.form.afterAction(this, false);
44994             return;
44995         }
44996         this.form.clearInvalid();
44997         this.form.setValues(result.data);
44998         this.form.afterAction(this, true);
44999     },
45000
45001     
45002     handleResponse : function(response){
45003         if(this.form.reader){
45004             var rs = this.form.reader.read(response);
45005             var data = rs.records && rs.records[0] ? rs.records[0].data : null;
45006             return {
45007                 success : rs.success,
45008                 data : data
45009             };
45010         }
45011         return Ext.decode(response.responseText);
45012     }
45013 });
45014
45015
45016
45017
45018 Ext.form.Action.DirectLoad = Ext.extend(Ext.form.Action.Load, {
45019     constructor: function(form, opts) {
45020         Ext.form.Action.DirectLoad.superclass.constructor.call(this, form, opts);
45021     },
45022     type : 'directload',
45023
45024     run : function(){
45025         var args = this.getParams();
45026         args.push(this.success, this);
45027         this.form.api.load.apply(window, args);
45028     },
45029
45030     getParams : function() {
45031         var buf = [], o = {};
45032         var bp = this.form.baseParams;
45033         var p = this.options.params;
45034         Ext.apply(o, p, bp);
45035         var paramOrder = this.form.paramOrder;
45036         if(paramOrder){
45037             for(var i = 0, len = paramOrder.length; i < len; i++){
45038                 buf.push(o[paramOrder[i]]);
45039             }
45040         }else if(this.form.paramsAsHash){
45041             buf.push(o);
45042         }
45043         return buf;
45044     },
45045     
45046     
45047     
45048     processResponse : function(result) {
45049         this.result = result;
45050         return result;
45051     },
45052
45053     success : function(response, trans){
45054         if(trans.type == Ext.Direct.exceptions.SERVER){
45055             response = {};
45056         }
45057         Ext.form.Action.DirectLoad.superclass.success.call(this, response);
45058     }
45059 });
45060
45061
45062 Ext.form.Action.DirectSubmit = Ext.extend(Ext.form.Action.Submit, {
45063     constructor : function(form, opts) {
45064         Ext.form.Action.DirectSubmit.superclass.constructor.call(this, form, opts);
45065     },
45066     type : 'directsubmit',
45067     
45068     run : function(){
45069         var o = this.options;
45070         if(o.clientValidation === false || this.form.isValid()){
45071             
45072             
45073             this.success.params = this.getParams();
45074             this.form.api.submit(this.form.el.dom, this.success, this);
45075         }else if (o.clientValidation !== false){ 
45076             this.failureType = Ext.form.Action.CLIENT_INVALID;
45077             this.form.afterAction(this, false);
45078         }
45079     },
45080
45081     getParams : function() {
45082         var o = {};
45083         var bp = this.form.baseParams;
45084         var p = this.options.params;
45085         Ext.apply(o, p, bp);
45086         return o;
45087     },
45088     
45089     
45090     
45091     processResponse : function(result) {
45092         this.result = result;
45093         return result;
45094     },
45095
45096     success : function(response, trans){
45097         if(trans.type == Ext.Direct.exceptions.SERVER){
45098             response = {};
45099         }
45100         Ext.form.Action.DirectSubmit.superclass.success.call(this, response);
45101     }
45102 });
45103
45104 Ext.form.Action.ACTION_TYPES = {
45105     'load' : Ext.form.Action.Load,
45106     'submit' : Ext.form.Action.Submit,
45107     'directload' : Ext.form.Action.DirectLoad,
45108     'directsubmit' : Ext.form.Action.DirectSubmit
45109 };
45110
45111 Ext.form.VTypes = function(){
45112     
45113     var alpha = /^[a-zA-Z_]+$/,
45114         alphanum = /^[a-zA-Z0-9_]+$/,
45115         email = /^(\w+)([\-+.][\w]+)*@(\w[\-\w]*\.){1,5}([A-Za-z]){2,6}$/,
45116         url = /(((^https?)|(^ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
45117
45118     
45119     return {
45120         
45121         'email' : function(v){
45122             return email.test(v);
45123         },
45124         
45125         'emailText' : 'This field should be an e-mail address in the format "user@example.com"',
45126         
45127         'emailMask' : /[a-z0-9_\.\-@\+]/i,
45128
45129         
45130         'url' : function(v){
45131             return url.test(v);
45132         },
45133         
45134         'urlText' : 'This field should be a URL in the format "http:/'+'/www.example.com"',
45135
45136         
45137         'alpha' : function(v){
45138             return alpha.test(v);
45139         },
45140         
45141         'alphaText' : 'This field should only contain letters and _',
45142         
45143         'alphaMask' : /[a-z_]/i,
45144
45145         
45146         'alphanum' : function(v){
45147             return alphanum.test(v);
45148         },
45149         
45150         'alphanumText' : 'This field should only contain letters, numbers and _',
45151         
45152         'alphanumMask' : /[a-z0-9_]/i
45153     };
45154 }();
45155
45156 Ext.grid.GridPanel = Ext.extend(Ext.Panel, {
45157     
45158     autoExpandColumn : false,
45159     
45160     
45161     autoExpandMax : 1000,
45162     
45163     
45164     autoExpandMin : 50,
45165     
45166     
45167     columnLines : false,
45168     
45169     
45170     
45171     
45172     
45173     
45174     ddText : '{0} selected row{1}',
45175     
45176     
45177     deferRowRender : true,
45178     
45179     
45180     
45181     
45182     enableColumnHide : true,
45183     
45184     
45185     enableColumnMove : true,
45186     
45187     
45188     enableDragDrop : false,
45189     
45190     
45191     enableHdMenu : true,
45192     
45193     
45194     
45195     loadMask : false,
45196     
45197     
45198     
45199     minColumnWidth : 25,
45200     
45201     
45202     
45203     
45204     
45205     stripeRows : false,
45206     
45207     
45208     trackMouseOver : true,
45209     
45210     
45211     stateEvents : ['columnmove', 'columnresize', 'sortchange', 'groupchange'],
45212     
45213     
45214     view : null,
45215
45216     
45217     bubbleEvents: [],
45218
45219     
45220
45221     
45222     rendered : false,
45223     
45224     
45225     viewReady : false,
45226
45227     
45228     initComponent : function() {
45229         Ext.grid.GridPanel.superclass.initComponent.call(this);
45230
45231         if (this.columnLines) {
45232             this.cls = (this.cls || '') + ' x-grid-with-col-lines';
45233         }
45234         
45235         
45236         this.autoScroll = false;
45237         this.autoWidth = false;
45238
45239         if(Ext.isArray(this.columns)){
45240             this.colModel = new Ext.grid.ColumnModel(this.columns);
45241             delete this.columns;
45242         }
45243
45244         
45245         if(this.ds){
45246             this.store = this.ds;
45247             delete this.ds;
45248         }
45249         if(this.cm){
45250             this.colModel = this.cm;
45251             delete this.cm;
45252         }
45253         if(this.sm){
45254             this.selModel = this.sm;
45255             delete this.sm;
45256         }
45257         this.store = Ext.StoreMgr.lookup(this.store);
45258
45259         this.addEvents(
45260             
45261             
45262             'click',
45263             
45264             'dblclick',
45265             
45266             'contextmenu',
45267             
45268             'mousedown',
45269             
45270             'mouseup',
45271             
45272             'mouseover',
45273             
45274             'mouseout',
45275             
45276             'keypress',
45277             
45278             'keydown',
45279
45280             
45281             
45282             'cellmousedown',
45283             
45284             'rowmousedown',
45285             
45286             'headermousedown',
45287
45288             
45289             'groupmousedown',
45290
45291             
45292             'rowbodymousedown',
45293
45294             
45295             'containermousedown',
45296
45297             
45298             'cellclick',
45299             
45300             'celldblclick',
45301             
45302             'rowclick',
45303             
45304             'rowdblclick',
45305             
45306             'headerclick',
45307             
45308             'headerdblclick',
45309             
45310             'groupclick',
45311             
45312             'groupdblclick',
45313             
45314             'containerclick',
45315             
45316             'containerdblclick',
45317
45318             
45319             'rowbodyclick',
45320             
45321             'rowbodydblclick',
45322
45323             
45324             'rowcontextmenu',
45325             
45326             'cellcontextmenu',
45327             
45328             'headercontextmenu',
45329             
45330             'groupcontextmenu',
45331             
45332             'containercontextmenu',
45333             
45334             'rowbodycontextmenu',
45335             
45336             'bodyscroll',
45337             
45338             'columnresize',
45339             
45340             'columnmove',
45341             
45342             'sortchange',
45343             
45344             'groupchange',
45345             
45346             'reconfigure',
45347             
45348             'viewready'
45349         );
45350     },
45351
45352     
45353     onRender : function(ct, position){
45354         Ext.grid.GridPanel.superclass.onRender.apply(this, arguments);
45355
45356         var c = this.getGridEl();
45357
45358         this.el.addClass('x-grid-panel');
45359
45360         this.mon(c, {
45361             scope: this,
45362             mousedown: this.onMouseDown,
45363             click: this.onClick,
45364             dblclick: this.onDblClick,
45365             contextmenu: this.onContextMenu
45366         });
45367
45368         this.relayEvents(c, ['mousedown','mouseup','mouseover','mouseout','keypress', 'keydown']);
45369
45370         var view = this.getView();
45371         view.init(this);
45372         view.render();
45373         this.getSelectionModel().init(this);
45374     },
45375
45376     
45377     initEvents : function(){
45378         Ext.grid.GridPanel.superclass.initEvents.call(this);
45379
45380         if(this.loadMask){
45381             this.loadMask = new Ext.LoadMask(this.bwrap,
45382                     Ext.apply({store:this.store}, this.loadMask));
45383         }
45384     },
45385
45386     initStateEvents : function(){
45387         Ext.grid.GridPanel.superclass.initStateEvents.call(this);
45388         this.mon(this.colModel, 'hiddenchange', this.saveState, this, {delay: 100});
45389     },
45390
45391     applyState : function(state){
45392         var cm = this.colModel,
45393             cs = state.columns,
45394             store = this.store,
45395             s,
45396             c,
45397             oldIndex;
45398
45399         if(cs){
45400             for(var i = 0, len = cs.length; i < len; i++){
45401                 s = cs[i];
45402                 c = cm.getColumnById(s.id);
45403                 if(c){
45404                     cm.setState(s.id, {
45405                         hidden: s.hidden,
45406                         width: s.width    
45407                     });
45408                     oldIndex = cm.getIndexById(s.id);
45409                     if(oldIndex != i){
45410                         cm.moveColumn(oldIndex, i);
45411                     }
45412                 }
45413             }
45414         }
45415         if(store){
45416             s = state.sort;
45417             if(s){
45418                 store[store.remoteSort ? 'setDefaultSort' : 'sort'](s.field, s.direction);
45419             }
45420             s = state.group;
45421             if(store.groupBy){
45422                 if(s){
45423                     store.groupBy(s);
45424                 }else{
45425                     store.clearGrouping();
45426                 }
45427             }
45428
45429         }
45430         var o = Ext.apply({}, state);
45431         delete o.columns;
45432         delete o.sort;
45433         Ext.grid.GridPanel.superclass.applyState.call(this, o);
45434     },
45435
45436     getState : function(){
45437         var o = {columns: []},
45438             store = this.store,
45439             ss,
45440             gs;
45441
45442         for(var i = 0, c; (c = this.colModel.config[i]); i++){
45443             o.columns[i] = {
45444                 id: c.id,
45445                 width: c.width
45446             };
45447             if(c.hidden){
45448                 o.columns[i].hidden = true;
45449             }
45450         }
45451         if(store){
45452             ss = store.getSortState();
45453             if(ss){
45454                 o.sort = ss;
45455             }
45456             if(store.getGroupState){
45457                 gs = store.getGroupState();
45458                 if(gs){
45459                     o.group = gs;
45460                 }
45461             }
45462         }
45463         return o;
45464     },
45465
45466     
45467     afterRender : function(){
45468         Ext.grid.GridPanel.superclass.afterRender.call(this);
45469         var v = this.view;
45470         this.on('bodyresize', v.layout, v);
45471         v.layout(true);
45472         if(this.deferRowRender){
45473             if (!this.deferRowRenderTask){
45474                 this.deferRowRenderTask = new Ext.util.DelayedTask(v.afterRender, this.view);
45475             }
45476             this.deferRowRenderTask.delay(10);
45477         }else{
45478             v.afterRender();
45479         }
45480         this.viewReady = true;
45481     },
45482
45483     
45484     reconfigure : function(store, colModel){
45485         var rendered = this.rendered;
45486         if(rendered){
45487             if(this.loadMask){
45488                 this.loadMask.destroy();
45489                 this.loadMask = new Ext.LoadMask(this.bwrap,
45490                         Ext.apply({}, {store:store}, this.initialConfig.loadMask));
45491             }
45492         }
45493         if(this.view){
45494             this.view.initData(store, colModel);
45495         }
45496         this.store = store;
45497         this.colModel = colModel;
45498         if(rendered){
45499             this.view.refresh(true);
45500         }
45501         this.fireEvent('reconfigure', this, store, colModel);
45502     },
45503
45504     
45505     onDestroy : function(){
45506         if (this.deferRowRenderTask && this.deferRowRenderTask.cancel){
45507             this.deferRowRenderTask.cancel();
45508         }
45509         if(this.rendered){
45510             Ext.destroy(this.view, this.loadMask);
45511         }else if(this.store && this.store.autoDestroy){
45512             this.store.destroy();
45513         }
45514         Ext.destroy(this.colModel, this.selModel);
45515         this.store = this.selModel = this.colModel = this.view = this.loadMask = null;
45516         Ext.grid.GridPanel.superclass.onDestroy.call(this);
45517     },
45518
45519     
45520     processEvent : function(name, e){
45521         this.view.processEvent(name, e);
45522     },
45523
45524     
45525     onClick : function(e){
45526         this.processEvent('click', e);
45527     },
45528
45529     
45530     onMouseDown : function(e){
45531         this.processEvent('mousedown', e);
45532     },
45533
45534     
45535     onContextMenu : function(e, t){
45536         this.processEvent('contextmenu', e);
45537     },
45538
45539     
45540     onDblClick : function(e){
45541         this.processEvent('dblclick', e);
45542     },
45543
45544     
45545     walkCells : function(row, col, step, fn, scope){
45546         var cm    = this.colModel,
45547             clen  = cm.getColumnCount(),
45548             ds    = this.store,
45549             rlen  = ds.getCount(),
45550             first = true;
45551
45552         if(step < 0){
45553             if(col < 0){
45554                 row--;
45555                 first = false;
45556             }
45557             while(row >= 0){
45558                 if(!first){
45559                     col = clen-1;
45560                 }
45561                 first = false;
45562                 while(col >= 0){
45563                     if(fn.call(scope || this, row, col, cm) === true){
45564                         return [row, col];
45565                     }
45566                     col--;
45567                 }
45568                 row--;
45569             }
45570         } else {
45571             if(col >= clen){
45572                 row++;
45573                 first = false;
45574             }
45575             while(row < rlen){
45576                 if(!first){
45577                     col = 0;
45578                 }
45579                 first = false;
45580                 while(col < clen){
45581                     if(fn.call(scope || this, row, col, cm) === true){
45582                         return [row, col];
45583                     }
45584                     col++;
45585                 }
45586                 row++;
45587             }
45588         }
45589         return null;
45590     },
45591
45592     
45593     getGridEl : function(){
45594         return this.body;
45595     },
45596
45597     
45598     stopEditing : Ext.emptyFn,
45599
45600     
45601     getSelectionModel : function(){
45602         if(!this.selModel){
45603             this.selModel = new Ext.grid.RowSelectionModel(
45604                     this.disableSelection ? {selectRow: Ext.emptyFn} : null);
45605         }
45606         return this.selModel;
45607     },
45608
45609     
45610     getStore : function(){
45611         return this.store;
45612     },
45613
45614     
45615     getColumnModel : function(){
45616         return this.colModel;
45617     },
45618
45619     
45620     getView : function() {
45621         if (!this.view) {
45622             this.view = new Ext.grid.GridView(this.viewConfig);
45623         }
45624         
45625         return this.view;
45626     },
45627     
45628     getDragDropText : function(){
45629         var count = this.selModel.getCount();
45630         return String.format(this.ddText, count, count == 1 ? '' : 's');
45631     }
45632
45633     
45634     
45635     
45636     
45637     
45638     
45639     
45640     
45641     
45642     
45643     
45644     
45645     
45646     
45647     
45648     
45649     
45650     
45651     
45652     
45653     
45654     
45655     
45656     
45657     
45658     
45659     
45660     
45661     
45662     
45663     
45664
45665
45666
45667     
45668     
45669     
45670     
45671     
45672     
45673     
45674     
45675     
45676     
45677     
45678     
45679     
45680     
45681     
45682     
45683 });
45684 Ext.reg('grid', Ext.grid.GridPanel);
45685 Ext.grid.PivotGrid = Ext.extend(Ext.grid.GridPanel, {
45686     
45687     
45688     aggregator: 'sum',
45689     
45690     
45691     renderer: undefined,
45692     
45693     
45694     
45695     
45696     
45697     
45698     
45699     
45700     initComponent: function() {
45701         Ext.grid.PivotGrid.superclass.initComponent.apply(this, arguments);
45702         
45703         this.initAxes();
45704         
45705         
45706         this.enableColumnResize = false;
45707         
45708         this.viewConfig = Ext.apply(this.viewConfig || {}, {
45709             forceFit: true
45710         });
45711         
45712         
45713         
45714         this.colModel = new Ext.grid.ColumnModel({});
45715     },
45716     
45717     
45718     getAggregator: function() {
45719         if (typeof this.aggregator == 'string') {
45720             return Ext.grid.PivotAggregatorMgr.types[this.aggregator];
45721         } else {
45722             return this.aggregator;
45723         }
45724     },
45725     
45726     
45727     setAggregator: function(aggregator) {
45728         this.aggregator = aggregator;
45729     },
45730     
45731     
45732     setMeasure: function(measure) {
45733         this.measure = measure;
45734     },
45735     
45736     
45737     setLeftAxis: function(axis, refresh) {
45738         
45739         this.leftAxis = axis;
45740         
45741         if (refresh) {
45742             this.view.refresh();
45743         }
45744     },
45745     
45746     
45747     setTopAxis: function(axis, refresh) {
45748         
45749         this.topAxis = axis;
45750         
45751         if (refresh) {
45752             this.view.refresh();
45753         }
45754     },
45755     
45756     
45757     initAxes: function() {
45758         var PivotAxis = Ext.grid.PivotAxis;
45759         
45760         if (!(this.leftAxis instanceof PivotAxis)) {
45761             this.setLeftAxis(new PivotAxis({
45762                 orientation: 'vertical',
45763                 dimensions : this.leftAxis || [],
45764                 store      : this.store
45765             }));
45766         };
45767         
45768         if (!(this.topAxis instanceof PivotAxis)) {
45769             this.setTopAxis(new PivotAxis({
45770                 orientation: 'horizontal',
45771                 dimensions : this.topAxis || [],
45772                 store      : this.store
45773             }));
45774         };
45775     },
45776     
45777     
45778     extractData: function() {
45779         var records  = this.store.data.items,
45780             recCount = records.length,
45781             cells    = [],
45782             record, i, j, k;
45783         
45784         if (recCount == 0) {
45785             return [];
45786         }
45787         
45788         var leftTuples = this.leftAxis.getTuples(),
45789             leftCount  = leftTuples.length,
45790             topTuples  = this.topAxis.getTuples(),
45791             topCount   = topTuples.length,
45792             aggregator = this.getAggregator();
45793         
45794         for (i = 0; i < recCount; i++) {
45795             record = records[i];
45796             
45797             for (j = 0; j < leftCount; j++) {
45798                 cells[j] = cells[j] || [];
45799                 
45800                 if (leftTuples[j].matcher(record) === true) {
45801                     for (k = 0; k < topCount; k++) {
45802                         cells[j][k] = cells[j][k] || [];
45803                         
45804                         if (topTuples[k].matcher(record)) {
45805                             cells[j][k].push(record);
45806                         }
45807                     }
45808                 }
45809             }
45810         }
45811         
45812         var rowCount = cells.length,
45813             colCount, row;
45814         
45815         for (i = 0; i < rowCount; i++) {
45816             row = cells[i];
45817             colCount = row.length;
45818             
45819             for (j = 0; j < colCount; j++) {
45820                 cells[i][j] = aggregator(cells[i][j], this.measure);
45821             }
45822         }
45823         
45824         return cells;
45825     },
45826     
45827     
45828     getView: function() {
45829         if (!this.view) {
45830             this.view = new Ext.grid.PivotGridView(this.viewConfig);
45831         }
45832         
45833         return this.view;
45834     }
45835 });
45836
45837 Ext.reg('pivotgrid', Ext.grid.PivotGrid);
45838
45839
45840 Ext.grid.PivotAggregatorMgr = new Ext.AbstractManager();
45841
45842 Ext.grid.PivotAggregatorMgr.registerType('sum', function(records, measure) {
45843     var length = records.length,
45844         total  = 0,
45845         i;
45846     
45847     for (i = 0; i < length; i++) {
45848         total += records[i].get(measure);
45849     }
45850     
45851     return total;
45852 });
45853
45854 Ext.grid.PivotAggregatorMgr.registerType('avg', function(records, measure) {
45855     var length = records.length,
45856         total  = 0,
45857         i;
45858     
45859     for (i = 0; i < length; i++) {
45860         total += records[i].get(measure);
45861     }
45862     
45863     return (total / length) || 'n/a';
45864 });
45865
45866 Ext.grid.PivotAggregatorMgr.registerType('min', function(records, measure) {
45867     var data   = [],
45868         length = records.length,
45869         i;
45870     
45871     for (i = 0; i < length; i++) {
45872         data.push(records[i].get(measure));
45873     }
45874     
45875     return Math.min.apply(this, data) || 'n/a';
45876 });
45877
45878 Ext.grid.PivotAggregatorMgr.registerType('max', function(records, measure) {
45879     var data   = [],
45880         length = records.length,
45881         i;
45882     
45883     for (i = 0; i < length; i++) {
45884         data.push(records[i].get(measure));
45885     }
45886     
45887     return Math.max.apply(this, data) || 'n/a';
45888 });
45889
45890 Ext.grid.PivotAggregatorMgr.registerType('count', function(records, measure) {
45891     return records.length;
45892 });
45893 Ext.grid.GridView = Ext.extend(Ext.util.Observable, {
45894     
45895
45896     
45897
45898     
45899
45900     
45901
45902     
45903
45904     
45905     deferEmptyText : true,
45906
45907     
45908     scrollOffset : undefined,
45909
45910     
45911     autoFill : false,
45912
45913     
45914     forceFit : false,
45915
45916     
45917     sortClasses : ['sort-asc', 'sort-desc'],
45918
45919     
45920     sortAscText : 'Sort Ascending',
45921
45922     
45923     sortDescText : 'Sort Descending',
45924
45925     
45926     columnsText : 'Columns',
45927
45928     
45929     selectedRowClass : 'x-grid3-row-selected',
45930
45931     
45932     borderWidth : 2,
45933     tdClass : 'x-grid3-cell',
45934     hdCls : 'x-grid3-hd',
45935     
45936     
45937     
45938     markDirty : true,
45939
45940     
45941     cellSelectorDepth : 4,
45942     
45943     
45944     rowSelectorDepth : 10,
45945
45946     
45947     rowBodySelectorDepth : 10,
45948
45949     
45950     cellSelector : 'td.x-grid3-cell',
45951     
45952     
45953     rowSelector : 'div.x-grid3-row',
45954
45955     
45956     rowBodySelector : 'div.x-grid3-row-body',
45957
45958     
45959     firstRowCls: 'x-grid3-row-first',
45960     lastRowCls: 'x-grid3-row-last',
45961     rowClsRe: /(?:^|\s+)x-grid3-row-(first|last|alt)(?:\s+|$)/g,
45962     
45963     
45964     headerMenuOpenCls: 'x-grid3-hd-menu-open',
45965     
45966     
45967     rowOverCls: 'x-grid3-row-over',
45968
45969     constructor : function(config) {
45970         Ext.apply(this, config);
45971         
45972         
45973         this.addEvents(
45974             
45975             'beforerowremoved',
45976             
45977             
45978             'beforerowsinserted',
45979             
45980             
45981             'beforerefresh',
45982             
45983             
45984             'rowremoved',
45985             
45986             
45987             'rowsinserted',
45988             
45989             
45990             'rowupdated',
45991             
45992             
45993             'refresh'
45994         );
45995         
45996         Ext.grid.GridView.superclass.constructor.call(this);
45997     },
45998
45999     
46000     
46001     
46002     masterTpl: new Ext.Template(
46003         '<div class="x-grid3" hidefocus="true">',
46004             '<div class="x-grid3-viewport">',
46005                 '<div class="x-grid3-header">',
46006                     '<div class="x-grid3-header-inner">',
46007                         '<div class="x-grid3-header-offset" style="{ostyle}">{header}</div>',
46008                     '</div>',
46009                     '<div class="x-clear"></div>',
46010                 '</div>',
46011                 '<div class="x-grid3-scroller">',
46012                     '<div class="x-grid3-body" style="{bstyle}">{body}</div>',
46013                     '<a href="#" class="x-grid3-focus" tabIndex="-1"></a>',
46014                 '</div>',
46015             '</div>',
46016             '<div class="x-grid3-resize-marker">&#160;</div>',
46017             '<div class="x-grid3-resize-proxy">&#160;</div>',
46018         '</div>'
46019     ),
46020     
46021     
46022     headerTpl: new Ext.Template(
46023         '<table border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',
46024             '<thead>',
46025                 '<tr class="x-grid3-hd-row">{cells}</tr>',
46026             '</thead>',
46027         '</table>'
46028     ),
46029     
46030     
46031     bodyTpl: new Ext.Template('{rows}'),
46032     
46033     
46034     cellTpl: new Ext.Template(
46035         '<td class="x-grid3-col x-grid3-cell x-grid3-td-{id} {css}" style="{style}" tabIndex="0" {cellAttr}>',
46036             '<div class="x-grid3-cell-inner x-grid3-col-{id}" unselectable="on" {attr}>{value}</div>',
46037         '</td>'
46038     ),
46039     
46040     
46041     initTemplates : function() {
46042         var templates = this.templates || {},
46043             template, name,
46044             
46045             headerCellTpl = new Ext.Template(
46046                 '<td class="x-grid3-hd x-grid3-cell x-grid3-td-{id} {css}" style="{style}">',
46047                     '<div {tooltip} {attr} class="x-grid3-hd-inner x-grid3-hd-{id}" unselectable="on" style="{istyle}">', 
46048                         this.grid.enableHdMenu ? '<a class="x-grid3-hd-btn" href="#"></a>' : '',
46049                         '{value}',
46050                         '<img alt="" class="x-grid3-sort-icon" src="', Ext.BLANK_IMAGE_URL, '" />',
46051                     '</div>',
46052                 '</td>'
46053             ),
46054         
46055             rowBodyText = [
46056                 '<tr class="x-grid3-row-body-tr" style="{bodyStyle}">',
46057                     '<td colspan="{cols}" class="x-grid3-body-cell" tabIndex="0" hidefocus="on">',
46058                         '<div class="x-grid3-row-body">{body}</div>',
46059                     '</td>',
46060                 '</tr>'
46061             ].join(""),
46062         
46063             innerText = [
46064                 '<table class="x-grid3-row-table" border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',
46065                      '<tbody>',
46066                         '<tr>{cells}</tr>',
46067                         this.enableRowBody ? rowBodyText : '',
46068                      '</tbody>',
46069                 '</table>'
46070             ].join("");
46071         
46072         Ext.applyIf(templates, {
46073             hcell   : headerCellTpl,
46074             cell    : this.cellTpl,
46075             body    : this.bodyTpl,
46076             header  : this.headerTpl,
46077             master  : this.masterTpl,
46078             row     : new Ext.Template('<div class="x-grid3-row {alt}" style="{tstyle}">' + innerText + '</div>'),
46079             rowInner: new Ext.Template(innerText)
46080         });
46081
46082         for (name in templates) {
46083             template = templates[name];
46084             
46085             if (template && Ext.isFunction(template.compile) && !template.compiled) {
46086                 template.disableFormats = true;
46087                 template.compile();
46088             }
46089         }
46090
46091         this.templates = templates;
46092         this.colRe = new RegExp('x-grid3-td-([^\\s]+)', '');
46093     },
46094
46095     
46096     fly : function(el) {
46097         if (!this._flyweight) {
46098             this._flyweight = new Ext.Element.Flyweight(document.body);
46099         }
46100         this._flyweight.dom = el;
46101         return this._flyweight;
46102     },
46103
46104     
46105     getEditorParent : function() {
46106         return this.scroller.dom;
46107     },
46108
46109     
46110     initElements : function() {
46111         var Element  = Ext.Element,
46112             el       = Ext.get(this.grid.getGridEl().dom.firstChild),
46113             mainWrap = new Element(el.child('div.x-grid3-viewport')),
46114             mainHd   = new Element(mainWrap.child('div.x-grid3-header')),
46115             scroller = new Element(mainWrap.child('div.x-grid3-scroller'));
46116         
46117         if (this.grid.hideHeaders) {
46118             mainHd.setDisplayed(false);
46119         }
46120         
46121         if (this.forceFit) {
46122             scroller.setStyle('overflow-x', 'hidden');
46123         }
46124         
46125         
46126         
46127         Ext.apply(this, {
46128             el      : el,
46129             mainWrap: mainWrap,
46130             scroller: scroller,
46131             mainHd  : mainHd,
46132             innerHd : mainHd.child('div.x-grid3-header-inner').dom,
46133             mainBody: new Element(Element.fly(scroller).child('div.x-grid3-body')),
46134             focusEl : new Element(Element.fly(scroller).child('a')),
46135             
46136             resizeMarker: new Element(el.child('div.x-grid3-resize-marker')),
46137             resizeProxy : new Element(el.child('div.x-grid3-resize-proxy'))
46138         });
46139         
46140         this.focusEl.swallowEvent('click', true);
46141     },
46142
46143     
46144     getRows : function() {
46145         return this.hasRows() ? this.mainBody.dom.childNodes : [];
46146     },
46147
46148     
46149
46150     
46151     findCell : function(el) {
46152         if (!el) {
46153             return false;
46154         }
46155         return this.fly(el).findParent(this.cellSelector, this.cellSelectorDepth);
46156     },
46157
46158     
46159     findCellIndex : function(el, requiredCls) {
46160         var cell = this.findCell(el),
46161             hasCls;
46162         
46163         if (cell) {
46164             hasCls = this.fly(cell).hasClass(requiredCls);
46165             if (!requiredCls || hasCls) {
46166                 return this.getCellIndex(cell);
46167             }
46168         }
46169         return false;
46170     },
46171
46172     
46173     getCellIndex : function(el) {
46174         if (el) {
46175             var match = el.className.match(this.colRe);
46176             
46177             if (match && match[1]) {
46178                 return this.cm.getIndexById(match[1]);
46179             }
46180         }
46181         return false;
46182     },
46183
46184     
46185     findHeaderCell : function(el) {
46186         var cell = this.findCell(el);
46187         return cell && this.fly(cell).hasClass(this.hdCls) ? cell : null;
46188     },
46189
46190     
46191     findHeaderIndex : function(el){
46192         return this.findCellIndex(el, this.hdCls);
46193     },
46194
46195     
46196     findRow : function(el) {
46197         if (!el) {
46198             return false;
46199         }
46200         return this.fly(el).findParent(this.rowSelector, this.rowSelectorDepth);
46201     },
46202
46203     
46204     findRowIndex : function(el) {
46205         var row = this.findRow(el);
46206         return row ? row.rowIndex : false;
46207     },
46208
46209     
46210     findRowBody : function(el) {
46211         if (!el) {
46212             return false;
46213         }
46214         
46215         return this.fly(el).findParent(this.rowBodySelector, this.rowBodySelectorDepth);
46216     },
46217
46218     
46219
46220     
46221     getRow : function(row) {
46222         return this.getRows()[row];
46223     },
46224
46225     
46226     getCell : function(row, col) {
46227         return Ext.fly(this.getRow(row)).query(this.cellSelector)[col]; 
46228     },
46229
46230     
46231     getHeaderCell : function(index) {
46232         return this.mainHd.dom.getElementsByTagName('td')[index];
46233     },
46234
46235     
46236
46237     
46238     addRowClass : function(rowId, cls) {
46239         var row = this.getRow(rowId);
46240         if (row) {
46241             this.fly(row).addClass(cls);
46242         }
46243     },
46244
46245     
46246     removeRowClass : function(row, cls) {
46247         var r = this.getRow(row);
46248         if(r){
46249             this.fly(r).removeClass(cls);
46250         }
46251     },
46252
46253     
46254     removeRow : function(row) {
46255         Ext.removeNode(this.getRow(row));
46256         this.syncFocusEl(row);
46257     },
46258
46259     
46260     removeRows : function(firstRow, lastRow) {
46261         var bd = this.mainBody.dom,
46262             rowIndex;
46263             
46264         for (rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){
46265             Ext.removeNode(bd.childNodes[firstRow]);
46266         }
46267         
46268         this.syncFocusEl(firstRow);
46269     },
46270
46271     
46272     
46273     
46274     getScrollState : function() {
46275         var sb = this.scroller.dom;
46276         
46277         return {
46278             left: sb.scrollLeft, 
46279             top : sb.scrollTop
46280         };
46281     },
46282
46283     
46284     restoreScroll : function(state) {
46285         var sb = this.scroller.dom;
46286         sb.scrollLeft = state.left;
46287         sb.scrollTop  = state.top;
46288     },
46289
46290     
46291     scrollToTop : function() {
46292         var dom = this.scroller.dom;
46293         
46294         dom.scrollTop  = 0;
46295         dom.scrollLeft = 0;
46296     },
46297
46298     
46299     syncScroll : function() {
46300         this.syncHeaderScroll();
46301         var mb = this.scroller.dom;
46302         this.grid.fireEvent('bodyscroll', mb.scrollLeft, mb.scrollTop);
46303     },
46304
46305     
46306     syncHeaderScroll : function() {
46307         var innerHd    = this.innerHd,
46308             scrollLeft = this.scroller.dom.scrollLeft;
46309         
46310         innerHd.scrollLeft = scrollLeft;
46311         innerHd.scrollLeft = scrollLeft; 
46312     },
46313     
46314     
46315     updateSortIcon : function(col, dir) {
46316         var sortClasses = this.sortClasses,
46317             sortClass   = sortClasses[dir == "DESC" ? 1 : 0],
46318             headers     = this.mainHd.select('td').removeClass(sortClasses);
46319         
46320         headers.item(col).addClass(sortClass);
46321     },
46322
46323     
46324     updateAllColumnWidths : function() {
46325         var totalWidth = this.getTotalWidth(),
46326             colCount   = this.cm.getColumnCount(),
46327             rows       = this.getRows(),
46328             rowCount   = rows.length,
46329             widths     = [],
46330             row, rowFirstChild, trow, i, j;
46331         
46332         for (i = 0; i < colCount; i++) {
46333             widths[i] = this.getColumnWidth(i);
46334             this.getHeaderCell(i).style.width = widths[i];
46335         }
46336         
46337         this.updateHeaderWidth();
46338         
46339         for (i = 0; i < rowCount; i++) {
46340             row = rows[i];
46341             row.style.width = totalWidth;
46342             rowFirstChild = row.firstChild;
46343             
46344             if (rowFirstChild) {
46345                 rowFirstChild.style.width = totalWidth;
46346                 trow = rowFirstChild.rows[0];
46347                 
46348                 for (j = 0; j < colCount; j++) {
46349                     trow.childNodes[j].style.width = widths[j];
46350                 }
46351             }
46352         }
46353         
46354         this.onAllColumnWidthsUpdated(widths, totalWidth);
46355     },
46356
46357     
46358     updateColumnWidth : function(column, width) {
46359         var columnWidth = this.getColumnWidth(column),
46360             totalWidth  = this.getTotalWidth(),
46361             headerCell  = this.getHeaderCell(column),
46362             nodes       = this.getRows(),
46363             nodeCount   = nodes.length,
46364             row, i, firstChild;
46365         
46366         this.updateHeaderWidth();
46367         headerCell.style.width = columnWidth;
46368         
46369         for (i = 0; i < nodeCount; i++) {
46370             row = nodes[i];
46371             firstChild = row.firstChild;
46372             
46373             row.style.width = totalWidth;
46374             if (firstChild) {
46375                 firstChild.style.width = totalWidth;
46376                 firstChild.rows[0].childNodes[column].style.width = columnWidth;
46377             }
46378         }
46379         
46380         this.onColumnWidthUpdated(column, columnWidth, totalWidth);
46381     },
46382     
46383     
46384     updateColumnHidden : function(col, hidden) {
46385         var totalWidth = this.getTotalWidth(),
46386             display    = hidden ? 'none' : '',
46387             headerCell = this.getHeaderCell(col),
46388             nodes      = this.getRows(),
46389             nodeCount  = nodes.length,
46390             row, rowFirstChild, i;
46391         
46392         this.updateHeaderWidth();
46393         headerCell.style.display = display;
46394         
46395         for (i = 0; i < nodeCount; i++) {
46396             row = nodes[i];
46397             row.style.width = totalWidth;
46398             rowFirstChild = row.firstChild;
46399             
46400             if (rowFirstChild) {
46401                 rowFirstChild.style.width = totalWidth;
46402                 rowFirstChild.rows[0].childNodes[col].style.display = display;
46403             }
46404         }
46405         
46406         this.onColumnHiddenUpdated(col, hidden, totalWidth);
46407         delete this.lastViewWidth; 
46408         this.layout();
46409     },
46410
46411     
46412     doRender : function(columns, records, store, startRow, colCount, stripe) {
46413         var templates = this.templates,
46414             cellTemplate = templates.cell,
46415             rowTemplate = templates.row,
46416             last = colCount - 1,
46417             tstyle = 'width:' + this.getTotalWidth() + ';',
46418             
46419             rowBuffer = [],
46420             colBuffer = [],
46421             rowParams = {tstyle: tstyle},
46422             meta = {},
46423             len  = records.length,
46424             alt,
46425             column,
46426             record, i, j, rowIndex;
46427
46428         
46429         for (j = 0; j < len; j++) {
46430             record    = records[j];
46431             colBuffer = [];
46432
46433             rowIndex = j + startRow;
46434
46435             
46436             for (i = 0; i < colCount; i++) {
46437                 column = columns[i];
46438                 
46439                 meta.id    = column.id;
46440                 meta.css   = i === 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');
46441                 meta.attr  = meta.cellAttr = '';
46442                 meta.style = column.style;
46443                 meta.value = column.renderer.call(column.scope, record.data[column.name], meta, record, rowIndex, i, store);
46444
46445                 if (Ext.isEmpty(meta.value)) {
46446                     meta.value = '&#160;';
46447                 }
46448
46449                 if (this.markDirty && record.dirty && typeof record.modified[column.name] != 'undefined') {
46450                     meta.css += ' x-grid3-dirty-cell';
46451                 }
46452
46453                 colBuffer[colBuffer.length] = cellTemplate.apply(meta);
46454             }
46455
46456             alt = [];
46457             
46458             if (stripe && ((rowIndex + 1) % 2 === 0)) {
46459                 alt[0] = 'x-grid3-row-alt';
46460             }
46461
46462             if (record.dirty) {
46463                 alt[1] = ' x-grid3-dirty-row';
46464             }
46465
46466             rowParams.cols = colCount;
46467
46468             if (this.getRowClass) {
46469                 alt[2] = this.getRowClass(record, rowIndex, rowParams, store);
46470             }
46471
46472             rowParams.alt   = alt.join(' ');
46473             rowParams.cells = colBuffer.join('');
46474
46475             rowBuffer[rowBuffer.length] = rowTemplate.apply(rowParams);
46476         }
46477
46478         return rowBuffer.join('');
46479     },
46480
46481     
46482     processRows : function(startRow, skipStripe) {
46483         if (!this.ds || this.ds.getCount() < 1) {
46484             return;
46485         }
46486
46487         var rows   = this.getRows(),
46488             length = rows.length,
46489             row, i;
46490
46491         skipStripe = skipStripe || !this.grid.stripeRows;
46492         startRow   = startRow   || 0;
46493
46494         for (i = 0; i < length; i++) {
46495             row = rows[i];
46496             if (row) {
46497                 row.rowIndex = i;
46498                 if (!skipStripe) {
46499                     row.className = row.className.replace(this.rowClsRe, ' ');
46500                     if ((i + 1) % 2 === 0){
46501                         row.className += ' x-grid3-row-alt';
46502                     }
46503                 }
46504             }
46505         }
46506
46507         
46508         if (startRow === 0) {
46509             Ext.fly(rows[0]).addClass(this.firstRowCls);
46510         }
46511
46512         Ext.fly(rows[length - 1]).addClass(this.lastRowCls);
46513     },
46514     
46515     
46516     afterRender : function() {
46517         if (!this.ds || !this.cm) {
46518             return;
46519         }
46520         
46521         this.mainBody.dom.innerHTML = this.renderBody() || '&#160;';
46522         this.processRows(0, true);
46523
46524         if (this.deferEmptyText !== true) {
46525             this.applyEmptyText();
46526         }
46527         
46528         this.grid.fireEvent('viewready', this.grid);
46529     },
46530     
46531     
46532     afterRenderUI: function() {
46533         var grid = this.grid;
46534         
46535         this.initElements();
46536
46537         
46538         Ext.fly(this.innerHd).on('click', this.handleHdDown, this);
46539
46540         this.mainHd.on({
46541             scope    : this,
46542             mouseover: this.handleHdOver,
46543             mouseout : this.handleHdOut,
46544             mousemove: this.handleHdMove
46545         });
46546
46547         this.scroller.on('scroll', this.syncScroll,  this);
46548         
46549         if (grid.enableColumnResize !== false) {
46550             this.splitZone = new Ext.grid.GridView.SplitDragZone(grid, this.mainHd.dom);
46551         }
46552
46553         if (grid.enableColumnMove) {
46554             this.columnDrag = new Ext.grid.GridView.ColumnDragZone(grid, this.innerHd);
46555             this.columnDrop = new Ext.grid.HeaderDropZone(grid, this.mainHd.dom);
46556         }
46557
46558         if (grid.enableHdMenu !== false) {
46559             this.hmenu = new Ext.menu.Menu({id: grid.id + '-hctx'});
46560             this.hmenu.add(
46561                 {itemId:'asc',  text: this.sortAscText,  cls: 'xg-hmenu-sort-asc'},
46562                 {itemId:'desc', text: this.sortDescText, cls: 'xg-hmenu-sort-desc'}
46563             );
46564
46565             if (grid.enableColumnHide !== false) {
46566                 this.colMenu = new Ext.menu.Menu({id:grid.id + '-hcols-menu'});
46567                 this.colMenu.on({
46568                     scope     : this,
46569                     beforeshow: this.beforeColMenuShow,
46570                     itemclick : this.handleHdMenuClick
46571                 });
46572                 this.hmenu.add('-', {
46573                     itemId:'columns',
46574                     hideOnClick: false,
46575                     text: this.columnsText,
46576                     menu: this.colMenu,
46577                     iconCls: 'x-cols-icon'
46578                 });
46579             }
46580
46581             this.hmenu.on('itemclick', this.handleHdMenuClick, this);
46582         }
46583
46584         if (grid.trackMouseOver) {
46585             this.mainBody.on({
46586                 scope    : this,
46587                 mouseover: this.onRowOver,
46588                 mouseout : this.onRowOut
46589             });
46590         }
46591
46592         if (grid.enableDragDrop || grid.enableDrag) {
46593             this.dragZone = new Ext.grid.GridDragZone(grid, {
46594                 ddGroup : grid.ddGroup || 'GridDD'
46595             });
46596         }
46597
46598         this.updateHeaderSortState();
46599     },
46600
46601     
46602     renderUI : function() {
46603         var templates = this.templates;
46604
46605         return templates.master.apply({
46606             body  : templates.body.apply({rows:'&#160;'}),
46607             header: this.renderHeaders(),
46608             ostyle: 'width:' + this.getOffsetWidth() + ';',
46609             bstyle: 'width:' + this.getTotalWidth()  + ';'
46610         });
46611     },
46612
46613     
46614     processEvent : function(name, e) {
46615         var target = e.getTarget(),
46616             grid   = this.grid,
46617             header = this.findHeaderIndex(target),
46618             row, cell, col, body;
46619
46620         grid.fireEvent(name, e);
46621
46622         if (header !== false) {
46623             grid.fireEvent('header' + name, grid, header, e);
46624         } else {
46625             row = this.findRowIndex(target);
46626
46627
46628
46629
46630             if (row !== false) {
46631                 cell = this.findCellIndex(target);
46632                 if (cell !== false) {
46633                     col = grid.colModel.getColumnAt(cell);
46634                     if (grid.fireEvent('cell' + name, grid, row, cell, e) !== false) {
46635                         if (!col || (col.processEvent && (col.processEvent(name, e, grid, row, cell) !== false))) {
46636                             grid.fireEvent('row' + name, grid, row, e);
46637                         }
46638                     }
46639                 } else {
46640                     if (grid.fireEvent('row' + name, grid, row, e) !== false) {
46641                         (body = this.findRowBody(target)) && grid.fireEvent('rowbody' + name, grid, row, e);
46642                     }
46643                 }
46644             } else {
46645                 grid.fireEvent('container' + name, grid, e);
46646             }
46647         }
46648     },
46649
46650     
46651     layout : function(initial) {
46652         if (!this.mainBody) {
46653             return; 
46654         }
46655
46656         var grid       = this.grid,
46657             gridEl     = grid.getGridEl(),
46658             gridSize   = gridEl.getSize(true),
46659             gridWidth  = gridSize.width,
46660             gridHeight = gridSize.height,
46661             scroller   = this.scroller,
46662             scrollStyle, headerHeight, scrollHeight;
46663         
46664         if (gridWidth < 20 || gridHeight < 20) {
46665             return;
46666         }
46667         
46668         if (grid.autoHeight) {
46669             scrollStyle = scroller.dom.style;
46670             scrollStyle.overflow = 'visible';
46671             
46672             if (Ext.isWebKit) {
46673                 scrollStyle.position = 'static';
46674             }
46675         } else {
46676             this.el.setSize(gridWidth, gridHeight);
46677             
46678             headerHeight = this.mainHd.getHeight();
46679             scrollHeight = gridHeight - headerHeight;
46680             
46681             scroller.setSize(gridWidth, scrollHeight);
46682             
46683             if (this.innerHd) {
46684                 this.innerHd.style.width = (gridWidth) + "px";
46685             }
46686         }
46687         
46688         if (this.forceFit || (initial === true && this.autoFill)) {
46689             if (this.lastViewWidth != gridWidth) {
46690                 this.fitColumns(false, false);
46691                 this.lastViewWidth = gridWidth;
46692             }
46693         } else {
46694             this.autoExpand();
46695             this.syncHeaderScroll();
46696         }
46697         
46698         this.onLayout(gridWidth, scrollHeight);
46699     },
46700
46701     
46702     
46703     onLayout : function(vw, vh) {
46704         
46705     },
46706
46707     onColumnWidthUpdated : function(col, w, tw) {
46708         
46709     },
46710
46711     onAllColumnWidthsUpdated : function(ws, tw) {
46712         
46713     },
46714
46715     onColumnHiddenUpdated : function(col, hidden, tw) {
46716         
46717     },
46718
46719     updateColumnText : function(col, text) {
46720         
46721     },
46722
46723     afterMove : function(colIndex) {
46724         
46725     },
46726
46727     
46728     
46729     init : function(grid) {
46730         this.grid = grid;
46731
46732         this.initTemplates();
46733         this.initData(grid.store, grid.colModel);
46734         this.initUI(grid);
46735     },
46736
46737     
46738     getColumnId : function(index){
46739         return this.cm.getColumnId(index);
46740     },
46741
46742     
46743     getOffsetWidth : function() {
46744         return (this.cm.getTotalWidth() + this.getScrollOffset()) + 'px';
46745     },
46746
46747     
46748     getScrollOffset: function() {
46749         return Ext.num(this.scrollOffset, Ext.getScrollBarWidth());
46750     },
46751
46752     
46753     renderHeaders : function() {
46754         var colModel   = this.cm,
46755             templates  = this.templates,
46756             headerTpl  = templates.hcell,
46757             properties = {},
46758             colCount   = colModel.getColumnCount(),
46759             last       = colCount - 1,
46760             cells      = [],
46761             i, cssCls;
46762         
46763         for (i = 0; i < colCount; i++) {
46764             if (i == 0) {
46765                 cssCls = 'x-grid3-cell-first ';
46766             } else {
46767                 cssCls = i == last ? 'x-grid3-cell-last ' : '';
46768             }
46769             
46770             properties = {
46771                 id     : colModel.getColumnId(i),
46772                 value  : colModel.getColumnHeader(i) || '',
46773                 style  : this.getColumnStyle(i, true),
46774                 css    : cssCls,
46775                 tooltip: this.getColumnTooltip(i)
46776             };
46777             
46778             if (colModel.config[i].align == 'right') {
46779                 properties.istyle = 'padding-right: 16px;';
46780             } else {
46781                 delete properties.istyle;
46782             }
46783             
46784             cells[i] = headerTpl.apply(properties);
46785         }
46786         
46787         return templates.header.apply({
46788             cells : cells.join(""),
46789             tstyle: String.format("width: {0};", this.getTotalWidth())
46790         });
46791     },
46792
46793     
46794     getColumnTooltip : function(i) {
46795         var tooltip = this.cm.getColumnTooltip(i);
46796         if (tooltip) {
46797             if (Ext.QuickTips.isEnabled()) {
46798                 return 'ext:qtip="' + tooltip + '"';
46799             } else {
46800                 return 'title="' + tooltip + '"';
46801             }
46802         }
46803         
46804         return '';
46805     },
46806
46807     
46808     beforeUpdate : function() {
46809         this.grid.stopEditing(true);
46810     },
46811
46812     
46813     updateHeaders : function() {
46814         this.innerHd.firstChild.innerHTML = this.renderHeaders();
46815         
46816         this.updateHeaderWidth(false);
46817     },
46818     
46819     
46820     updateHeaderWidth: function(updateMain) {
46821         var innerHdChild = this.innerHd.firstChild,
46822             totalWidth   = this.getTotalWidth();
46823         
46824         innerHdChild.style.width = this.getOffsetWidth();
46825         innerHdChild.firstChild.style.width = totalWidth;
46826         
46827         if (updateMain !== false) {
46828             this.mainBody.dom.style.width = totalWidth;
46829         }
46830     },
46831
46832     
46833     focusRow : function(row) {
46834         this.focusCell(row, 0, false);
46835     },
46836
46837     
46838     focusCell : function(row, col, hscroll) {
46839         this.syncFocusEl(this.ensureVisible(row, col, hscroll));
46840         
46841         var focusEl = this.focusEl;
46842         
46843         if (Ext.isGecko) {
46844             focusEl.focus();
46845         } else {
46846             focusEl.focus.defer(1, focusEl);
46847         }
46848     },
46849
46850     
46851     resolveCell : function(row, col, hscroll) {
46852         if (!Ext.isNumber(row)) {
46853             row = row.rowIndex;
46854         }
46855         
46856         if (!this.ds) {
46857             return null;
46858         }
46859         
46860         if (row < 0 || row >= this.ds.getCount()) {
46861             return null;
46862         }
46863         col = (col !== undefined ? col : 0);
46864
46865         var rowEl    = this.getRow(row),
46866             colModel = this.cm,
46867             colCount = colModel.getColumnCount(),
46868             cellEl;
46869             
46870         if (!(hscroll === false && col === 0)) {
46871             while (col < colCount && colModel.isHidden(col)) {
46872                 col++;
46873             }
46874             
46875             cellEl = this.getCell(row, col);
46876         }
46877
46878         return {row: rowEl, cell: cellEl};
46879     },
46880
46881     
46882     getResolvedXY : function(resolved) {
46883         if (!resolved) {
46884             return null;
46885         }
46886         
46887         var cell = resolved.cell,
46888             row  = resolved.row;
46889         
46890         if (cell) {
46891             return Ext.fly(cell).getXY();
46892         } else {
46893             return [this.el.getX(), Ext.fly(row).getY()];
46894         }
46895     },
46896
46897     
46898     syncFocusEl : function(row, col, hscroll) {
46899         var xy = row;
46900         
46901         if (!Ext.isArray(xy)) {
46902             row = Math.min(row, Math.max(0, this.getRows().length-1));
46903             
46904             if (isNaN(row)) {
46905                 return;
46906             }
46907             
46908             xy = this.getResolvedXY(this.resolveCell(row, col, hscroll));
46909         }
46910         
46911         this.focusEl.setXY(xy || this.scroller.getXY());
46912     },
46913
46914     
46915     ensureVisible : function(row, col, hscroll) {
46916         var resolved = this.resolveCell(row, col, hscroll);
46917         
46918         if (!resolved || !resolved.row) {
46919             return null;
46920         }
46921
46922         var rowEl  = resolved.row,
46923             cellEl = resolved.cell,
46924             c = this.scroller.dom,
46925             p = rowEl,
46926             ctop = 0,
46927             stop = this.el.dom;
46928
46929         while (p && p != stop) {
46930             ctop += p.offsetTop;
46931             p = p.offsetParent;
46932         }
46933
46934         ctop -= this.mainHd.dom.offsetHeight;
46935         stop = parseInt(c.scrollTop, 10);
46936
46937         var cbot = ctop + rowEl.offsetHeight,
46938             ch = c.clientHeight,
46939             sbot = stop + ch;
46940
46941
46942         if (ctop < stop) {
46943           c.scrollTop = ctop;
46944         } else if(cbot > sbot) {
46945             c.scrollTop = cbot-ch;
46946         }
46947
46948         if (hscroll !== false) {
46949             var cleft  = parseInt(cellEl.offsetLeft, 10),
46950                 cright = cleft + cellEl.offsetWidth,
46951                 sleft  = parseInt(c.scrollLeft, 10),
46952                 sright = sleft + c.clientWidth;
46953                 
46954             if (cleft < sleft) {
46955                 c.scrollLeft = cleft;
46956             } else if(cright > sright) {
46957                 c.scrollLeft = cright-c.clientWidth;
46958             }
46959         }
46960         
46961         return this.getResolvedXY(resolved);
46962     },
46963
46964     
46965     insertRows : function(dm, firstRow, lastRow, isUpdate) {
46966         var last = dm.getCount() - 1;
46967         if( !isUpdate && firstRow === 0 && lastRow >= last) {
46968             this.fireEvent('beforerowsinserted', this, firstRow, lastRow);
46969                 this.refresh();
46970             this.fireEvent('rowsinserted', this, firstRow, lastRow);
46971         } else {
46972             if (!isUpdate) {
46973                 this.fireEvent('beforerowsinserted', this, firstRow, lastRow);
46974             }
46975             var html = this.renderRows(firstRow, lastRow),
46976                 before = this.getRow(firstRow);
46977             if (before) {
46978                 if(firstRow === 0){
46979                     Ext.fly(this.getRow(0)).removeClass(this.firstRowCls);
46980                 }
46981                 Ext.DomHelper.insertHtml('beforeBegin', before, html);
46982             } else {
46983                 var r = this.getRow(last - 1);
46984                 if(r){
46985                     Ext.fly(r).removeClass(this.lastRowCls);
46986                 }
46987                 Ext.DomHelper.insertHtml('beforeEnd', this.mainBody.dom, html);
46988             }
46989             if (!isUpdate) {
46990                 this.fireEvent('rowsinserted', this, firstRow, lastRow);
46991                 this.processRows(firstRow);
46992             } else if (firstRow === 0 || firstRow >= last) {
46993                 
46994                 Ext.fly(this.getRow(firstRow)).addClass(firstRow === 0 ? this.firstRowCls : this.lastRowCls);
46995             }
46996         }
46997         this.syncFocusEl(firstRow);
46998     },
46999
47000     
47001     deleteRows : function(dm, firstRow, lastRow) {
47002         if (dm.getRowCount() < 1) {
47003             this.refresh();
47004         } else {
47005             this.fireEvent('beforerowsdeleted', this, firstRow, lastRow);
47006
47007             this.removeRows(firstRow, lastRow);
47008
47009             this.processRows(firstRow);
47010             this.fireEvent('rowsdeleted', this, firstRow, lastRow);
47011         }
47012     },
47013
47014     
47015     getColumnStyle : function(colIndex, isHeader) {
47016         var colModel  = this.cm,
47017             colConfig = colModel.config,
47018             style     = isHeader ? '' : colConfig[colIndex].css || '',
47019             align     = colConfig[colIndex].align;
47020         
47021         style += String.format("width: {0};", this.getColumnWidth(colIndex));
47022         
47023         if (colModel.isHidden(colIndex)) {
47024             style += 'display: none; ';
47025         }
47026         
47027         if (align) {
47028             style += String.format("text-align: {0};", align);
47029         }
47030         
47031         return style;
47032     },
47033
47034     
47035     getColumnWidth : function(column) {
47036         var columnWidth = this.cm.getColumnWidth(column),
47037             borderWidth = this.borderWidth;
47038         
47039         if (Ext.isNumber(columnWidth)) {
47040             if (Ext.isBorderBox || (Ext.isWebKit && !Ext.isSafari2)) {
47041                 return columnWidth + "px";
47042             } else {
47043                 return Math.max(columnWidth - borderWidth, 0) + "px";
47044             }
47045         } else {
47046             return columnWidth;
47047         }
47048     },
47049
47050     
47051     getTotalWidth : function() {
47052         return this.cm.getTotalWidth() + 'px';
47053     },
47054
47055     
47056     fitColumns : function(preventRefresh, onlyExpand, omitColumn) {
47057         var grid          = this.grid,
47058             colModel      = this.cm,
47059             totalColWidth = colModel.getTotalWidth(false),
47060             gridWidth     = this.getGridInnerWidth(),
47061             extraWidth    = gridWidth - totalColWidth,
47062             columns       = [],
47063             extraCol      = 0,
47064             width         = 0,
47065             colWidth, fraction, i;
47066         
47067         
47068         if (gridWidth < 20 || extraWidth === 0) {
47069             return false;
47070         }
47071         
47072         var visibleColCount = colModel.getColumnCount(true),
47073             totalColCount   = colModel.getColumnCount(false),
47074             adjCount        = visibleColCount - (Ext.isNumber(omitColumn) ? 1 : 0);
47075         
47076         if (adjCount === 0) {
47077             adjCount = 1;
47078             omitColumn = undefined;
47079         }
47080         
47081         
47082         for (i = 0; i < totalColCount; i++) {
47083             if (!colModel.isFixed(i) && i !== omitColumn) {
47084                 colWidth = colModel.getColumnWidth(i);
47085                 columns.push(i, colWidth);
47086                 
47087                 if (!colModel.isHidden(i)) {
47088                     extraCol = i;
47089                     width += colWidth;
47090                 }
47091             }
47092         }
47093         
47094         fraction = (gridWidth - colModel.getTotalWidth()) / width;
47095         
47096         while (columns.length) {
47097             colWidth = columns.pop();
47098             i        = columns.pop();
47099             
47100             colModel.setColumnWidth(i, Math.max(grid.minColumnWidth, Math.floor(colWidth + colWidth * fraction)), true);
47101         }
47102         
47103         
47104         totalColWidth = colModel.getTotalWidth(false);
47105         
47106         if (totalColWidth > gridWidth) {
47107             var adjustCol = (adjCount == visibleColCount) ? extraCol : omitColumn,
47108                 newWidth  = Math.max(1, colModel.getColumnWidth(adjustCol) - (totalColWidth - gridWidth));
47109             
47110             colModel.setColumnWidth(adjustCol, newWidth, true);
47111         }
47112         
47113         if (preventRefresh !== true) {
47114             this.updateAllColumnWidths();
47115         }
47116         
47117         return true;
47118     },
47119
47120     
47121     autoExpand : function(preventUpdate) {
47122         var grid             = this.grid,
47123             colModel         = this.cm,
47124             gridWidth        = this.getGridInnerWidth(),
47125             totalColumnWidth = colModel.getTotalWidth(false),
47126             autoExpandColumn = grid.autoExpandColumn;
47127         
47128         if (!this.userResized && autoExpandColumn) {
47129             if (gridWidth != totalColumnWidth) {
47130                 
47131                 var colIndex     = colModel.getIndexById(autoExpandColumn),
47132                     currentWidth = colModel.getColumnWidth(colIndex),
47133                     desiredWidth = gridWidth - totalColumnWidth + currentWidth,
47134                     newWidth     = Math.min(Math.max(desiredWidth, grid.autoExpandMin), grid.autoExpandMax);
47135                 
47136                 if (currentWidth != newWidth) {
47137                     colModel.setColumnWidth(colIndex, newWidth, true);
47138                     
47139                     if (preventUpdate !== true) {
47140                         this.updateColumnWidth(colIndex, newWidth);
47141                     }
47142                 }
47143             }
47144         }
47145     },
47146     
47147     
47148     getGridInnerWidth: function() {
47149         return this.grid.getGridEl().getWidth(true) - this.getScrollOffset();
47150     },
47151
47152     
47153     getColumnData : function() {
47154         var columns  = [],
47155             colModel = this.cm,
47156             colCount = colModel.getColumnCount(),
47157             fields   = this.ds.fields,
47158             i, name;
47159         
47160         for (i = 0; i < colCount; i++) {
47161             name = colModel.getDataIndex(i);
47162             
47163             columns[i] = {
47164                 name    : Ext.isDefined(name) ? name : (fields.get(i) ? fields.get(i).name : undefined),
47165                 renderer: colModel.getRenderer(i),
47166                 scope   : colModel.getRendererScope(i),
47167                 id      : colModel.getColumnId(i),
47168                 style   : this.getColumnStyle(i)
47169             };
47170         }
47171         
47172         return columns;
47173     },
47174
47175     
47176     renderRows : function(startRow, endRow) {
47177         var grid     = this.grid,
47178             store    = grid.store,
47179             stripe   = grid.stripeRows,
47180             colModel = grid.colModel,
47181             colCount = colModel.getColumnCount(),
47182             rowCount = store.getCount(),
47183             records;
47184         
47185         if (rowCount < 1) {
47186             return '';
47187         }
47188         
47189         startRow = startRow || 0;
47190         endRow   = Ext.isDefined(endRow) ? endRow : rowCount - 1;
47191         records  = store.getRange(startRow, endRow);
47192         
47193         return this.doRender(this.getColumnData(), records, store, startRow, colCount, stripe);
47194     },
47195
47196     
47197     renderBody : function(){
47198         var markup = this.renderRows() || '&#160;';
47199         return this.templates.body.apply({rows: markup});
47200     },
47201
47202     
47203     refreshRow: function(record) {
47204         var store     = this.ds,
47205             colCount  = this.cm.getColumnCount(),
47206             columns   = this.getColumnData(),
47207             last      = colCount - 1,
47208             cls       = ['x-grid3-row'],
47209             rowParams = {
47210                 tstyle: String.format("width: {0};", this.getTotalWidth())
47211             },
47212             colBuffer = [],
47213             cellTpl   = this.templates.cell,
47214             rowIndex, row, column, meta, css, i;
47215         
47216         if (Ext.isNumber(record)) {
47217             rowIndex = record;
47218             record   = store.getAt(rowIndex);
47219         } else {
47220             rowIndex = store.indexOf(record);
47221         }
47222         
47223         
47224         if (!record || rowIndex < 0) {
47225             return;
47226         }
47227         
47228         
47229         for (i = 0; i < colCount; i++) {
47230             column = columns[i];
47231             
47232             if (i == 0) {
47233                 css = 'x-grid3-cell-first';
47234             } else {
47235                 css = (i == last) ? 'x-grid3-cell-last ' : '';
47236             }
47237             
47238             meta = {
47239                 id      : column.id,
47240                 style   : column.style,
47241                 css     : css,
47242                 attr    : "",
47243                 cellAttr: ""
47244             };
47245             
47246             meta.value = column.renderer.call(column.scope, record.data[column.name], meta, record, rowIndex, i, store);
47247             
47248             if (Ext.isEmpty(meta.value)) {
47249                 meta.value = '&#160;';
47250             }
47251             
47252             if (this.markDirty && record.dirty && typeof record.modified[column.name] != 'undefined') {
47253                 meta.css += ' x-grid3-dirty-cell';
47254             }
47255             
47256             colBuffer[i] = cellTpl.apply(meta);
47257         }
47258         
47259         row = this.getRow(rowIndex);
47260         row.className = '';
47261         
47262         if (this.grid.stripeRows && ((rowIndex + 1) % 2 === 0)) {
47263             cls.push('x-grid3-row-alt');
47264         }
47265         
47266         if (this.getRowClass) {
47267             rowParams.cols = colCount;
47268             cls.push(this.getRowClass(record, rowIndex, rowParams, store));
47269         }
47270         
47271         this.fly(row).addClass(cls).setStyle(rowParams.tstyle);
47272         rowParams.cells = colBuffer.join("");
47273         row.innerHTML = this.templates.rowInner.apply(rowParams);
47274         
47275         this.fireEvent('rowupdated', this, rowIndex, record);
47276     },
47277
47278     
47279     refresh : function(headersToo) {
47280         this.fireEvent('beforerefresh', this);
47281         this.grid.stopEditing(true);
47282
47283         var result = this.renderBody();
47284         this.mainBody.update(result).setWidth(this.getTotalWidth());
47285         if (headersToo === true) {
47286             this.updateHeaders();
47287             this.updateHeaderSortState();
47288         }
47289         this.processRows(0, true);
47290         this.layout();
47291         this.applyEmptyText();
47292         this.fireEvent('refresh', this);
47293     },
47294
47295     
47296     applyEmptyText : function() {
47297         if (this.emptyText && !this.hasRows()) {
47298             this.mainBody.update('<div class="x-grid-empty">' + this.emptyText + '</div>');
47299         }
47300     },
47301
47302     
47303     updateHeaderSortState : function() {
47304         var state = this.ds.getSortState();
47305         if (!state) {
47306             return;
47307         }
47308
47309         if (!this.sortState || (this.sortState.field != state.field || this.sortState.direction != state.direction)) {
47310             this.grid.fireEvent('sortchange', this.grid, state);
47311         }
47312
47313         this.sortState = state;
47314
47315         var sortColumn = this.cm.findColumnIndex(state.field);
47316         if (sortColumn != -1) {
47317             var sortDir = state.direction;
47318             this.updateSortIcon(sortColumn, sortDir);
47319         }
47320     },
47321
47322     
47323     clearHeaderSortState : function() {
47324         if (!this.sortState) {
47325             return;
47326         }
47327         this.grid.fireEvent('sortchange', this.grid, null);
47328         this.mainHd.select('td').removeClass(this.sortClasses);
47329         delete this.sortState;
47330     },
47331
47332     
47333     destroy : function() {
47334         var me              = this,
47335             grid            = me.grid,
47336             gridEl          = grid.getGridEl(),
47337             dragZone        = me.dragZone,
47338             splitZone       = me.splitZone,
47339             columnDrag      = me.columnDrag,
47340             columnDrop      = me.columnDrop,
47341             scrollToTopTask = me.scrollToTopTask,
47342             columnDragData,
47343             columnDragProxy;
47344         
47345         if (scrollToTopTask && scrollToTopTask.cancel) {
47346             scrollToTopTask.cancel();
47347         }
47348         
47349         Ext.destroyMembers(me, 'colMenu', 'hmenu');
47350
47351         me.initData(null, null);
47352         me.purgeListeners();
47353         
47354         Ext.fly(me.innerHd).un("click", me.handleHdDown, me);
47355
47356         if (grid.enableColumnMove) {
47357             columnDragData = columnDrag.dragData;
47358             columnDragProxy = columnDrag.proxy;
47359             Ext.destroy(
47360                 columnDrag.el,
47361                 columnDragProxy.ghost,
47362                 columnDragProxy.el,
47363                 columnDrop.el,
47364                 columnDrop.proxyTop,
47365                 columnDrop.proxyBottom,
47366                 columnDragData.ddel,
47367                 columnDragData.header
47368             );
47369             
47370             if (columnDragProxy.anim) {
47371                 Ext.destroy(columnDragProxy.anim);
47372             }
47373             
47374             delete columnDragProxy.ghost;
47375             delete columnDragData.ddel;
47376             delete columnDragData.header;
47377             columnDrag.destroy();
47378             
47379             delete Ext.dd.DDM.locationCache[columnDrag.id];
47380             delete columnDrag._domRef;
47381
47382             delete columnDrop.proxyTop;
47383             delete columnDrop.proxyBottom;
47384             columnDrop.destroy();
47385             delete Ext.dd.DDM.locationCache["gridHeader" + gridEl.id];
47386             delete columnDrop._domRef;
47387             delete Ext.dd.DDM.ids[columnDrop.ddGroup];
47388         }
47389
47390         if (splitZone) { 
47391             splitZone.destroy();
47392             delete splitZone._domRef;
47393             delete Ext.dd.DDM.ids["gridSplitters" + gridEl.id];
47394         }
47395
47396         Ext.fly(me.innerHd).removeAllListeners();
47397         Ext.removeNode(me.innerHd);
47398         delete me.innerHd;
47399
47400         Ext.destroy(
47401             me.el,
47402             me.mainWrap,
47403             me.mainHd,
47404             me.scroller,
47405             me.mainBody,
47406             me.focusEl,
47407             me.resizeMarker,
47408             me.resizeProxy,
47409             me.activeHdBtn,
47410             me._flyweight,
47411             dragZone,
47412             splitZone
47413         );
47414
47415         delete grid.container;
47416
47417         if (dragZone) {
47418             dragZone.destroy();
47419         }
47420
47421         Ext.dd.DDM.currentTarget = null;
47422         delete Ext.dd.DDM.locationCache[gridEl.id];
47423
47424         Ext.EventManager.removeResizeListener(me.onWindowResize, me);
47425     },
47426
47427     
47428     onDenyColumnHide : function() {
47429
47430     },
47431
47432     
47433     render : function() {
47434         if (this.autoFill) {
47435             var ct = this.grid.ownerCt;
47436             
47437             if (ct && ct.getLayout()) {
47438                 ct.on('afterlayout', function() {
47439                     this.fitColumns(true, true);
47440                     this.updateHeaders();
47441                     this.updateHeaderSortState();
47442                 }, this, {single: true});
47443             }
47444         } else if (this.forceFit) {
47445             this.fitColumns(true, false);
47446         } else if (this.grid.autoExpandColumn) {
47447             this.autoExpand(true);
47448         }
47449         
47450         this.grid.getGridEl().dom.innerHTML = this.renderUI();
47451         
47452         this.afterRenderUI();
47453     },
47454
47455     
47456     
47457     
47458     initData : function(newStore, newColModel) {
47459         var me = this;
47460         
47461         if (me.ds) {
47462             var oldStore = me.ds;
47463             
47464             oldStore.un('add', me.onAdd, me);
47465             oldStore.un('load', me.onLoad, me);
47466             oldStore.un('clear', me.onClear, me);
47467             oldStore.un('remove', me.onRemove, me);
47468             oldStore.un('update', me.onUpdate, me);
47469             oldStore.un('datachanged', me.onDataChange, me);
47470             
47471             if (oldStore !== newStore && oldStore.autoDestroy) {
47472                 oldStore.destroy();
47473             }
47474         }
47475         
47476         if (newStore) {
47477             newStore.on({
47478                 scope      : me,
47479                 load       : me.onLoad,
47480                 add        : me.onAdd,
47481                 remove     : me.onRemove,
47482                 update     : me.onUpdate,
47483                 clear      : me.onClear,
47484                 datachanged: me.onDataChange
47485             });
47486         }
47487         
47488         if (me.cm) {
47489             var oldColModel = me.cm;
47490             
47491             oldColModel.un('configchange', me.onColConfigChange, me);
47492             oldColModel.un('widthchange',  me.onColWidthChange, me);
47493             oldColModel.un('headerchange', me.onHeaderChange, me);
47494             oldColModel.un('hiddenchange', me.onHiddenChange, me);
47495             oldColModel.un('columnmoved',  me.onColumnMove, me);
47496         }
47497         
47498         if (newColModel) {
47499             delete me.lastViewWidth;
47500             
47501             newColModel.on({
47502                 scope       : me,
47503                 configchange: me.onColConfigChange,
47504                 widthchange : me.onColWidthChange,
47505                 headerchange: me.onHeaderChange,
47506                 hiddenchange: me.onHiddenChange,
47507                 columnmoved : me.onColumnMove
47508             });
47509         }
47510         
47511         me.ds = newStore;
47512         me.cm = newColModel;
47513     },
47514
47515     
47516     onDataChange : function(){
47517         this.refresh(true);
47518         this.updateHeaderSortState();
47519         this.syncFocusEl(0);
47520     },
47521
47522     
47523     onClear : function() {
47524         this.refresh();
47525         this.syncFocusEl(0);
47526     },
47527
47528     
47529     onUpdate : function(store, record) {
47530         this.refreshRow(record);
47531     },
47532
47533     
47534     onAdd : function(store, records, index) {
47535         this.insertRows(store, index, index + (records.length-1));
47536     },
47537
47538     
47539     onRemove : function(store, record, index, isUpdate) {
47540         if (isUpdate !== true) {
47541             this.fireEvent('beforerowremoved', this, index, record);
47542         }
47543         
47544         this.removeRow(index);
47545         
47546         if (isUpdate !== true) {
47547             this.processRows(index);
47548             this.applyEmptyText();
47549             this.fireEvent('rowremoved', this, index, record);
47550         }
47551     },
47552
47553     
47554     onLoad : function() {
47555         if (Ext.isGecko) {
47556             if (!this.scrollToTopTask) {
47557                 this.scrollToTopTask = new Ext.util.DelayedTask(this.scrollToTop, this);
47558             }
47559             this.scrollToTopTask.delay(1);
47560         } else {
47561             this.scrollToTop();
47562         }
47563     },
47564
47565     
47566     onColWidthChange : function(cm, col, width) {
47567         this.updateColumnWidth(col, width);
47568     },
47569
47570     
47571     onHeaderChange : function(cm, col, text) {
47572         this.updateHeaders();
47573     },
47574
47575     
47576     onHiddenChange : function(cm, col, hidden) {
47577         this.updateColumnHidden(col, hidden);
47578     },
47579
47580     
47581     onColumnMove : function(cm, oldIndex, newIndex) {
47582         this.indexMap = null;
47583         this.refresh(true);
47584         this.restoreScroll(this.getScrollState());
47585         
47586         this.afterMove(newIndex);
47587         this.grid.fireEvent('columnmove', oldIndex, newIndex);
47588     },
47589
47590     
47591     onColConfigChange : function() {
47592         delete this.lastViewWidth;
47593         this.indexMap = null;
47594         this.refresh(true);
47595     },
47596
47597     
47598     
47599     initUI : function(grid) {
47600         grid.on('headerclick', this.onHeaderClick, this);
47601     },
47602
47603     
47604     initEvents : Ext.emptyFn,
47605
47606     
47607     onHeaderClick : function(g, index) {
47608         if (this.headersDisabled || !this.cm.isSortable(index)) {
47609             return;
47610         }
47611         g.stopEditing(true);
47612         g.store.sort(this.cm.getDataIndex(index));
47613     },
47614
47615     
47616     onRowOver : function(e, target) {
47617         var row = this.findRowIndex(target);
47618         
47619         if (row !== false) {
47620             this.addRowClass(row, this.rowOverCls);
47621         }
47622     },
47623
47624     
47625     onRowOut : function(e, target) {
47626         var row = this.findRowIndex(target);
47627         
47628         if (row !== false && !e.within(this.getRow(row), true)) {
47629             this.removeRowClass(row, this.rowOverCls);
47630         }
47631     },
47632
47633     
47634     onRowSelect : function(row) {
47635         this.addRowClass(row, this.selectedRowClass);
47636     },
47637
47638     
47639     onRowDeselect : function(row) {
47640         this.removeRowClass(row, this.selectedRowClass);
47641     },
47642
47643     
47644     onCellSelect : function(row, col) {
47645         var cell = this.getCell(row, col);
47646         if (cell) {
47647             this.fly(cell).addClass('x-grid3-cell-selected');
47648         }
47649     },
47650
47651     
47652     onCellDeselect : function(row, col) {
47653         var cell = this.getCell(row, col);
47654         if (cell) {
47655             this.fly(cell).removeClass('x-grid3-cell-selected');
47656         }
47657     },
47658
47659     
47660     handleWheel : function(e) {
47661         e.stopPropagation();
47662     },
47663
47664     
47665     onColumnSplitterMoved : function(cellIndex, width) {
47666         this.userResized = true;
47667         this.grid.colModel.setColumnWidth(cellIndex, width, true);
47668
47669         if (this.forceFit) {
47670             this.fitColumns(true, false, cellIndex);
47671             this.updateAllColumnWidths();
47672         } else {
47673             this.updateColumnWidth(cellIndex, width);
47674             this.syncHeaderScroll();
47675         }
47676
47677         this.grid.fireEvent('columnresize', cellIndex, width);
47678     },
47679
47680     
47681     beforeColMenuShow : function() {
47682         var colModel = this.cm,
47683             colCount = colModel.getColumnCount(),
47684             colMenu  = this.colMenu,
47685             i;
47686
47687         colMenu.removeAll();
47688
47689         for (i = 0; i < colCount; i++) {
47690             if (colModel.config[i].hideable !== false) {
47691                 colMenu.add(new Ext.menu.CheckItem({
47692                     text       : colModel.getColumnHeader(i),
47693                     itemId     : 'col-' + colModel.getColumnId(i),
47694                     checked    : !colModel.isHidden(i),
47695                     disabled   : colModel.config[i].hideable === false,
47696                     hideOnClick: false
47697                 }));
47698             }
47699         }
47700     },
47701     
47702     
47703     handleHdMenuClick : function(item) {
47704         var store     = this.ds,
47705             dataIndex = this.cm.getDataIndex(this.hdCtxIndex);
47706
47707         switch (item.getItemId()) {
47708             case 'asc':
47709                 store.sort(dataIndex, 'ASC');
47710                 break;
47711             case 'desc':
47712                 store.sort(dataIndex, 'DESC');
47713                 break;
47714             default:
47715                 this.handleHdMenuClickDefault(item);
47716         }
47717         return true;
47718     },
47719     
47720     
47721     handleHdMenuClickDefault: function(item) {
47722         var colModel = this.cm,
47723             itemId   = item.getItemId(),
47724             index    = colModel.getIndexById(itemId.substr(4));
47725
47726         if (index != -1) {
47727             if (item.checked && colModel.getColumnsBy(this.isHideableColumn, this).length <= 1) {
47728                 this.onDenyColumnHide();
47729                 return;
47730             }
47731             colModel.setHidden(index, item.checked);
47732         }
47733     },
47734
47735     
47736     handleHdDown : function(e, target) {
47737         if (Ext.fly(target).hasClass('x-grid3-hd-btn')) {
47738             e.stopEvent();
47739             
47740             var colModel  = this.cm,
47741                 header    = this.findHeaderCell(target),
47742                 index     = this.getCellIndex(header),
47743                 sortable  = colModel.isSortable(index),
47744                 menu      = this.hmenu,
47745                 menuItems = menu.items,
47746                 menuCls   = this.headerMenuOpenCls;
47747             
47748             this.hdCtxIndex = index;
47749             
47750             Ext.fly(header).addClass(menuCls);
47751             menuItems.get('asc').setDisabled(!sortable);
47752             menuItems.get('desc').setDisabled(!sortable);
47753             
47754             menu.on('hide', function() {
47755                 Ext.fly(header).removeClass(menuCls);
47756             }, this, {single:true});
47757             
47758             menu.show(target, 'tl-bl?');
47759         }
47760     },
47761
47762     
47763     handleHdMove : function(e) {
47764         var header = this.findHeaderCell(this.activeHdRef);
47765         
47766         if (header && !this.headersDisabled) {
47767             var handleWidth  = this.splitHandleWidth || 5,
47768                 activeRegion = this.activeHdRegion,
47769                 headerStyle  = header.style,
47770                 colModel     = this.cm,
47771                 cursor       = '',
47772                 pageX        = e.getPageX();
47773                 
47774             if (this.grid.enableColumnResize !== false) {
47775                 var activeHeaderIndex = this.activeHdIndex,
47776                     previousVisible   = this.getPreviousVisible(activeHeaderIndex),
47777                     currentResizable  = colModel.isResizable(activeHeaderIndex),
47778                     previousResizable = previousVisible && colModel.isResizable(previousVisible),
47779                     inLeftResizer     = pageX - activeRegion.left <= handleWidth,
47780                     inRightResizer    = activeRegion.right - pageX <= (!this.activeHdBtn ? handleWidth : 2);
47781                 
47782                 if (inLeftResizer && previousResizable) {
47783                     cursor = Ext.isAir ? 'move' : Ext.isWebKit ? 'e-resize' : 'col-resize'; 
47784                 } else if (inRightResizer && currentResizable) {
47785                     cursor = Ext.isAir ? 'move' : Ext.isWebKit ? 'w-resize' : 'col-resize';
47786                 }
47787             }
47788             
47789             headerStyle.cursor = cursor;
47790         }
47791     },
47792     
47793     
47794     getPreviousVisible: function(index) {
47795         while (index > 0) {
47796             if (!this.cm.isHidden(index - 1)) {
47797                 return index;
47798             }
47799             index--;
47800         }
47801         return undefined;
47802     },
47803
47804     
47805     handleHdOver : function(e, target) {
47806         var header = this.findHeaderCell(target);
47807         
47808         if (header && !this.headersDisabled) {
47809             var fly = this.fly(header);
47810             
47811             this.activeHdRef = target;
47812             this.activeHdIndex = this.getCellIndex(header);
47813             this.activeHdRegion = fly.getRegion();
47814             
47815             if (!this.isMenuDisabled(this.activeHdIndex, fly)) {
47816                 fly.addClass('x-grid3-hd-over');
47817                 this.activeHdBtn = fly.child('.x-grid3-hd-btn');
47818                 
47819                 if (this.activeHdBtn) {
47820                     this.activeHdBtn.dom.style.height = (header.firstChild.offsetHeight - 1) + 'px';
47821                 }
47822             }
47823         }
47824     },
47825
47826     
47827     handleHdOut : function(e, target) {
47828         var header = this.findHeaderCell(target);
47829         
47830         if (header && (!Ext.isIE || !e.within(header, true))) {
47831             this.activeHdRef = null;
47832             this.fly(header).removeClass('x-grid3-hd-over');
47833             header.style.cursor = '';
47834         }
47835     },
47836     
47837     
47838     isMenuDisabled: function(cellIndex, el) {
47839         return this.cm.isMenuDisabled(cellIndex);
47840     },
47841
47842     
47843     hasRows : function() {
47844         var fc = this.mainBody.dom.firstChild;
47845         return fc && fc.nodeType == 1 && fc.className != 'x-grid-empty';
47846     },
47847     
47848     
47849     isHideableColumn : function(c) {
47850         return !c.hidden;
47851     },
47852
47853     
47854     bind : function(d, c) {
47855         this.initData(d, c);
47856     }
47857 });
47858
47859
47860
47861
47862 Ext.grid.GridView.SplitDragZone = Ext.extend(Ext.dd.DDProxy, {
47863
47864     constructor: function(grid, hd){
47865         this.grid = grid;
47866         this.view = grid.getView();
47867         this.marker = this.view.resizeMarker;
47868         this.proxy = this.view.resizeProxy;
47869         Ext.grid.GridView.SplitDragZone.superclass.constructor.call(this, hd,
47870             'gridSplitters' + this.grid.getGridEl().id, {
47871             dragElId : Ext.id(this.proxy.dom), resizeFrame:false
47872         });
47873         this.scroll = false;
47874         this.hw = this.view.splitHandleWidth || 5;
47875     },
47876
47877     b4StartDrag : function(x, y){
47878         this.dragHeadersDisabled = this.view.headersDisabled;
47879         this.view.headersDisabled = true;
47880         var h = this.view.mainWrap.getHeight();
47881         this.marker.setHeight(h);
47882         this.marker.show();
47883         this.marker.alignTo(this.view.getHeaderCell(this.cellIndex), 'tl-tl', [-2, 0]);
47884         this.proxy.setHeight(h);
47885         var w = this.cm.getColumnWidth(this.cellIndex),
47886             minw = Math.max(w-this.grid.minColumnWidth, 0);
47887         this.resetConstraints();
47888         this.setXConstraint(minw, 1000);
47889         this.setYConstraint(0, 0);
47890         this.minX = x - minw;
47891         this.maxX = x + 1000;
47892         this.startPos = x;
47893         Ext.dd.DDProxy.prototype.b4StartDrag.call(this, x, y);
47894     },
47895
47896     allowHeaderDrag : function(e){
47897         return true;
47898     },
47899
47900     handleMouseDown : function(e){
47901         var t = this.view.findHeaderCell(e.getTarget());
47902         if(t && this.allowHeaderDrag(e)){
47903             var xy = this.view.fly(t).getXY(), 
47904                 x = xy[0],
47905                 exy = e.getXY(), 
47906                 ex = exy[0],
47907                 w = t.offsetWidth, 
47908                 adjust = false;
47909                 
47910             if((ex - x) <= this.hw){
47911                 adjust = -1;
47912             }else if((x+w) - ex <= this.hw){
47913                 adjust = 0;
47914             }
47915             if(adjust !== false){
47916                 this.cm = this.grid.colModel;
47917                 var ci = this.view.getCellIndex(t);
47918                 if(adjust == -1){
47919                   if (ci + adjust < 0) {
47920                     return;
47921                   }
47922                     while(this.cm.isHidden(ci+adjust)){
47923                         --adjust;
47924                         if(ci+adjust < 0){
47925                             return;
47926                         }
47927                     }
47928                 }
47929                 this.cellIndex = ci+adjust;
47930                 this.split = t.dom;
47931                 if(this.cm.isResizable(this.cellIndex) && !this.cm.isFixed(this.cellIndex)){
47932                     Ext.grid.GridView.SplitDragZone.superclass.handleMouseDown.apply(this, arguments);
47933                 }
47934             }else if(this.view.columnDrag){
47935                 this.view.columnDrag.callHandleMouseDown(e);
47936             }
47937         }
47938     },
47939
47940     endDrag : function(e){
47941         this.marker.hide();
47942         var v = this.view,
47943             endX = Math.max(this.minX, e.getPageX()),
47944             diff = endX - this.startPos,
47945             disabled = this.dragHeadersDisabled;
47946             
47947         v.onColumnSplitterMoved(this.cellIndex, this.cm.getColumnWidth(this.cellIndex)+diff);
47948         setTimeout(function(){
47949             v.headersDisabled = disabled;
47950         }, 50);
47951     },
47952
47953     autoOffset : function(){
47954         this.setDelta(0,0);
47955     }
47956 });
47957
47958 Ext.grid.PivotGridView = Ext.extend(Ext.grid.GridView, {
47959     
47960     
47961     colHeaderCellCls: 'grid-hd-group-cell',
47962     
47963     
47964     title: '',
47965     
47966     
47967     
47968     
47969     getColumnHeaders: function() {
47970         return this.grid.topAxis.buildHeaders();;
47971     },
47972     
47973     
47974     getRowHeaders: function() {
47975         return this.grid.leftAxis.buildHeaders();
47976     },
47977     
47978     
47979     renderRows : function(startRow, endRow) {
47980         var grid          = this.grid,
47981             rows          = grid.extractData(),
47982             rowCount      = rows.length,
47983             templates     = this.templates,
47984             renderer      = grid.renderer,
47985             hasRenderer   = typeof renderer == 'function',
47986             getCellCls    = this.getCellCls,
47987             hasGetCellCls = typeof getCellCls == 'function',
47988             cellTemplate  = templates.cell,
47989             rowTemplate   = templates.row,
47990             rowBuffer     = [],
47991             meta          = {},
47992             tstyle        = 'width:' + this.getGridInnerWidth() + 'px;',
47993             colBuffer, column, i;
47994         
47995         startRow = startRow || 0;
47996         endRow   = Ext.isDefined(endRow) ? endRow : rowCount - 1;
47997         
47998         for (i = 0; i < rowCount; i++) {
47999             row = rows[i];
48000             colCount  = row.length;
48001             colBuffer = [];
48002             
48003             rowIndex = startRow + i;
48004
48005             
48006             for (j = 0; j < colCount; j++) {
48007                 cell = row[j];
48008
48009                 meta.css   = j === 0 ? 'x-grid3-cell-first ' : (j == (colCount - 1) ? 'x-grid3-cell-last ' : '');
48010                 meta.attr  = meta.cellAttr = '';
48011                 meta.value = cell;
48012
48013                 if (Ext.isEmpty(meta.value)) {
48014                     meta.value = '&#160;';
48015                 }
48016                 
48017                 if (hasRenderer) {
48018                     meta.value = renderer(meta.value);
48019                 }
48020                 
48021                 if (hasGetCellCls) {
48022                     meta.css += getCellCls(meta.value) + ' ';
48023                 }
48024
48025                 colBuffer[colBuffer.length] = cellTemplate.apply(meta);
48026             }
48027             
48028             rowBuffer[rowBuffer.length] = rowTemplate.apply({
48029                 tstyle: tstyle,
48030                 cols  : colCount,
48031                 cells : colBuffer.join(""),
48032                 alt   : ''
48033             });
48034         }
48035         
48036         return rowBuffer.join("");
48037     },
48038     
48039     
48040     masterTpl: new Ext.Template(
48041         '<div class="x-grid3 x-pivotgrid" hidefocus="true">',
48042             '<div class="x-grid3-viewport">',
48043                 '<div class="x-grid3-header">',
48044                     '<div class="x-grid3-header-title"><span>{title}</span></div>',
48045                     '<div class="x-grid3-header-inner">',
48046                         '<div class="x-grid3-header-offset" style="{ostyle}"></div>',
48047                     '</div>',
48048                     '<div class="x-clear"></div>',
48049                 '</div>',
48050                 '<div class="x-grid3-scroller">',
48051                     '<div class="x-grid3-row-headers"></div>',
48052                     '<div class="x-grid3-body" style="{bstyle}">{body}</div>',
48053                     '<a href="#" class="x-grid3-focus" tabIndex="-1"></a>',
48054                 '</div>',
48055             '</div>',
48056             '<div class="x-grid3-resize-marker">&#160;</div>',
48057             '<div class="x-grid3-resize-proxy">&#160;</div>',
48058         '</div>'
48059     ),
48060     
48061     
48062     initTemplates: function() {
48063         Ext.grid.PivotGridView.superclass.initTemplates.apply(this, arguments);
48064         
48065         var templates = this.templates || {};
48066         if (!templates.gcell) {
48067             templates.gcell = new Ext.XTemplate(
48068                 '<td class="x-grid3-hd x-grid3-gcell x-grid3-td-{id} ux-grid-hd-group-row-{row} ' + this.colHeaderCellCls + '" style="{style}">',
48069                     '<div {tooltip} class="x-grid3-hd-inner x-grid3-hd-{id}" unselectable="on" style="{istyle}">', 
48070                         this.grid.enableHdMenu ? '<a class="x-grid3-hd-btn" href="#"></a>' : '', '{value}',
48071                     '</div>',
48072                 '</td>'
48073             );
48074         }
48075         
48076         this.templates = templates;
48077         this.hrowRe = new RegExp("ux-grid-hd-group-row-(\\d+)", "");
48078     },
48079     
48080     
48081     initElements: function() {
48082         Ext.grid.PivotGridView.superclass.initElements.apply(this, arguments);
48083         
48084         
48085         this.rowHeadersEl = new Ext.Element(this.scroller.child('div.x-grid3-row-headers'));
48086         
48087         
48088         this.headerTitleEl = new Ext.Element(this.mainHd.child('div.x-grid3-header-title'));
48089     },
48090     
48091     
48092     getGridInnerWidth: function() {
48093         var previousWidth = Ext.grid.PivotGridView.superclass.getGridInnerWidth.apply(this, arguments);
48094         
48095         return previousWidth - this.getTotalRowHeaderWidth();
48096     },
48097     
48098     
48099     getTotalRowHeaderWidth: function() {
48100         var headers = this.getRowHeaders(),
48101             length  = headers.length,
48102             total   = 0,
48103             i;
48104         
48105         for (i = 0; i< length; i++) {
48106             total += headers[i].width;
48107         }
48108         
48109         return total;
48110     },
48111     
48112     
48113     getTotalColumnHeaderHeight: function() {
48114         return this.getColumnHeaders().length * 21;
48115     },
48116     
48117     
48118     renderUI : function() {
48119         var templates  = this.templates,
48120             innerWidth = this.getGridInnerWidth();
48121             
48122         return templates.master.apply({
48123             body  : templates.body.apply({rows:'&#160;'}),
48124             ostyle: 'width:' + innerWidth + 'px',
48125             bstyle: 'width:' + innerWidth + 'px'
48126         });
48127     },
48128     
48129     
48130     onLayout: function(width, height) {
48131         Ext.grid.PivotGridView.superclass.onLayout.apply(this, arguments);
48132         
48133         var width = this.getGridInnerWidth();
48134         
48135         this.resizeColumnHeaders(width);
48136         this.resizeAllRows(width);
48137     },
48138     
48139     
48140     refresh : function(headersToo) {
48141         this.fireEvent('beforerefresh', this);
48142         this.grid.stopEditing(true);
48143         
48144         var result = this.renderBody();
48145         this.mainBody.update(result).setWidth(this.getGridInnerWidth());
48146         if (headersToo === true) {
48147             this.updateHeaders();
48148             this.updateHeaderSortState();
48149         }
48150         this.processRows(0, true);
48151         this.layout();
48152         this.applyEmptyText();
48153         this.fireEvent('refresh', this);
48154     },
48155     
48156     
48157     renderHeaders: Ext.emptyFn,
48158     
48159     
48160     fitColumns: Ext.emptyFn,
48161     
48162     
48163     resizeColumnHeaders: function(width) {
48164         var topAxis = this.grid.topAxis;
48165         
48166         if (topAxis.rendered) {
48167             topAxis.el.setWidth(width);
48168         }
48169     },
48170     
48171     
48172     resizeRowHeaders: function() {
48173         var rowHeaderWidth = this.getTotalRowHeaderWidth(),
48174             marginStyle    = String.format("margin-left: {0}px;", rowHeaderWidth);
48175         
48176         this.rowHeadersEl.setWidth(rowHeaderWidth);
48177         this.mainBody.applyStyles(marginStyle);
48178         Ext.fly(this.innerHd).applyStyles(marginStyle);
48179         
48180         this.headerTitleEl.setWidth(rowHeaderWidth);
48181         this.headerTitleEl.setHeight(this.getTotalColumnHeaderHeight());
48182     },
48183     
48184     
48185     resizeAllRows: function(width) {
48186         var rows   = this.getRows(),
48187             length = rows.length,
48188             i;
48189         
48190         for (i = 0; i < length; i++) {
48191             Ext.fly(rows[i]).setWidth(width);
48192             Ext.fly(rows[i]).child('table').setWidth(width);
48193         }
48194     },
48195     
48196     
48197     updateHeaders: function() {
48198         this.renderGroupRowHeaders();
48199         this.renderGroupColumnHeaders();
48200     },
48201     
48202     
48203     renderGroupRowHeaders: function() {
48204         var leftAxis = this.grid.leftAxis;
48205         
48206         this.resizeRowHeaders();
48207         leftAxis.rendered = false;
48208         leftAxis.render(this.rowHeadersEl);
48209         
48210         this.setTitle(this.title);
48211     },
48212     
48213     
48214     setTitle: function(title) {
48215         this.headerTitleEl.child('span').dom.innerHTML = title;
48216     },
48217     
48218     
48219     renderGroupColumnHeaders: function() {
48220         var topAxis = this.grid.topAxis;
48221         
48222         topAxis.rendered = false;
48223         topAxis.render(this.innerHd.firstChild);
48224     },
48225     
48226     
48227     isMenuDisabled: function(cellIndex, el) {
48228         return true;
48229     }
48230 });
48231 Ext.grid.PivotAxis = Ext.extend(Ext.Component, {
48232     
48233     orientation: 'horizontal',
48234     
48235     
48236     defaultHeaderWidth: 80,
48237     
48238     
48239     paddingWidth: 7,
48240     
48241     
48242     setDimensions: function(dimensions) {
48243         this.dimensions = dimensions;
48244     },
48245     
48246     
48247     onRender: function(ct, position) {
48248         var rows = this.orientation == 'horizontal'
48249                  ? this.renderHorizontalRows()
48250                  : this.renderVerticalRows();
48251         
48252         this.el = Ext.DomHelper.overwrite(ct.dom, {tag: 'table', cn: rows}, true);
48253     },
48254     
48255     
48256     renderHorizontalRows: function() {
48257         var headers  = this.buildHeaders(),
48258             rowCount = headers.length,
48259             rows     = [],
48260             cells, cols, colCount, i, j;
48261         
48262         for (i = 0; i < rowCount; i++) {
48263             cells = [];
48264             cols  = headers[i].items;
48265             colCount = cols.length;
48266
48267             for (j = 0; j < colCount; j++) {
48268                 cells.push({
48269                     tag: 'td',
48270                     html: cols[j].header,
48271                     colspan: cols[j].span
48272                 });
48273             }
48274
48275             rows[i] = {
48276                 tag: 'tr',
48277                 cn: cells
48278             };
48279         }
48280         
48281         return rows;
48282     },
48283     
48284     
48285     renderVerticalRows: function() {
48286         var headers  = this.buildHeaders(),
48287             colCount = headers.length,
48288             rowCells = [],
48289             rows     = [],
48290             rowCount, col, row, colWidth, i, j;
48291         
48292         for (i = 0; i < colCount; i++) {
48293             col = headers[i];
48294             colWidth = col.width || 80;
48295             rowCount = col.items.length;
48296             
48297             for (j = 0; j < rowCount; j++) {
48298                 row = col.items[j];
48299                 
48300                 rowCells[row.start] = rowCells[row.start] || [];
48301                 rowCells[row.start].push({
48302                     tag    : 'td',
48303                     html   : row.header,
48304                     rowspan: row.span,
48305                     width  : Ext.isBorderBox ? colWidth : colWidth - this.paddingWidth
48306                 });
48307             }
48308         }
48309         
48310         rowCount = rowCells.length;
48311         for (i = 0; i < rowCount; i++) {
48312             rows[i] = {
48313                 tag: 'tr',
48314                 cn : rowCells[i]
48315             };
48316         }
48317         
48318         return rows;
48319     },
48320     
48321     
48322     getTuples: function() {
48323         var newStore = new Ext.data.Store({});
48324         
48325         newStore.data = this.store.data.clone();
48326         newStore.fields = this.store.fields;
48327         
48328         var sorters    = [],
48329             dimensions = this.dimensions,
48330             length     = dimensions.length,
48331             i;
48332         
48333         for (i = 0; i < length; i++) {
48334             sorters.push({
48335                 field    : dimensions[i].dataIndex,
48336                 direction: dimensions[i].direction || 'ASC'
48337             });
48338         }
48339         
48340         newStore.sort(sorters);
48341         
48342         var records = newStore.data.items,
48343             hashes  = [],
48344             tuples  = [],
48345             recData, hash, info, data, key;
48346         
48347         length = records.length;
48348         
48349         for (i = 0; i < length; i++) {
48350             info = this.getRecordInfo(records[i]);
48351             data = info.data;
48352             hash = "";
48353             
48354             for (key in data) {
48355                 hash += data[key] + '---';
48356             }
48357             
48358             if (hashes.indexOf(hash) == -1) {
48359                 hashes.push(hash);
48360                 tuples.push(info);
48361             }
48362         }
48363         
48364         newStore.destroy();
48365         
48366         return tuples;
48367     },
48368     
48369     
48370     getRecordInfo: function(record) {
48371         var dimensions = this.dimensions,
48372             length  = dimensions.length,
48373             data    = {},
48374             dimension, dataIndex, i;
48375         
48376         
48377         for (i = 0; i < length; i++) {
48378             dimension = dimensions[i];
48379             dataIndex = dimension.dataIndex;
48380             
48381             data[dataIndex] = record.get(dataIndex);
48382         }
48383         
48384         
48385         
48386         var createMatcherFunction = function(data) {
48387             return function(record) {
48388                 for (var dataIndex in data) {
48389                     if (record.get(dataIndex) != data[dataIndex]) {
48390                         return false;
48391                     }
48392                 }
48393                 
48394                 return true;
48395             };
48396         };
48397         
48398         return {
48399             data: data,
48400             matcher: createMatcherFunction(data)
48401         };
48402     },
48403     
48404     
48405     buildHeaders: function() {
48406         var tuples     = this.getTuples(),
48407             rowCount   = tuples.length,
48408             dimensions = this.dimensions,
48409             colCount   = dimensions.length,
48410             headers    = [],
48411             tuple, rows, currentHeader, previousHeader, span, start, isLast, changed, i, j;
48412         
48413         for (i = 0; i < colCount; i++) {
48414             dimension = dimensions[i];
48415             rows  = [];
48416             span  = 0;
48417             start = 0;
48418             
48419             for (j = 0; j < rowCount; j++) {
48420                 tuple  = tuples[j];
48421                 isLast = j == (rowCount - 1);
48422                 currentHeader = tuple.data[dimension.dataIndex];
48423                 
48424                 
48425                 changed = previousHeader != undefined && previousHeader != currentHeader;
48426                 if (i > 0 && j > 0) {
48427                     changed = changed || tuple.data[dimensions[i-1].dataIndex] != tuples[j-1].data[dimensions[i-1].dataIndex];
48428                 }
48429                 
48430                 if (changed) {                    
48431                     rows.push({
48432                         header: previousHeader,
48433                         span  : span,
48434                         start : start
48435                     });
48436                     
48437                     start += span;
48438                     span = 0;
48439                 }
48440                 
48441                 if (isLast) {
48442                     rows.push({
48443                         header: currentHeader,
48444                         span  : span + 1,
48445                         start : start
48446                     });
48447                     
48448                     start += span;
48449                     span = 0;
48450                 }
48451                 
48452                 previousHeader = currentHeader;
48453                 span++;
48454             }
48455             
48456             headers.push({
48457                 items: rows,
48458                 width: dimension.width || this.defaultHeaderWidth
48459             });
48460             
48461             previousHeader = undefined;
48462         }
48463         
48464         return headers;
48465     }
48466 });
48467
48468
48469 Ext.grid.HeaderDragZone = Ext.extend(Ext.dd.DragZone, {
48470     maxDragWidth: 120,
48471     
48472     constructor : function(grid, hd, hd2){
48473         this.grid = grid;
48474         this.view = grid.getView();
48475         this.ddGroup = "gridHeader" + this.grid.getGridEl().id;
48476         Ext.grid.HeaderDragZone.superclass.constructor.call(this, hd);
48477         if(hd2){
48478             this.setHandleElId(Ext.id(hd));
48479             this.setOuterHandleElId(Ext.id(hd2));
48480         }
48481         this.scroll = false;
48482     },
48483     
48484     getDragData : function(e){
48485         var t = Ext.lib.Event.getTarget(e),
48486             h = this.view.findHeaderCell(t);
48487         if(h){
48488             return {ddel: h.firstChild, header:h};
48489         }
48490         return false;
48491     },
48492
48493     onInitDrag : function(e){
48494         
48495         this.dragHeadersDisabled = this.view.headersDisabled;
48496         this.view.headersDisabled = true;
48497         var clone = this.dragData.ddel.cloneNode(true);
48498         clone.id = Ext.id();
48499         clone.style.width = Math.min(this.dragData.header.offsetWidth,this.maxDragWidth) + "px";
48500         this.proxy.update(clone);
48501         return true;
48502     },
48503
48504     afterValidDrop : function(){
48505         this.completeDrop();
48506     },
48507
48508     afterInvalidDrop : function(){
48509         this.completeDrop();
48510     },
48511     
48512     completeDrop: function(){
48513         var v = this.view,
48514             disabled = this.dragHeadersDisabled;
48515         setTimeout(function(){
48516             v.headersDisabled = disabled;
48517         }, 50);
48518     }
48519 });
48520
48521
48522
48523 Ext.grid.HeaderDropZone = Ext.extend(Ext.dd.DropZone, {
48524     proxyOffsets : [-4, -9],
48525     fly: Ext.Element.fly,
48526     
48527     constructor : function(grid, hd, hd2){
48528         this.grid = grid;
48529         this.view = grid.getView();
48530         
48531         this.proxyTop = Ext.DomHelper.append(document.body, {
48532             cls:"col-move-top", html:"&#160;"
48533         }, true);
48534         this.proxyBottom = Ext.DomHelper.append(document.body, {
48535             cls:"col-move-bottom", html:"&#160;"
48536         }, true);
48537         this.proxyTop.hide = this.proxyBottom.hide = function(){
48538             this.setLeftTop(-100,-100);
48539             this.setStyle("visibility", "hidden");
48540         };
48541         this.ddGroup = "gridHeader" + this.grid.getGridEl().id;
48542         
48543         
48544         Ext.grid.HeaderDropZone.superclass.constructor.call(this, grid.getGridEl().dom);
48545     },
48546
48547     getTargetFromEvent : function(e){
48548         var t = Ext.lib.Event.getTarget(e),
48549             cindex = this.view.findCellIndex(t);
48550         if(cindex !== false){
48551             return this.view.getHeaderCell(cindex);
48552         }
48553     },
48554
48555     nextVisible : function(h){
48556         var v = this.view, cm = this.grid.colModel;
48557         h = h.nextSibling;
48558         while(h){
48559             if(!cm.isHidden(v.getCellIndex(h))){
48560                 return h;
48561             }
48562             h = h.nextSibling;
48563         }
48564         return null;
48565     },
48566
48567     prevVisible : function(h){
48568         var v = this.view, cm = this.grid.colModel;
48569         h = h.prevSibling;
48570         while(h){
48571             if(!cm.isHidden(v.getCellIndex(h))){
48572                 return h;
48573             }
48574             h = h.prevSibling;
48575         }
48576         return null;
48577     },
48578
48579     positionIndicator : function(h, n, e){
48580         var x = Ext.lib.Event.getPageX(e),
48581             r = Ext.lib.Dom.getRegion(n.firstChild),
48582             px, 
48583             pt, 
48584             py = r.top + this.proxyOffsets[1];
48585         if((r.right - x) <= (r.right-r.left)/2){
48586             px = r.right+this.view.borderWidth;
48587             pt = "after";
48588         }else{
48589             px = r.left;
48590             pt = "before";
48591         }
48592
48593         if(this.grid.colModel.isFixed(this.view.getCellIndex(n))){
48594             return false;
48595         }
48596
48597         px +=  this.proxyOffsets[0];
48598         this.proxyTop.setLeftTop(px, py);
48599         this.proxyTop.show();
48600         if(!this.bottomOffset){
48601             this.bottomOffset = this.view.mainHd.getHeight();
48602         }
48603         this.proxyBottom.setLeftTop(px, py+this.proxyTop.dom.offsetHeight+this.bottomOffset);
48604         this.proxyBottom.show();
48605         return pt;
48606     },
48607
48608     onNodeEnter : function(n, dd, e, data){
48609         if(data.header != n){
48610             this.positionIndicator(data.header, n, e);
48611         }
48612     },
48613
48614     onNodeOver : function(n, dd, e, data){
48615         var result = false;
48616         if(data.header != n){
48617             result = this.positionIndicator(data.header, n, e);
48618         }
48619         if(!result){
48620             this.proxyTop.hide();
48621             this.proxyBottom.hide();
48622         }
48623         return result ? this.dropAllowed : this.dropNotAllowed;
48624     },
48625
48626     onNodeOut : function(n, dd, e, data){
48627         this.proxyTop.hide();
48628         this.proxyBottom.hide();
48629     },
48630
48631     onNodeDrop : function(n, dd, e, data){
48632         var h = data.header;
48633         if(h != n){
48634             var cm = this.grid.colModel,
48635                 x = Ext.lib.Event.getPageX(e),
48636                 r = Ext.lib.Dom.getRegion(n.firstChild),
48637                 pt = (r.right - x) <= ((r.right-r.left)/2) ? "after" : "before",
48638                 oldIndex = this.view.getCellIndex(h),
48639                 newIndex = this.view.getCellIndex(n);
48640             if(pt == "after"){
48641                 newIndex++;
48642             }
48643             if(oldIndex < newIndex){
48644                 newIndex--;
48645             }
48646             cm.moveColumn(oldIndex, newIndex);
48647             return true;
48648         }
48649         return false;
48650     }
48651 });
48652
48653 Ext.grid.GridView.ColumnDragZone = Ext.extend(Ext.grid.HeaderDragZone, {
48654     
48655     constructor : function(grid, hd){
48656         Ext.grid.GridView.ColumnDragZone.superclass.constructor.call(this, grid, hd, null);
48657         this.proxy.el.addClass('x-grid3-col-dd');
48658     },
48659     
48660     handleMouseDown : function(e){
48661     },
48662
48663     callHandleMouseDown : function(e){
48664         Ext.grid.GridView.ColumnDragZone.superclass.handleMouseDown.call(this, e);
48665     }
48666 });
48667
48668 Ext.grid.SplitDragZone = Ext.extend(Ext.dd.DDProxy, {
48669     fly: Ext.Element.fly,
48670     
48671     constructor : function(grid, hd, hd2){
48672         this.grid = grid;
48673         this.view = grid.getView();
48674         this.proxy = this.view.resizeProxy;
48675         Ext.grid.SplitDragZone.superclass.constructor.call(this, hd,
48676             "gridSplitters" + this.grid.getGridEl().id, {
48677             dragElId : Ext.id(this.proxy.dom), resizeFrame:false
48678         });
48679         this.setHandleElId(Ext.id(hd));
48680         this.setOuterHandleElId(Ext.id(hd2));
48681         this.scroll = false;
48682     },
48683
48684     b4StartDrag : function(x, y){
48685         this.view.headersDisabled = true;
48686         this.proxy.setHeight(this.view.mainWrap.getHeight());
48687         var w = this.cm.getColumnWidth(this.cellIndex);
48688         var minw = Math.max(w-this.grid.minColumnWidth, 0);
48689         this.resetConstraints();
48690         this.setXConstraint(minw, 1000);
48691         this.setYConstraint(0, 0);
48692         this.minX = x - minw;
48693         this.maxX = x + 1000;
48694         this.startPos = x;
48695         Ext.dd.DDProxy.prototype.b4StartDrag.call(this, x, y);
48696     },
48697
48698
48699     handleMouseDown : function(e){
48700         var ev = Ext.EventObject.setEvent(e);
48701         var t = this.fly(ev.getTarget());
48702         if(t.hasClass("x-grid-split")){
48703             this.cellIndex = this.view.getCellIndex(t.dom);
48704             this.split = t.dom;
48705             this.cm = this.grid.colModel;
48706             if(this.cm.isResizable(this.cellIndex) && !this.cm.isFixed(this.cellIndex)){
48707                 Ext.grid.SplitDragZone.superclass.handleMouseDown.apply(this, arguments);
48708             }
48709         }
48710     },
48711
48712     endDrag : function(e){
48713         this.view.headersDisabled = false;
48714         var endX = Math.max(this.minX, Ext.lib.Event.getPageX(e));
48715         var diff = endX - this.startPos;
48716         this.view.onColumnSplitterMoved(this.cellIndex, this.cm.getColumnWidth(this.cellIndex)+diff);
48717     },
48718
48719     autoOffset : function(){
48720         this.setDelta(0,0);
48721     }
48722 });
48723 Ext.grid.GridDragZone = function(grid, config){
48724     this.view = grid.getView();
48725     Ext.grid.GridDragZone.superclass.constructor.call(this, this.view.mainBody.dom, config);
48726     this.scroll = false;
48727     this.grid = grid;
48728     this.ddel = document.createElement('div');
48729     this.ddel.className = 'x-grid-dd-wrap';
48730 };
48731
48732 Ext.extend(Ext.grid.GridDragZone, Ext.dd.DragZone, {
48733     ddGroup : "GridDD",
48734
48735     
48736     getDragData : function(e){
48737         var t = Ext.lib.Event.getTarget(e);
48738         var rowIndex = this.view.findRowIndex(t);
48739         if(rowIndex !== false){
48740             var sm = this.grid.selModel;
48741             if(!sm.isSelected(rowIndex) || e.hasModifier()){
48742                 sm.handleMouseDown(this.grid, rowIndex, e);
48743             }
48744             return {grid: this.grid, ddel: this.ddel, rowIndex: rowIndex, selections:sm.getSelections()};
48745         }
48746         return false;
48747     },
48748
48749     
48750     onInitDrag : function(e){
48751         var data = this.dragData;
48752         this.ddel.innerHTML = this.grid.getDragDropText();
48753         this.proxy.update(this.ddel);
48754         
48755     },
48756
48757     
48758     afterRepair : function(){
48759         this.dragging = false;
48760     },
48761
48762     
48763     getRepairXY : function(e, data){
48764         return false;
48765     },
48766
48767     onEndDrag : function(data, e){
48768         
48769     },
48770
48771     onValidDrop : function(dd, e, id){
48772         
48773         this.hideProxy();
48774     },
48775
48776     beforeInvalidDrop : function(e, id){
48777
48778     }
48779 });
48780
48781 Ext.grid.ColumnModel = Ext.extend(Ext.util.Observable, {
48782     
48783     defaultWidth: 100,
48784
48785     
48786     defaultSortable: false,
48787
48788     
48789
48790     
48791
48792     constructor : function(config) {
48793         
48794             if (config.columns) {
48795                 Ext.apply(this, config);
48796                 this.setConfig(config.columns, true);
48797             } else {
48798                 this.setConfig(config, true);
48799             }
48800             
48801             this.addEvents(
48802                 
48803                 "widthchange",
48804                 
48805                 
48806                 "headerchange",
48807                 
48808                 
48809                 "hiddenchange",
48810                 
48811                 
48812                 "columnmoved",
48813                 
48814                 
48815                 "configchange"
48816             );
48817             
48818             Ext.grid.ColumnModel.superclass.constructor.call(this);
48819     },
48820
48821     
48822     getColumnId : function(index) {
48823         return this.config[index].id;
48824     },
48825
48826     getColumnAt : function(index) {
48827         return this.config[index];
48828     },
48829
48830     
48831     setConfig : function(config, initial) {
48832         var i, c, len;
48833         
48834         if (!initial) { 
48835             delete this.totalWidth;
48836             
48837             for (i = 0, len = this.config.length; i < len; i++) {
48838                 c = this.config[i];
48839                 
48840                 if (c.setEditor) {
48841                     
48842                     c.setEditor(null);
48843                 }
48844             }
48845         }
48846
48847         
48848         this.defaults = Ext.apply({
48849             width: this.defaultWidth,
48850             sortable: this.defaultSortable
48851         }, this.defaults);
48852
48853         this.config = config;
48854         this.lookup = {};
48855
48856         for (i = 0, len = config.length; i < len; i++) {
48857             c = Ext.applyIf(config[i], this.defaults);
48858             
48859             
48860             if (Ext.isEmpty(c.id)) {
48861                 c.id = i;
48862             }
48863             
48864             if (!c.isColumn) {
48865                 var Cls = Ext.grid.Column.types[c.xtype || 'gridcolumn'];
48866                 c = new Cls(c);
48867                 config[i] = c;
48868             }
48869             
48870             this.lookup[c.id] = c;
48871         }
48872         
48873         if (!initial) {
48874             this.fireEvent('configchange', this);
48875         }
48876     },
48877
48878     
48879     getColumnById : function(id) {
48880         return this.lookup[id];
48881     },
48882
48883     
48884     getIndexById : function(id) {
48885         for (var i = 0, len = this.config.length; i < len; i++) {
48886             if (this.config[i].id == id) {
48887                 return i;
48888             }
48889         }
48890         return -1;
48891     },
48892
48893     
48894     moveColumn : function(oldIndex, newIndex) {
48895         var config = this.config,
48896             c      = config[oldIndex];
48897             
48898         config.splice(oldIndex, 1);
48899         config.splice(newIndex, 0, c);
48900         this.dataMap = null;
48901         this.fireEvent("columnmoved", this, oldIndex, newIndex);
48902     },
48903
48904     
48905     getColumnCount : function(visibleOnly) {
48906         var length = this.config.length,
48907             c = 0,
48908             i;
48909         
48910         if (visibleOnly === true) {
48911             for (i = 0; i < length; i++) {
48912                 if (!this.isHidden(i)) {
48913                     c++;
48914                 }
48915             }
48916             
48917             return c;
48918         }
48919         
48920         return length;
48921     },
48922
48923     
48924     getColumnsBy : function(fn, scope) {
48925         var config = this.config,
48926             length = config.length,
48927             result = [],
48928             i, c;
48929             
48930         for (i = 0; i < length; i++){
48931             c = config[i];
48932             
48933             if (fn.call(scope || this, c, i) === true) {
48934                 result[result.length] = c;
48935             }
48936         }
48937         
48938         return result;
48939     },
48940
48941     
48942     isSortable : function(col) {
48943         return !!this.config[col].sortable;
48944     },
48945
48946     
48947     isMenuDisabled : function(col) {
48948         return !!this.config[col].menuDisabled;
48949     },
48950
48951     
48952     getRenderer : function(col) {
48953         return this.config[col].renderer || Ext.grid.ColumnModel.defaultRenderer;
48954     },
48955
48956     getRendererScope : function(col) {
48957         return this.config[col].scope;
48958     },
48959
48960     
48961     setRenderer : function(col, fn) {
48962         this.config[col].renderer = fn;
48963     },
48964
48965     
48966     getColumnWidth : function(col) {
48967         var width = this.config[col].width;
48968         if(typeof width != 'number'){
48969             width = this.defaultWidth;
48970         }
48971         return width;
48972     },
48973
48974     
48975     setColumnWidth : function(col, width, suppressEvent) {
48976         this.config[col].width = width;
48977         this.totalWidth = null;
48978         
48979         if (!suppressEvent) {
48980              this.fireEvent("widthchange", this, col, width);
48981         }
48982     },
48983
48984     
48985     getTotalWidth : function(includeHidden) {
48986         if (!this.totalWidth) {
48987             this.totalWidth = 0;
48988             for (var i = 0, len = this.config.length; i < len; i++) {
48989                 if (includeHidden || !this.isHidden(i)) {
48990                     this.totalWidth += this.getColumnWidth(i);
48991                 }
48992             }
48993         }
48994         return this.totalWidth;
48995     },
48996
48997     
48998     getColumnHeader : function(col) {
48999         return this.config[col].header;
49000     },
49001
49002     
49003     setColumnHeader : function(col, header) {
49004         this.config[col].header = header;
49005         this.fireEvent("headerchange", this, col, header);
49006     },
49007
49008     
49009     getColumnTooltip : function(col) {
49010             return this.config[col].tooltip;
49011     },
49012     
49013     setColumnTooltip : function(col, tooltip) {
49014             this.config[col].tooltip = tooltip;
49015     },
49016
49017     
49018     getDataIndex : function(col) {
49019         return this.config[col].dataIndex;
49020     },
49021
49022     
49023     setDataIndex : function(col, dataIndex) {
49024         this.config[col].dataIndex = dataIndex;
49025     },
49026
49027     
49028     findColumnIndex : function(dataIndex) {
49029         var c = this.config;
49030         for(var i = 0, len = c.length; i < len; i++){
49031             if(c[i].dataIndex == dataIndex){
49032                 return i;
49033             }
49034         }
49035         return -1;
49036     },
49037
49038     
49039     isCellEditable : function(colIndex, rowIndex) {
49040         var c = this.config[colIndex],
49041             ed = c.editable;
49042
49043         
49044         return !!(ed || (!Ext.isDefined(ed) && c.editor));
49045     },
49046
49047     
49048     getCellEditor : function(colIndex, rowIndex) {
49049         return this.config[colIndex].getCellEditor(rowIndex);
49050     },
49051
49052     
49053     setEditable : function(col, editable) {
49054         this.config[col].editable = editable;
49055     },
49056
49057     
49058     isHidden : function(colIndex) {
49059         return !!this.config[colIndex].hidden; 
49060     },
49061
49062     
49063     isFixed : function(colIndex) {
49064         return !!this.config[colIndex].fixed;
49065     },
49066
49067     
49068     isResizable : function(colIndex) {
49069         return colIndex >= 0 && this.config[colIndex].resizable !== false && this.config[colIndex].fixed !== true;
49070     },
49071     
49072     
49073     setHidden : function(colIndex, hidden) {
49074         var c = this.config[colIndex];
49075         if(c.hidden !== hidden){
49076             c.hidden = hidden;
49077             this.totalWidth = null;
49078             this.fireEvent("hiddenchange", this, colIndex, hidden);
49079         }
49080     },
49081
49082     
49083     setEditor : function(col, editor) {
49084         this.config[col].setEditor(editor);
49085     },
49086
49087     
49088     destroy : function() {
49089         var length = this.config.length,
49090             i = 0;
49091
49092         for (; i < length; i++){
49093             this.config[i].destroy(); 
49094         }
49095         delete this.config;
49096         delete this.lookup;
49097         this.purgeListeners();
49098     },
49099
49100     
49101     setState : function(col, state) {
49102         state = Ext.applyIf(state, this.defaults);
49103         Ext.apply(this.config[col], state);
49104     }
49105 });
49106
49107
49108 Ext.grid.ColumnModel.defaultRenderer = function(value) {
49109     if (typeof value == "string" && value.length < 1) {
49110         return "&#160;";
49111     }
49112     return value;
49113 };
49114 Ext.grid.AbstractSelectionModel = Ext.extend(Ext.util.Observable,  {
49115     
49116
49117     constructor : function(){
49118         this.locked = false;
49119         Ext.grid.AbstractSelectionModel.superclass.constructor.call(this);
49120     },
49121
49122     
49123     init : function(grid){
49124         this.grid = grid;
49125         if(this.lockOnInit){
49126             delete this.lockOnInit;
49127             this.locked = false;
49128             this.lock();
49129         }
49130         this.initEvents();
49131     },
49132
49133     
49134     lock : function(){
49135         if(!this.locked){
49136             this.locked = true;
49137             
49138             var g = this.grid;
49139             if(g){
49140                 g.getView().on({
49141                     scope: this,
49142                     beforerefresh: this.sortUnLock,
49143                     refresh: this.sortLock
49144                 });
49145             }else{
49146                 this.lockOnInit = true;
49147             }
49148         }
49149     },
49150
49151     
49152     sortLock : function() {
49153         this.locked = true;
49154     },
49155
49156     
49157     sortUnLock : function() {
49158         this.locked = false;
49159     },
49160
49161     
49162     unlock : function(){
49163         if(this.locked){
49164             this.locked = false;
49165             var g = this.grid,
49166                 gv;
49167                 
49168             
49169             if(g){
49170                 gv = g.getView();
49171                 gv.un('beforerefresh', this.sortUnLock, this);
49172                 gv.un('refresh', this.sortLock, this);    
49173             }else{
49174                 delete this.lockOnInit;
49175             }
49176         }
49177     },
49178
49179     
49180     isLocked : function(){
49181         return this.locked;
49182     },
49183
49184     destroy: function(){
49185         this.unlock();
49186         this.purgeListeners();
49187     }
49188 });
49189 Ext.grid.RowSelectionModel = Ext.extend(Ext.grid.AbstractSelectionModel,  {
49190     
49191     singleSelect : false,
49192     
49193     constructor : function(config){
49194         Ext.apply(this, config);
49195         this.selections = new Ext.util.MixedCollection(false, function(o){
49196             return o.id;
49197         });
49198
49199         this.last = false;
49200         this.lastActive = false;
49201
49202         this.addEvents(
49203                 
49204                 'selectionchange',
49205                 
49206                 'beforerowselect',
49207                 
49208                 'rowselect',
49209                 
49210                 'rowdeselect'
49211         );
49212         Ext.grid.RowSelectionModel.superclass.constructor.call(this);
49213     },
49214
49215     
49216     
49217     initEvents : function(){
49218
49219         if(!this.grid.enableDragDrop && !this.grid.enableDrag){
49220             this.grid.on('rowmousedown', this.handleMouseDown, this);
49221         }
49222
49223         this.rowNav = new Ext.KeyNav(this.grid.getGridEl(), {
49224             up: this.onKeyPress, 
49225             down: this.onKeyPress,
49226             scope: this
49227         });
49228
49229         this.grid.getView().on({
49230             scope: this,
49231             refresh: this.onRefresh,
49232             rowupdated: this.onRowUpdated,
49233             rowremoved: this.onRemove
49234         });
49235     },
49236     
49237     onKeyPress : function(e, name){
49238         var up = name == 'up',
49239             method = up ? 'selectPrevious' : 'selectNext',
49240             add = up ? -1 : 1,
49241             last;
49242         if(!e.shiftKey || this.singleSelect){
49243             this[method](false);
49244         }else if(this.last !== false && this.lastActive !== false){
49245             last = this.last;
49246             this.selectRange(this.last,  this.lastActive + add);
49247             this.grid.getView().focusRow(this.lastActive);
49248             if(last !== false){
49249                 this.last = last;
49250             }
49251         }else{
49252            this.selectFirstRow();
49253         }
49254     },
49255
49256     
49257     onRefresh : function(){
49258         var ds = this.grid.store,
49259             s = this.getSelections(),
49260             i = 0,
49261             len = s.length, 
49262             index;
49263             
49264         this.silent = true;
49265         this.clearSelections(true);
49266         for(; i < len; i++){
49267             r = s[i];
49268             if((index = ds.indexOfId(r.id)) != -1){
49269                 this.selectRow(index, true);
49270             }
49271         }
49272         if(s.length != this.selections.getCount()){
49273             this.fireEvent('selectionchange', this);
49274         }
49275         this.silent = false;
49276     },
49277
49278     
49279     onRemove : function(v, index, r){
49280         if(this.selections.remove(r) !== false){
49281             this.fireEvent('selectionchange', this);
49282         }
49283     },
49284
49285     
49286     onRowUpdated : function(v, index, r){
49287         if(this.isSelected(r)){
49288             v.onRowSelect(index);
49289         }
49290     },
49291
49292     
49293     selectRecords : function(records, keepExisting){
49294         if(!keepExisting){
49295             this.clearSelections();
49296         }
49297         var ds = this.grid.store,
49298             i = 0,
49299             len = records.length;
49300         for(; i < len; i++){
49301             this.selectRow(ds.indexOf(records[i]), true);
49302         }
49303     },
49304
49305     
49306     getCount : function(){
49307         return this.selections.length;
49308     },
49309
49310     
49311     selectFirstRow : function(){
49312         this.selectRow(0);
49313     },
49314
49315     
49316     selectLastRow : function(keepExisting){
49317         this.selectRow(this.grid.store.getCount() - 1, keepExisting);
49318     },
49319
49320     
49321     selectNext : function(keepExisting){
49322         if(this.hasNext()){
49323             this.selectRow(this.last+1, keepExisting);
49324             this.grid.getView().focusRow(this.last);
49325             return true;
49326         }
49327         return false;
49328     },
49329
49330     
49331     selectPrevious : function(keepExisting){
49332         if(this.hasPrevious()){
49333             this.selectRow(this.last-1, keepExisting);
49334             this.grid.getView().focusRow(this.last);
49335             return true;
49336         }
49337         return false;
49338     },
49339
49340     
49341     hasNext : function(){
49342         return this.last !== false && (this.last+1) < this.grid.store.getCount();
49343     },
49344
49345     
49346     hasPrevious : function(){
49347         return !!this.last;
49348     },
49349
49350
49351     
49352     getSelections : function(){
49353         return [].concat(this.selections.items);
49354     },
49355
49356     
49357     getSelected : function(){
49358         return this.selections.itemAt(0);
49359     },
49360
49361     
49362     each : function(fn, scope){
49363         var s = this.getSelections(),
49364             i = 0,
49365             len = s.length;
49366             
49367         for(; i < len; i++){
49368             if(fn.call(scope || this, s[i], i) === false){
49369                 return false;
49370             }
49371         }
49372         return true;
49373     },
49374
49375     
49376     clearSelections : function(fast){
49377         if(this.isLocked()){
49378             return;
49379         }
49380         if(fast !== true){
49381             var ds = this.grid.store,
49382                 s = this.selections;
49383             s.each(function(r){
49384                 this.deselectRow(ds.indexOfId(r.id));
49385             }, this);
49386             s.clear();
49387         }else{
49388             this.selections.clear();
49389         }
49390         this.last = false;
49391     },
49392
49393
49394     
49395     selectAll : function(){
49396         if(this.isLocked()){
49397             return;
49398         }
49399         this.selections.clear();
49400         for(var i = 0, len = this.grid.store.getCount(); i < len; i++){
49401             this.selectRow(i, true);
49402         }
49403     },
49404
49405     
49406     hasSelection : function(){
49407         return this.selections.length > 0;
49408     },
49409
49410     
49411     isSelected : function(index){
49412         var r = Ext.isNumber(index) ? this.grid.store.getAt(index) : index;
49413         return (r && this.selections.key(r.id) ? true : false);
49414     },
49415
49416     
49417     isIdSelected : function(id){
49418         return (this.selections.key(id) ? true : false);
49419     },
49420
49421     
49422     handleMouseDown : function(g, rowIndex, e){
49423         if(e.button !== 0 || this.isLocked()){
49424             return;
49425         }
49426         var view = this.grid.getView();
49427         if(e.shiftKey && !this.singleSelect && this.last !== false){
49428             var last = this.last;
49429             this.selectRange(last, rowIndex, e.ctrlKey);
49430             this.last = last; 
49431             view.focusRow(rowIndex);
49432         }else{
49433             var isSelected = this.isSelected(rowIndex);
49434             if(e.ctrlKey && isSelected){
49435                 this.deselectRow(rowIndex);
49436             }else if(!isSelected || this.getCount() > 1){
49437                 this.selectRow(rowIndex, e.ctrlKey || e.shiftKey);
49438                 view.focusRow(rowIndex);
49439             }
49440         }
49441     },
49442
49443     
49444     selectRows : function(rows, keepExisting){
49445         if(!keepExisting){
49446             this.clearSelections();
49447         }
49448         for(var i = 0, len = rows.length; i < len; i++){
49449             this.selectRow(rows[i], true);
49450         }
49451     },
49452
49453     
49454     selectRange : function(startRow, endRow, keepExisting){
49455         var i;
49456         if(this.isLocked()){
49457             return;
49458         }
49459         if(!keepExisting){
49460             this.clearSelections();
49461         }
49462         if(startRow <= endRow){
49463             for(i = startRow; i <= endRow; i++){
49464                 this.selectRow(i, true);
49465             }
49466         }else{
49467             for(i = startRow; i >= endRow; i--){
49468                 this.selectRow(i, true);
49469             }
49470         }
49471     },
49472
49473     
49474     deselectRange : function(startRow, endRow, preventViewNotify){
49475         if(this.isLocked()){
49476             return;
49477         }
49478         for(var i = startRow; i <= endRow; i++){
49479             this.deselectRow(i, preventViewNotify);
49480         }
49481     },
49482
49483     
49484     selectRow : function(index, keepExisting, preventViewNotify){
49485         if(this.isLocked() || (index < 0 || index >= this.grid.store.getCount()) || (keepExisting && this.isSelected(index))){
49486             return;
49487         }
49488         var r = this.grid.store.getAt(index);
49489         if(r && this.fireEvent('beforerowselect', this, index, keepExisting, r) !== false){
49490             if(!keepExisting || this.singleSelect){
49491                 this.clearSelections();
49492             }
49493             this.selections.add(r);
49494             this.last = this.lastActive = index;
49495             if(!preventViewNotify){
49496                 this.grid.getView().onRowSelect(index);
49497             }
49498             if(!this.silent){
49499                 this.fireEvent('rowselect', this, index, r);
49500                 this.fireEvent('selectionchange', this);
49501             }
49502         }
49503     },
49504
49505     
49506     deselectRow : function(index, preventViewNotify){
49507         if(this.isLocked()){
49508             return;
49509         }
49510         if(this.last == index){
49511             this.last = false;
49512         }
49513         if(this.lastActive == index){
49514             this.lastActive = false;
49515         }
49516         var r = this.grid.store.getAt(index);
49517         if(r){
49518             this.selections.remove(r);
49519             if(!preventViewNotify){
49520                 this.grid.getView().onRowDeselect(index);
49521             }
49522             this.fireEvent('rowdeselect', this, index, r);
49523             this.fireEvent('selectionchange', this);
49524         }
49525     },
49526
49527     
49528     acceptsNav : function(row, col, cm){
49529         return !cm.isHidden(col) && cm.isCellEditable(col, row);
49530     },
49531
49532     
49533     onEditorKey : function(field, e){
49534         var k = e.getKey(), 
49535             newCell, 
49536             g = this.grid, 
49537             last = g.lastEdit,
49538             ed = g.activeEditor,
49539             shift = e.shiftKey,
49540             ae, last, r, c;
49541             
49542         if(k == e.TAB){
49543             e.stopEvent();
49544             ed.completeEdit();
49545             if(shift){
49546                 newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
49547             }else{
49548                 newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
49549             }
49550         }else if(k == e.ENTER){
49551             if(this.moveEditorOnEnter !== false){
49552                 if(shift){
49553                     newCell = g.walkCells(last.row - 1, last.col, -1, this.acceptsNav, this);
49554                 }else{
49555                     newCell = g.walkCells(last.row + 1, last.col, 1, this.acceptsNav, this);
49556                 }
49557             }
49558         }
49559         if(newCell){
49560             r = newCell[0];
49561             c = newCell[1];
49562
49563             if(last.row != r){
49564                 this.selectRow(r); 
49565             }
49566
49567             if(g.isEditor && g.editing){ 
49568                 ae = g.activeEditor;
49569                 if(ae && ae.field.triggerBlur){
49570                     
49571                     ae.field.triggerBlur();
49572                 }
49573             }
49574             g.startEditing(r, c);
49575         }
49576     },
49577     
49578     destroy : function(){
49579         Ext.destroy(this.rowNav);
49580         this.rowNav = null;
49581         Ext.grid.RowSelectionModel.superclass.destroy.call(this);
49582     }
49583 });
49584 Ext.grid.Column = Ext.extend(Ext.util.Observable, {
49585     
49586     
49587     
49588     
49589     
49590     
49591     
49592     
49593     
49594     
49595     
49596     
49597     
49598     
49599     
49600     
49601     
49602     
49603     
49604     
49605     
49606     
49607
49608     
49609     isColumn : true,
49610
49611     constructor : function(config){
49612         Ext.apply(this, config);
49613
49614         if(Ext.isString(this.renderer)){
49615             this.renderer = Ext.util.Format[this.renderer];
49616         }else if(Ext.isObject(this.renderer)){
49617             this.scope = this.renderer.scope;
49618             this.renderer = this.renderer.fn;
49619         }
49620         if(!this.scope){
49621             this.scope = this;
49622         }
49623
49624         var ed = this.editor;
49625         delete this.editor;
49626         this.setEditor(ed);
49627         this.addEvents(
49628             
49629             'click',
49630             
49631             'contextmenu',
49632             
49633             'dblclick',
49634             
49635             'mousedown'
49636         );
49637         Ext.grid.Column.superclass.constructor.call(this);
49638     },
49639
49640     
49641     processEvent : function(name, e, grid, rowIndex, colIndex){
49642         return this.fireEvent(name, this, grid, rowIndex, e);
49643     },
49644
49645     
49646     destroy: function() {
49647         if(this.setEditor){
49648             this.setEditor(null);
49649         }
49650         this.purgeListeners();
49651     },
49652
49653     
49654     renderer : function(value){
49655         return value;
49656     },
49657
49658     
49659     getEditor: function(rowIndex){
49660         return this.editable !== false ? this.editor : null;
49661     },
49662
49663     
49664     setEditor : function(editor){
49665         var ed = this.editor;
49666         if(ed){
49667             if(ed.gridEditor){
49668                 ed.gridEditor.destroy();
49669                 delete ed.gridEditor;
49670             }else{
49671                 ed.destroy();
49672             }
49673         }
49674         this.editor = null;
49675         if(editor){
49676             
49677             if(!editor.isXType){
49678                 editor = Ext.create(editor, 'textfield');
49679             }
49680             this.editor = editor;
49681         }
49682     },
49683
49684     
49685     getCellEditor: function(rowIndex){
49686         var ed = this.getEditor(rowIndex);
49687         if(ed){
49688             if(!ed.startEdit){
49689                 if(!ed.gridEditor){
49690                     ed.gridEditor = new Ext.grid.GridEditor(ed);
49691                 }
49692                 ed = ed.gridEditor;
49693             }
49694         }
49695         return ed;
49696     }
49697 });
49698
49699
49700 Ext.grid.BooleanColumn = Ext.extend(Ext.grid.Column, {
49701     
49702     trueText: 'true',
49703     
49704     falseText: 'false',
49705     
49706     undefinedText: '&#160;',
49707
49708     constructor: function(cfg){
49709         Ext.grid.BooleanColumn.superclass.constructor.call(this, cfg);
49710         var t = this.trueText, f = this.falseText, u = this.undefinedText;
49711         this.renderer = function(v){
49712             if(v === undefined){
49713                 return u;
49714             }
49715             if(!v || v === 'false'){
49716                 return f;
49717             }
49718             return t;
49719         };
49720     }
49721 });
49722
49723
49724 Ext.grid.NumberColumn = Ext.extend(Ext.grid.Column, {
49725     
49726     format : '0,000.00',
49727     constructor: function(cfg){
49728         Ext.grid.NumberColumn.superclass.constructor.call(this, cfg);
49729         this.renderer = Ext.util.Format.numberRenderer(this.format);
49730     }
49731 });
49732
49733
49734 Ext.grid.DateColumn = Ext.extend(Ext.grid.Column, {
49735     
49736     format : 'm/d/Y',
49737     constructor: function(cfg){
49738         Ext.grid.DateColumn.superclass.constructor.call(this, cfg);
49739         this.renderer = Ext.util.Format.dateRenderer(this.format);
49740     }
49741 });
49742
49743
49744 Ext.grid.TemplateColumn = Ext.extend(Ext.grid.Column, {
49745     
49746     constructor: function(cfg){
49747         Ext.grid.TemplateColumn.superclass.constructor.call(this, cfg);
49748         var tpl = (!Ext.isPrimitive(this.tpl) && this.tpl.compile) ? this.tpl : new Ext.XTemplate(this.tpl);
49749         this.renderer = function(value, p, r){
49750             return tpl.apply(r.data);
49751         };
49752         this.tpl = tpl;
49753     }
49754 });
49755
49756
49757 Ext.grid.ActionColumn = Ext.extend(Ext.grid.Column, {
49758     
49759     
49760     
49761     
49762     
49763     
49764     
49765     
49766     header: '&#160;',
49767
49768     actionIdRe: /x-action-col-(\d+)/,
49769     
49770     
49771     altText: '',
49772
49773     constructor: function(cfg) {
49774         var me = this,
49775             items = cfg.items || (me.items = [me]),
49776             l = items.length,
49777             i,
49778             item;
49779
49780         Ext.grid.ActionColumn.superclass.constructor.call(me, cfg);
49781
49782
49783
49784         me.renderer = function(v, meta) {
49785
49786             v = Ext.isFunction(cfg.renderer) ? cfg.renderer.apply(this, arguments)||'' : '';
49787
49788             meta.css += ' x-action-col-cell';
49789             for (i = 0; i < l; i++) {
49790                 item = items[i];
49791                 v += '<img alt="' + me.altText + '" src="' + (item.icon || Ext.BLANK_IMAGE_URL) +
49792                     '" class="x-action-col-icon x-action-col-' + String(i) + ' ' + (item.iconCls || '') +
49793                     ' ' + (Ext.isFunction(item.getClass) ? item.getClass.apply(item.scope||this.scope||this, arguments) : '') + '"' +
49794                     ((item.tooltip) ? ' ext:qtip="' + item.tooltip + '"' : '') + ' />';
49795             }
49796             return v;
49797         };
49798     },
49799
49800     destroy: function() {
49801         delete this.items;
49802         delete this.renderer;
49803         return Ext.grid.ActionColumn.superclass.destroy.apply(this, arguments);
49804     },
49805
49806     
49807     processEvent : function(name, e, grid, rowIndex, colIndex){
49808         var m = e.getTarget().className.match(this.actionIdRe),
49809             item, fn;
49810         if (m && (item = this.items[parseInt(m[1], 10)])) {
49811             if (name == 'click') {
49812                 (fn = item.handler || this.handler) && fn.call(item.scope||this.scope||this, grid, rowIndex, colIndex, item, e);
49813             } else if ((name == 'mousedown') && (item.stopSelection !== false)) {
49814                 return false;
49815             }
49816         }
49817         return Ext.grid.ActionColumn.superclass.processEvent.apply(this, arguments);
49818     }
49819 });
49820
49821
49822 Ext.grid.Column.types = {
49823     gridcolumn : Ext.grid.Column,
49824     booleancolumn: Ext.grid.BooleanColumn,
49825     numbercolumn: Ext.grid.NumberColumn,
49826     datecolumn: Ext.grid.DateColumn,
49827     templatecolumn: Ext.grid.TemplateColumn,
49828     actioncolumn: Ext.grid.ActionColumn
49829 };
49830 Ext.grid.RowNumberer = Ext.extend(Object, {
49831     
49832     header: "",
49833     
49834     width: 23,
49835     
49836     sortable: false,
49837     
49838     constructor : function(config){
49839         Ext.apply(this, config);
49840         if(this.rowspan){
49841             this.renderer = this.renderer.createDelegate(this);
49842         }
49843     },
49844
49845     
49846     fixed:true,
49847     hideable: false,
49848     menuDisabled:true,
49849     dataIndex: '',
49850     id: 'numberer',
49851     rowspan: undefined,
49852
49853     
49854     renderer : function(v, p, record, rowIndex){
49855         if(this.rowspan){
49856             p.cellAttr = 'rowspan="'+this.rowspan+'"';
49857         }
49858         return rowIndex+1;
49859     }
49860 });
49861 Ext.grid.CheckboxSelectionModel = Ext.extend(Ext.grid.RowSelectionModel, {
49862
49863     
49864     
49865     header : '<div class="x-grid3-hd-checker">&#160;</div>',
49866     
49867     width : 20,
49868     
49869     sortable : false,
49870
49871     
49872     menuDisabled : true,
49873     fixed : true,
49874     hideable: false,
49875     dataIndex : '',
49876     id : 'checker',
49877     isColumn: true, 
49878
49879     constructor : function(){
49880         Ext.grid.CheckboxSelectionModel.superclass.constructor.apply(this, arguments);
49881         if(this.checkOnly){
49882             this.handleMouseDown = Ext.emptyFn;
49883         }
49884     },
49885
49886     
49887     initEvents : function(){
49888         Ext.grid.CheckboxSelectionModel.superclass.initEvents.call(this);
49889         this.grid.on('render', function(){
49890             Ext.fly(this.grid.getView().innerHd).on('mousedown', this.onHdMouseDown, this);
49891         }, this);
49892     },
49893
49894     
49895     processEvent : function(name, e, grid, rowIndex, colIndex){
49896         if (name == 'mousedown') {
49897             this.onMouseDown(e, e.getTarget());
49898             return false;
49899         } else {
49900             return Ext.grid.Column.prototype.processEvent.apply(this, arguments);
49901         }
49902     },
49903
49904     
49905     onMouseDown : function(e, t){
49906         if(e.button === 0 && t.className == 'x-grid3-row-checker'){ 
49907             e.stopEvent();
49908             var row = e.getTarget('.x-grid3-row');
49909             if(row){
49910                 var index = row.rowIndex;
49911                 if(this.isSelected(index)){
49912                     this.deselectRow(index);
49913                 }else{
49914                     this.selectRow(index, true);
49915                     this.grid.getView().focusRow(index);
49916                 }
49917             }
49918         }
49919     },
49920
49921     
49922     onHdMouseDown : function(e, t) {
49923         if(t.className == 'x-grid3-hd-checker'){
49924             e.stopEvent();
49925             var hd = Ext.fly(t.parentNode);
49926             var isChecked = hd.hasClass('x-grid3-hd-checker-on');
49927             if(isChecked){
49928                 hd.removeClass('x-grid3-hd-checker-on');
49929                 this.clearSelections();
49930             }else{
49931                 hd.addClass('x-grid3-hd-checker-on');
49932                 this.selectAll();
49933             }
49934         }
49935     },
49936
49937     
49938     renderer : function(v, p, record){
49939         return '<div class="x-grid3-row-checker">&#160;</div>';
49940     }
49941 });
49942 Ext.grid.CellSelectionModel = Ext.extend(Ext.grid.AbstractSelectionModel,  {
49943     
49944     constructor : function(config){
49945         Ext.apply(this, config);
49946
49947             this.selection = null;
49948         
49949             this.addEvents(
49950                 
49951                 "beforecellselect",
49952                 
49953                 "cellselect",
49954                 
49955                 "selectionchange"
49956             );
49957         
49958             Ext.grid.CellSelectionModel.superclass.constructor.call(this);
49959     },
49960
49961     
49962     initEvents : function(){
49963         this.grid.on('cellmousedown', this.handleMouseDown, this);
49964         this.grid.on(Ext.EventManager.getKeyEvent(), this.handleKeyDown, this);
49965         this.grid.getView().on({
49966             scope: this,
49967             refresh: this.onViewChange,
49968             rowupdated: this.onRowUpdated,
49969             beforerowremoved: this.clearSelections,
49970             beforerowsinserted: this.clearSelections
49971         });
49972         if(this.grid.isEditor){
49973             this.grid.on('beforeedit', this.beforeEdit,  this);
49974         }
49975     },
49976
49977         
49978     beforeEdit : function(e){
49979         this.select(e.row, e.column, false, true, e.record);
49980     },
49981
49982         
49983     onRowUpdated : function(v, index, r){
49984         if(this.selection && this.selection.record == r){
49985             v.onCellSelect(index, this.selection.cell[1]);
49986         }
49987     },
49988
49989         
49990     onViewChange : function(){
49991         this.clearSelections(true);
49992     },
49993
49994         
49995     getSelectedCell : function(){
49996         return this.selection ? this.selection.cell : null;
49997     },
49998
49999     
50000     clearSelections : function(preventNotify){
50001         var s = this.selection;
50002         if(s){
50003             if(preventNotify !== true){
50004                 this.grid.view.onCellDeselect(s.cell[0], s.cell[1]);
50005             }
50006             this.selection = null;
50007             this.fireEvent("selectionchange", this, null);
50008         }
50009     },
50010
50011     
50012     hasSelection : function(){
50013         return this.selection ? true : false;
50014     },
50015
50016     
50017     handleMouseDown : function(g, row, cell, e){
50018         if(e.button !== 0 || this.isLocked()){
50019             return;
50020         }
50021         this.select(row, cell);
50022     },
50023
50024     
50025     select : function(rowIndex, colIndex, preventViewNotify, preventFocus,  r){
50026         if(this.fireEvent("beforecellselect", this, rowIndex, colIndex) !== false){
50027             this.clearSelections();
50028             r = r || this.grid.store.getAt(rowIndex);
50029             this.selection = {
50030                 record : r,
50031                 cell : [rowIndex, colIndex]
50032             };
50033             if(!preventViewNotify){
50034                 var v = this.grid.getView();
50035                 v.onCellSelect(rowIndex, colIndex);
50036                 if(preventFocus !== true){
50037                     v.focusCell(rowIndex, colIndex);
50038                 }
50039             }
50040             this.fireEvent("cellselect", this, rowIndex, colIndex);
50041             this.fireEvent("selectionchange", this, this.selection);
50042         }
50043     },
50044
50045         
50046     isSelectable : function(rowIndex, colIndex, cm){
50047         return !cm.isHidden(colIndex);
50048     },
50049     
50050     
50051     onEditorKey: function(field, e){
50052         if(e.getKey() == e.TAB){
50053             this.handleKeyDown(e);
50054         }
50055     },
50056
50057     
50058     handleKeyDown : function(e){
50059         if(!e.isNavKeyPress()){
50060             return;
50061         }
50062         
50063         var k = e.getKey(),
50064             g = this.grid,
50065             s = this.selection,
50066             sm = this,
50067             walk = function(row, col, step){
50068                 return g.walkCells(
50069                     row,
50070                     col,
50071                     step,
50072                     g.isEditor && g.editing ? sm.acceptsNav : sm.isSelectable, 
50073                     sm
50074                 );
50075             },
50076             cell, newCell, r, c, ae;
50077
50078         switch(k){
50079             case e.ESC:
50080             case e.PAGE_UP:
50081             case e.PAGE_DOWN:
50082                 
50083                 break;
50084             default:
50085                 
50086                 e.stopEvent();
50087                 break;
50088         }
50089
50090         if(!s){
50091             cell = walk(0, 0, 1); 
50092             if(cell){
50093                 this.select(cell[0], cell[1]);
50094             }
50095             return;
50096         }
50097
50098         cell = s.cell;  
50099         r = cell[0];    
50100         c = cell[1];    
50101         
50102         switch(k){
50103             case e.TAB:
50104                 if(e.shiftKey){
50105                     newCell = walk(r, c - 1, -1);
50106                 }else{
50107                     newCell = walk(r, c + 1, 1);
50108                 }
50109                 break;
50110             case e.DOWN:
50111                 newCell = walk(r + 1, c, 1);
50112                 break;
50113             case e.UP:
50114                 newCell = walk(r - 1, c, -1);
50115                 break;
50116             case e.RIGHT:
50117                 newCell = walk(r, c + 1, 1);
50118                 break;
50119             case e.LEFT:
50120                 newCell = walk(r, c - 1, -1);
50121                 break;
50122             case e.ENTER:
50123                 if (g.isEditor && !g.editing) {
50124                     g.startEditing(r, c);
50125                     return;
50126                 }
50127                 break;
50128         }
50129
50130         if(newCell){
50131             
50132             r = newCell[0];
50133             c = newCell[1];
50134
50135             this.select(r, c); 
50136
50137             if(g.isEditor && g.editing){ 
50138                 ae = g.activeEditor;
50139                 if(ae && ae.field.triggerBlur){
50140                     
50141                     ae.field.triggerBlur();
50142                 }
50143                 g.startEditing(r, c);
50144             }
50145         }
50146     },
50147
50148     acceptsNav : function(row, col, cm){
50149         return !cm.isHidden(col) && cm.isCellEditable(col, row);
50150     }
50151 });
50152 Ext.grid.EditorGridPanel = Ext.extend(Ext.grid.GridPanel, {
50153     
50154     clicksToEdit: 2,
50155
50156     
50157     forceValidation: false,
50158
50159     
50160     isEditor : true,
50161     
50162     detectEdit: false,
50163
50164     
50165     autoEncode : false,
50166
50167     
50168     
50169     trackMouseOver: false, 
50170
50171     
50172     initComponent : function(){
50173         Ext.grid.EditorGridPanel.superclass.initComponent.call(this);
50174
50175         if(!this.selModel){
50176             
50177             this.selModel = new Ext.grid.CellSelectionModel();
50178         }
50179
50180         this.activeEditor = null;
50181
50182         this.addEvents(
50183             
50184             "beforeedit",
50185             
50186             "afteredit",
50187             
50188             "validateedit"
50189         );
50190     },
50191
50192     
50193     initEvents : function(){
50194         Ext.grid.EditorGridPanel.superclass.initEvents.call(this);
50195
50196         this.getGridEl().on('mousewheel', this.stopEditing.createDelegate(this, [true]), this);
50197         this.on('columnresize', this.stopEditing, this, [true]);
50198
50199         if(this.clicksToEdit == 1){
50200             this.on("cellclick", this.onCellDblClick, this);
50201         }else {
50202             var view = this.getView();
50203             if(this.clicksToEdit == 'auto' && view.mainBody){
50204                 view.mainBody.on('mousedown', this.onAutoEditClick, this);
50205             }
50206             this.on('celldblclick', this.onCellDblClick, this);
50207         }
50208     },
50209
50210     onResize : function(){
50211         Ext.grid.EditorGridPanel.superclass.onResize.apply(this, arguments);
50212         var ae = this.activeEditor;
50213         if(this.editing && ae){
50214             ae.realign(true);
50215         }
50216     },
50217
50218     
50219     onCellDblClick : function(g, row, col){
50220         this.startEditing(row, col);
50221     },
50222
50223     
50224     onAutoEditClick : function(e, t){
50225         if(e.button !== 0){
50226             return;
50227         }
50228         var row = this.view.findRowIndex(t),
50229             col = this.view.findCellIndex(t);
50230         if(row !== false && col !== false){
50231             this.stopEditing();
50232             if(this.selModel.getSelectedCell){ 
50233                 var sc = this.selModel.getSelectedCell();
50234                 if(sc && sc[0] === row && sc[1] === col){
50235                     this.startEditing(row, col);
50236                 }
50237             }else{
50238                 if(this.selModel.isSelected(row)){
50239                     this.startEditing(row, col);
50240                 }
50241             }
50242         }
50243     },
50244
50245     
50246     onEditComplete : function(ed, value, startValue){
50247         this.editing = false;
50248         this.lastActiveEditor = this.activeEditor;
50249         this.activeEditor = null;
50250
50251         var r = ed.record,
50252             field = this.colModel.getDataIndex(ed.col);
50253         value = this.postEditValue(value, startValue, r, field);
50254         if(this.forceValidation === true || String(value) !== String(startValue)){
50255             var e = {
50256                 grid: this,
50257                 record: r,
50258                 field: field,
50259                 originalValue: startValue,
50260                 value: value,
50261                 row: ed.row,
50262                 column: ed.col,
50263                 cancel:false
50264             };
50265             if(this.fireEvent("validateedit", e) !== false && !e.cancel && String(value) !== String(startValue)){
50266                 r.set(field, e.value);
50267                 delete e.cancel;
50268                 this.fireEvent("afteredit", e);
50269             }
50270         }
50271         this.view.focusCell(ed.row, ed.col);
50272     },
50273
50274     
50275     startEditing : function(row, col){
50276         this.stopEditing();
50277         if(this.colModel.isCellEditable(col, row)){
50278             this.view.ensureVisible(row, col, true);
50279             var r = this.store.getAt(row),
50280                 field = this.colModel.getDataIndex(col),
50281                 e = {
50282                     grid: this,
50283                     record: r,
50284                     field: field,
50285                     value: r.data[field],
50286                     row: row,
50287                     column: col,
50288                     cancel:false
50289                 };
50290             if(this.fireEvent("beforeedit", e) !== false && !e.cancel){
50291                 this.editing = true;
50292                 var ed = this.colModel.getCellEditor(col, row);
50293                 if(!ed){
50294                     return;
50295                 }
50296                 if(!ed.rendered){
50297                     ed.parentEl = this.view.getEditorParent(ed);
50298                     ed.on({
50299                         scope: this,
50300                         render: {
50301                             fn: function(c){
50302                                 c.field.focus(false, true);
50303                             },
50304                             single: true,
50305                             scope: this
50306                         },
50307                         specialkey: function(field, e){
50308                             this.getSelectionModel().onEditorKey(field, e);
50309                         },
50310                         complete: this.onEditComplete,
50311                         canceledit: this.stopEditing.createDelegate(this, [true])
50312                     });
50313                 }
50314                 Ext.apply(ed, {
50315                     row     : row,
50316                     col     : col,
50317                     record  : r
50318                 });
50319                 this.lastEdit = {
50320                     row: row,
50321                     col: col
50322                 };
50323                 this.activeEditor = ed;
50324                 
50325                 
50326                 ed.selectSameEditor = (this.activeEditor == this.lastActiveEditor);
50327                 var v = this.preEditValue(r, field);
50328                 ed.startEdit(this.view.getCell(row, col).firstChild, Ext.isDefined(v) ? v : '');
50329
50330                 
50331                 (function(){
50332                     delete ed.selectSameEditor;
50333                 }).defer(50);
50334             }
50335         }
50336     },
50337
50338     
50339     preEditValue : function(r, field){
50340         var value = r.data[field];
50341         return this.autoEncode && Ext.isString(value) ? Ext.util.Format.htmlDecode(value) : value;
50342     },
50343
50344     
50345     postEditValue : function(value, originalValue, r, field){
50346         return this.autoEncode && Ext.isString(value) ? Ext.util.Format.htmlEncode(value) : value;
50347     },
50348
50349     
50350     stopEditing : function(cancel){
50351         if(this.editing){
50352             
50353             var ae = this.lastActiveEditor = this.activeEditor;
50354             if(ae){
50355                 ae[cancel === true ? 'cancelEdit' : 'completeEdit']();
50356                 this.view.focusCell(ae.row, ae.col);
50357             }
50358             this.activeEditor = null;
50359         }
50360         this.editing = false;
50361     }
50362 });
50363 Ext.reg('editorgrid', Ext.grid.EditorGridPanel);
50364
50365 Ext.grid.GridEditor = function(field, config){
50366     Ext.grid.GridEditor.superclass.constructor.call(this, field, config);
50367     field.monitorTab = false;
50368 };
50369
50370 Ext.extend(Ext.grid.GridEditor, Ext.Editor, {
50371     alignment: "tl-tl",
50372     autoSize: "width",
50373     hideEl : false,
50374     cls: "x-small-editor x-grid-editor",
50375     shim:false,
50376     shadow:false
50377 });
50378 Ext.grid.PropertyRecord = Ext.data.Record.create([
50379     {name:'name',type:'string'}, 'value'
50380 ]);
50381
50382
50383 Ext.grid.PropertyStore = Ext.extend(Ext.util.Observable, {
50384     
50385     constructor : function(grid, source){
50386         this.grid = grid;
50387         this.store = new Ext.data.Store({
50388             recordType : Ext.grid.PropertyRecord
50389         });
50390         this.store.on('update', this.onUpdate,  this);
50391         if(source){
50392             this.setSource(source);
50393         }
50394         Ext.grid.PropertyStore.superclass.constructor.call(this);    
50395     },
50396     
50397     
50398     setSource : function(o){
50399         this.source = o;
50400         this.store.removeAll();
50401         var data = [];
50402         for(var k in o){
50403             if(this.isEditableValue(o[k])){
50404                 data.push(new Ext.grid.PropertyRecord({name: k, value: o[k]}, k));
50405             }
50406         }
50407         this.store.loadRecords({records: data}, {}, true);
50408     },
50409
50410     
50411     onUpdate : function(ds, record, type){
50412         if(type == Ext.data.Record.EDIT){
50413             var v = record.data.value;
50414             var oldValue = record.modified.value;
50415             if(this.grid.fireEvent('beforepropertychange', this.source, record.id, v, oldValue) !== false){
50416                 this.source[record.id] = v;
50417                 record.commit();
50418                 this.grid.fireEvent('propertychange', this.source, record.id, v, oldValue);
50419             }else{
50420                 record.reject();
50421             }
50422         }
50423     },
50424
50425     
50426     getProperty : function(row){
50427        return this.store.getAt(row);
50428     },
50429
50430     
50431     isEditableValue: function(val){
50432         return Ext.isPrimitive(val) || Ext.isDate(val);
50433     },
50434
50435     
50436     setValue : function(prop, value, create){
50437         var r = this.getRec(prop);
50438         if(r){
50439             r.set('value', value);
50440             this.source[prop] = value;
50441         }else if(create){
50442             
50443             this.source[prop] = value;
50444             r = new Ext.grid.PropertyRecord({name: prop, value: value}, prop);
50445             this.store.add(r);
50446
50447         }
50448     },
50449     
50450     
50451     remove : function(prop){
50452         var r = this.getRec(prop);
50453         if(r){
50454             this.store.remove(r);
50455             delete this.source[prop];
50456         }
50457     },
50458     
50459     
50460     getRec : function(prop){
50461         return this.store.getById(prop);
50462     },
50463
50464     
50465     getSource : function(){
50466         return this.source;
50467     }
50468 });
50469
50470
50471 Ext.grid.PropertyColumnModel = Ext.extend(Ext.grid.ColumnModel, {
50472     
50473     nameText : 'Name',
50474     valueText : 'Value',
50475     dateFormat : 'm/j/Y',
50476     trueText: 'true',
50477     falseText: 'false',
50478     
50479     constructor : function(grid, store){
50480         var g = Ext.grid,
50481                 f = Ext.form;
50482                 
50483             this.grid = grid;
50484             g.PropertyColumnModel.superclass.constructor.call(this, [
50485                 {header: this.nameText, width:50, sortable: true, dataIndex:'name', id: 'name', menuDisabled:true},
50486                 {header: this.valueText, width:50, resizable:false, dataIndex: 'value', id: 'value', menuDisabled:true}
50487             ]);
50488             this.store = store;
50489         
50490             var bfield = new f.Field({
50491                 autoCreate: {tag: 'select', children: [
50492                     {tag: 'option', value: 'true', html: this.trueText},
50493                     {tag: 'option', value: 'false', html: this.falseText}
50494                 ]},
50495                 getValue : function(){
50496                     return this.el.dom.value == 'true';
50497                 }
50498             });
50499             this.editors = {
50500                 'date' : new g.GridEditor(new f.DateField({selectOnFocus:true})),
50501                 'string' : new g.GridEditor(new f.TextField({selectOnFocus:true})),
50502                 'number' : new g.GridEditor(new f.NumberField({selectOnFocus:true, style:'text-align:left;'})),
50503                 'boolean' : new g.GridEditor(bfield, {
50504                     autoSize: 'both'
50505                 })
50506             };
50507             this.renderCellDelegate = this.renderCell.createDelegate(this);
50508             this.renderPropDelegate = this.renderProp.createDelegate(this);
50509     },
50510
50511     
50512     renderDate : function(dateVal){
50513         return dateVal.dateFormat(this.dateFormat);
50514     },
50515
50516     
50517     renderBool : function(bVal){
50518         return this[bVal ? 'trueText' : 'falseText'];
50519     },
50520
50521     
50522     isCellEditable : function(colIndex, rowIndex){
50523         return colIndex == 1;
50524     },
50525
50526     
50527     getRenderer : function(col){
50528         return col == 1 ?
50529             this.renderCellDelegate : this.renderPropDelegate;
50530     },
50531
50532     
50533     renderProp : function(v){
50534         return this.getPropertyName(v);
50535     },
50536
50537     
50538     renderCell : function(val, meta, rec){
50539         var renderer = this.grid.customRenderers[rec.get('name')];
50540         if(renderer){
50541             return renderer.apply(this, arguments);
50542         }
50543         var rv = val;
50544         if(Ext.isDate(val)){
50545             rv = this.renderDate(val);
50546         }else if(typeof val == 'boolean'){
50547             rv = this.renderBool(val);
50548         }
50549         return Ext.util.Format.htmlEncode(rv);
50550     },
50551
50552     
50553     getPropertyName : function(name){
50554         var pn = this.grid.propertyNames;
50555         return pn && pn[name] ? pn[name] : name;
50556     },
50557
50558     
50559     getCellEditor : function(colIndex, rowIndex){
50560         var p = this.store.getProperty(rowIndex),
50561             n = p.data.name, 
50562             val = p.data.value;
50563         if(this.grid.customEditors[n]){
50564             return this.grid.customEditors[n];
50565         }
50566         if(Ext.isDate(val)){
50567             return this.editors.date;
50568         }else if(typeof val == 'number'){
50569             return this.editors.number;
50570         }else if(typeof val == 'boolean'){
50571             return this.editors['boolean'];
50572         }else{
50573             return this.editors.string;
50574         }
50575     },
50576
50577     
50578     destroy : function(){
50579         Ext.grid.PropertyColumnModel.superclass.destroy.call(this);
50580         this.destroyEditors(this.editors);
50581         this.destroyEditors(this.grid.customEditors);
50582     },
50583     
50584     destroyEditors: function(editors){
50585         for(var ed in editors){
50586             Ext.destroy(editors[ed]);
50587         }
50588     }
50589 });
50590
50591
50592 Ext.grid.PropertyGrid = Ext.extend(Ext.grid.EditorGridPanel, {
50593     
50594     
50595     
50596     
50597     
50598
50599     
50600     enableColumnMove:false,
50601     stripeRows:false,
50602     trackMouseOver: false,
50603     clicksToEdit:1,
50604     enableHdMenu : false,
50605     viewConfig : {
50606         forceFit:true
50607     },
50608
50609     
50610     initComponent : function(){
50611         this.customRenderers = this.customRenderers || {};
50612         this.customEditors = this.customEditors || {};
50613         this.lastEditRow = null;
50614         var store = new Ext.grid.PropertyStore(this);
50615         this.propStore = store;
50616         var cm = new Ext.grid.PropertyColumnModel(this, store);
50617         store.store.sort('name', 'ASC');
50618         this.addEvents(
50619             
50620             'beforepropertychange',
50621             
50622             'propertychange'
50623         );
50624         this.cm = cm;
50625         this.ds = store.store;
50626         Ext.grid.PropertyGrid.superclass.initComponent.call(this);
50627
50628                 this.mon(this.selModel, 'beforecellselect', function(sm, rowIndex, colIndex){
50629             if(colIndex === 0){
50630                 this.startEditing.defer(200, this, [rowIndex, 1]);
50631                 return false;
50632             }
50633         }, this);
50634     },
50635
50636     
50637     onRender : function(){
50638         Ext.grid.PropertyGrid.superclass.onRender.apply(this, arguments);
50639
50640         this.getGridEl().addClass('x-props-grid');
50641     },
50642
50643     
50644     afterRender: function(){
50645         Ext.grid.PropertyGrid.superclass.afterRender.apply(this, arguments);
50646         if(this.source){
50647             this.setSource(this.source);
50648         }
50649     },
50650
50651     
50652     setSource : function(source){
50653         this.propStore.setSource(source);
50654     },
50655
50656     
50657     getSource : function(){
50658         return this.propStore.getSource();
50659     },
50660     
50661     
50662     setProperty : function(prop, value, create){
50663         this.propStore.setValue(prop, value, create);    
50664     },
50665     
50666     
50667     removeProperty : function(prop){
50668         this.propStore.remove(prop);
50669     }
50670
50671     
50672     
50673     
50674     
50675 });
50676 Ext.reg("propertygrid", Ext.grid.PropertyGrid);
50677
50678 Ext.grid.GroupingView = Ext.extend(Ext.grid.GridView, {
50679
50680     
50681     groupByText : 'Group By This Field',
50682     
50683     showGroupsText : 'Show in Groups',
50684     
50685     hideGroupedColumn : false,
50686     
50687     showGroupName : true,
50688     
50689     startCollapsed : false,
50690     
50691     enableGrouping : true,
50692     
50693     enableGroupingMenu : true,
50694     
50695     enableNoGroups : true,
50696     
50697     emptyGroupText : '(None)',
50698     
50699     ignoreAdd : false,
50700     
50701     groupTextTpl : '{text}',
50702
50703     
50704     groupMode: 'value',
50705
50706     
50707     
50708     
50709     cancelEditOnToggle: true,
50710
50711     
50712     initTemplates : function(){
50713         Ext.grid.GroupingView.superclass.initTemplates.call(this);
50714         this.state = {};
50715
50716         var sm = this.grid.getSelectionModel();
50717         sm.on(sm.selectRow ? 'beforerowselect' : 'beforecellselect',
50718                 this.onBeforeRowSelect, this);
50719
50720         if(!this.startGroup){
50721             this.startGroup = new Ext.XTemplate(
50722                 '<div id="{groupId}" class="x-grid-group {cls}">',
50723                     '<div id="{groupId}-hd" class="x-grid-group-hd" style="{style}"><div class="x-grid-group-title">', this.groupTextTpl ,'</div></div>',
50724                     '<div id="{groupId}-bd" class="x-grid-group-body">'
50725             );
50726         }
50727         this.startGroup.compile();
50728
50729         if (!this.endGroup) {
50730             this.endGroup = '</div></div>';
50731         }
50732     },
50733
50734     
50735     findGroup : function(el){
50736         return Ext.fly(el).up('.x-grid-group', this.mainBody.dom);
50737     },
50738
50739     
50740     getGroups : function(){
50741         return this.hasRows() ? this.mainBody.dom.childNodes : [];
50742     },
50743
50744     
50745     onAdd : function(ds, records, index) {
50746         if (this.canGroup() && !this.ignoreAdd) {
50747             var ss = this.getScrollState();
50748             this.fireEvent('beforerowsinserted', ds, index, index + (records.length-1));
50749             this.refresh();
50750             this.restoreScroll(ss);
50751             this.fireEvent('rowsinserted', ds, index, index + (records.length-1));
50752         } else if (!this.canGroup()) {
50753             Ext.grid.GroupingView.superclass.onAdd.apply(this, arguments);
50754         }
50755     },
50756
50757     
50758     onRemove : function(ds, record, index, isUpdate){
50759         Ext.grid.GroupingView.superclass.onRemove.apply(this, arguments);
50760         var g = document.getElementById(record._groupId);
50761         if(g && g.childNodes[1].childNodes.length < 1){
50762             Ext.removeNode(g);
50763         }
50764         this.applyEmptyText();
50765     },
50766
50767     
50768     refreshRow : function(record){
50769         if(this.ds.getCount()==1){
50770             this.refresh();
50771         }else{
50772             this.isUpdating = true;
50773             Ext.grid.GroupingView.superclass.refreshRow.apply(this, arguments);
50774             this.isUpdating = false;
50775         }
50776     },
50777
50778     
50779     beforeMenuShow : function(){
50780         var item, items = this.hmenu.items, disabled = this.cm.config[this.hdCtxIndex].groupable === false;
50781         if((item = items.get('groupBy'))){
50782             item.setDisabled(disabled);
50783         }
50784         if((item = items.get('showGroups'))){
50785             item.setDisabled(disabled);
50786             item.setChecked(this.canGroup(), true);
50787         }
50788     },
50789
50790     
50791     renderUI : function(){
50792         var markup = Ext.grid.GroupingView.superclass.renderUI.call(this);
50793
50794         if(this.enableGroupingMenu && this.hmenu){
50795             this.hmenu.add('-',{
50796                 itemId:'groupBy',
50797                 text: this.groupByText,
50798                 handler: this.onGroupByClick,
50799                 scope: this,
50800                 iconCls:'x-group-by-icon'
50801             });
50802             if(this.enableNoGroups){
50803                 this.hmenu.add({
50804                     itemId:'showGroups',
50805                     text: this.showGroupsText,
50806                     checked: true,
50807                     checkHandler: this.onShowGroupsClick,
50808                     scope: this
50809                 });
50810             }
50811             this.hmenu.on('beforeshow', this.beforeMenuShow, this);
50812         }
50813         return markup;
50814     },
50815
50816     processEvent: function(name, e){
50817         Ext.grid.GroupingView.superclass.processEvent.call(this, name, e);
50818         var hd = e.getTarget('.x-grid-group-hd', this.mainBody);
50819         if(hd){
50820             
50821             var field = this.getGroupField(),
50822                 prefix = this.getPrefix(field),
50823                 groupValue = hd.id.substring(prefix.length),
50824                 emptyRe = new RegExp('gp-' + Ext.escapeRe(field) + '--hd');
50825
50826             
50827             groupValue = groupValue.substr(0, groupValue.length - 3);
50828             
50829             
50830             if(groupValue || emptyRe.test(hd.id)){
50831                 this.grid.fireEvent('group' + name, this.grid, field, groupValue, e);
50832             }
50833             if(name == 'mousedown' && e.button == 0){
50834                 this.toggleGroup(hd.parentNode);
50835             }
50836         }
50837
50838     },
50839
50840     
50841     onGroupByClick : function(){
50842         this.enableGrouping = true;
50843         this.grid.store.groupBy(this.cm.getDataIndex(this.hdCtxIndex));
50844         this.grid.fireEvent('groupchange', this, this.grid.store.getGroupState());
50845         this.beforeMenuShow(); 
50846         this.refresh();
50847     },
50848
50849     
50850     onShowGroupsClick : function(mi, checked){
50851         this.enableGrouping = checked;
50852         if(checked){
50853             this.onGroupByClick();
50854         }else{
50855             this.grid.store.clearGrouping();
50856             this.grid.fireEvent('groupchange', this, null);
50857         }
50858     },
50859
50860     
50861     toggleRowIndex : function(rowIndex, expanded){
50862         if(!this.canGroup()){
50863             return;
50864         }
50865         var row = this.getRow(rowIndex);
50866         if(row){
50867             this.toggleGroup(this.findGroup(row), expanded);
50868         }
50869     },
50870
50871     
50872     toggleGroup : function(group, expanded){
50873         var gel = Ext.get(group);
50874         expanded = Ext.isDefined(expanded) ? expanded : gel.hasClass('x-grid-group-collapsed');
50875         if(this.state[gel.id] !== expanded){
50876             if (this.cancelEditOnToggle !== false) {
50877                 this.grid.stopEditing(true);
50878             }
50879             this.state[gel.id] = expanded;
50880             gel[expanded ? 'removeClass' : 'addClass']('x-grid-group-collapsed');
50881         }
50882     },
50883
50884     
50885     toggleAllGroups : function(expanded){
50886         var groups = this.getGroups();
50887         for(var i = 0, len = groups.length; i < len; i++){
50888             this.toggleGroup(groups[i], expanded);
50889         }
50890     },
50891
50892     
50893     expandAllGroups : function(){
50894         this.toggleAllGroups(true);
50895     },
50896
50897     
50898     collapseAllGroups : function(){
50899         this.toggleAllGroups(false);
50900     },
50901
50902     
50903     getGroup : function(v, r, groupRenderer, rowIndex, colIndex, ds){
50904         var column = this.cm.config[colIndex],
50905             g = groupRenderer ? groupRenderer.call(column.scope, v, {}, r, rowIndex, colIndex, ds) : String(v);
50906         if(g === '' || g === '&#160;'){
50907             g = column.emptyGroupText || this.emptyGroupText;
50908         }
50909         return g;
50910     },
50911
50912     
50913     getGroupField : function(){
50914         return this.grid.store.getGroupState();
50915     },
50916
50917     
50918     afterRender : function(){
50919         if(!this.ds || !this.cm){
50920             return;
50921         }
50922         Ext.grid.GroupingView.superclass.afterRender.call(this);
50923         if(this.grid.deferRowRender){
50924             this.updateGroupWidths();
50925         }
50926     },
50927     
50928     afterRenderUI: function () {
50929         Ext.grid.GroupingView.superclass.afterRenderUI.call(this);
50930
50931         if (this.enableGroupingMenu && this.hmenu) {
50932             this.hmenu.add('-',{
50933                 itemId:'groupBy',
50934                 text: this.groupByText,
50935                 handler: this.onGroupByClick,
50936                 scope: this,
50937                 iconCls:'x-group-by-icon'
50938             });
50939             
50940             if (this.enableNoGroups) {
50941                 this.hmenu.add({
50942                     itemId:'showGroups',
50943                     text: this.showGroupsText,
50944                     checked: true,
50945                     checkHandler: this.onShowGroupsClick,
50946                     scope: this
50947                 });
50948             }
50949             
50950             this.hmenu.on('beforeshow', this.beforeMenuShow, this);
50951         }
50952     },
50953
50954     
50955     renderRows : function(){
50956         var groupField = this.getGroupField();
50957         var eg = !!groupField;
50958         
50959         if(this.hideGroupedColumn) {
50960             var colIndex = this.cm.findColumnIndex(groupField),
50961                 hasLastGroupField = Ext.isDefined(this.lastGroupField);
50962             if(!eg && hasLastGroupField){
50963                 this.mainBody.update('');
50964                 this.cm.setHidden(this.cm.findColumnIndex(this.lastGroupField), false);
50965                 delete this.lastGroupField;
50966             }else if (eg && !hasLastGroupField){
50967                 this.lastGroupField = groupField;
50968                 this.cm.setHidden(colIndex, true);
50969             }else if (eg && hasLastGroupField && groupField !== this.lastGroupField) {
50970                 this.mainBody.update('');
50971                 var oldIndex = this.cm.findColumnIndex(this.lastGroupField);
50972                 this.cm.setHidden(oldIndex, false);
50973                 this.lastGroupField = groupField;
50974                 this.cm.setHidden(colIndex, true);
50975             }
50976         }
50977         return Ext.grid.GroupingView.superclass.renderRows.apply(
50978                     this, arguments);
50979     },
50980
50981     
50982     doRender : function(cs, rs, ds, startRow, colCount, stripe){
50983         if(rs.length < 1){
50984             return '';
50985         }
50986
50987         if(!this.canGroup() || this.isUpdating){
50988             return Ext.grid.GroupingView.superclass.doRender.apply(this, arguments);
50989         }
50990
50991         var groupField = this.getGroupField(),
50992             colIndex = this.cm.findColumnIndex(groupField),
50993             g,
50994             gstyle = 'width:' + this.getTotalWidth() + ';',
50995             cfg = this.cm.config[colIndex],
50996             groupRenderer = cfg.groupRenderer || cfg.renderer,
50997             prefix = this.showGroupName ? (cfg.groupName || cfg.header)+': ' : '',
50998             groups = [],
50999             curGroup, i, len, gid;
51000
51001         for(i = 0, len = rs.length; i < len; i++){
51002             var rowIndex = startRow + i,
51003                 r = rs[i],
51004                 gvalue = r.data[groupField];
51005
51006                 g = this.getGroup(gvalue, r, groupRenderer, rowIndex, colIndex, ds);
51007             if(!curGroup || curGroup.group != g){
51008                 gid = this.constructId(gvalue, groupField, colIndex);
51009                 
51010                 
51011                 this.state[gid] = !(Ext.isDefined(this.state[gid]) ? !this.state[gid] : this.startCollapsed);
51012                 curGroup = {
51013                     group: g,
51014                     gvalue: gvalue,
51015                     text: prefix + g,
51016                     groupId: gid,
51017                     startRow: rowIndex,
51018                     rs: [r],
51019                     cls: this.state[gid] ? '' : 'x-grid-group-collapsed',
51020                     style: gstyle
51021                 };
51022                 groups.push(curGroup);
51023             }else{
51024                 curGroup.rs.push(r);
51025             }
51026             r._groupId = gid;
51027         }
51028
51029         var buf = [];
51030         for(i = 0, len = groups.length; i < len; i++){
51031             g = groups[i];
51032             this.doGroupStart(buf, g, cs, ds, colCount);
51033             buf[buf.length] = Ext.grid.GroupingView.superclass.doRender.call(
51034                     this, cs, g.rs, ds, g.startRow, colCount, stripe);
51035
51036             this.doGroupEnd(buf, g, cs, ds, colCount);
51037         }
51038         return buf.join('');
51039     },
51040
51041     
51042     getGroupId : function(value){
51043         var field = this.getGroupField();
51044         return this.constructId(value, field, this.cm.findColumnIndex(field));
51045     },
51046
51047     
51048     constructId : function(value, field, idx){
51049         var cfg = this.cm.config[idx],
51050             groupRenderer = cfg.groupRenderer || cfg.renderer,
51051             val = (this.groupMode == 'value') ? value : this.getGroup(value, {data:{}}, groupRenderer, 0, idx, this.ds);
51052
51053         return this.getPrefix(field) + Ext.util.Format.htmlEncode(val);
51054     },
51055
51056     
51057     canGroup  : function(){
51058         return this.enableGrouping && !!this.getGroupField();
51059     },
51060
51061     
51062     getPrefix: function(field){
51063         return this.grid.getGridEl().id + '-gp-' + field + '-';
51064     },
51065
51066     
51067     doGroupStart : function(buf, g, cs, ds, colCount){
51068         buf[buf.length] = this.startGroup.apply(g);
51069     },
51070
51071     
51072     doGroupEnd : function(buf, g, cs, ds, colCount){
51073         buf[buf.length] = this.endGroup;
51074     },
51075
51076     
51077     getRows : function(){
51078         if(!this.canGroup()){
51079             return Ext.grid.GroupingView.superclass.getRows.call(this);
51080         }
51081         var r = [],
51082             gs = this.getGroups(),
51083             g,
51084             i = 0,
51085             len = gs.length,
51086             j,
51087             jlen;
51088         for(; i < len; ++i){
51089             g = gs[i].childNodes[1];
51090             if(g){
51091                 g = g.childNodes;
51092                 for(j = 0, jlen = g.length; j < jlen; ++j){
51093                     r[r.length] = g[j];
51094                 }
51095             }
51096         }
51097         return r;
51098     },
51099
51100     
51101     updateGroupWidths : function(){
51102         if(!this.canGroup() || !this.hasRows()){
51103             return;
51104         }
51105         var tw = Math.max(this.cm.getTotalWidth(), this.el.dom.offsetWidth-this.getScrollOffset()) +'px';
51106         var gs = this.getGroups();
51107         for(var i = 0, len = gs.length; i < len; i++){
51108             gs[i].firstChild.style.width = tw;
51109         }
51110     },
51111
51112     
51113     onColumnWidthUpdated : function(col, w, tw){
51114         Ext.grid.GroupingView.superclass.onColumnWidthUpdated.call(this, col, w, tw);
51115         this.updateGroupWidths();
51116     },
51117
51118     
51119     onAllColumnWidthsUpdated : function(ws, tw){
51120         Ext.grid.GroupingView.superclass.onAllColumnWidthsUpdated.call(this, ws, tw);
51121         this.updateGroupWidths();
51122     },
51123
51124     
51125     onColumnHiddenUpdated : function(col, hidden, tw){
51126         Ext.grid.GroupingView.superclass.onColumnHiddenUpdated.call(this, col, hidden, tw);
51127         this.updateGroupWidths();
51128     },
51129
51130     
51131     onLayout : function(){
51132         this.updateGroupWidths();
51133     },
51134
51135     
51136     onBeforeRowSelect : function(sm, rowIndex){
51137         this.toggleRowIndex(rowIndex, true);
51138     }
51139 });
51140
51141 Ext.grid.GroupingView.GROUP_ID = 1000;