Upgrade to ExtJS 3.1.0 - Released 12/16/2009
[extjs.git] / ext-all-debug.js
1 /*
2  * Ext JS Library 3.1.0
3  * Copyright(c) 2006-2009 Ext JS, LLC
4  * licensing@extjs.com
5  * http://www.extjs.com/license
6  */
7
8 Ext.DomHelper = function(){
9     var tempTableEl = null,
10         emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i,
11         tableRe = /^table|tbody|tr|td$/i,
12         pub,
13         
14         afterbegin = 'afterbegin',
15         afterend = 'afterend',
16         beforebegin = 'beforebegin',
17         beforeend = 'beforeend',
18         ts = '<table>',
19         te = '</table>',
20         tbs = ts+'<tbody>',
21         tbe = '</tbody>'+te,
22         trs = tbs + '<tr>',
23         tre = '</tr>'+tbe;
24
25     
26     function doInsert(el, o, returnElement, pos, sibling, append){
27         var newNode = pub.insertHtml(pos, Ext.getDom(el), createHtml(o));
28         return returnElement ? Ext.get(newNode, true) : newNode;
29     }
30
31     
32     function createHtml(o){
33         var b = '',
34             attr,
35             val,
36             key,
37             keyVal,
38             cn;
39
40         if(Ext.isString(o)){
41             b = o;
42         } else if (Ext.isArray(o)) {
43             for (var i=0; i < o.length; i++) {
44                 if(o[i]) {
45                     b += createHtml(o[i]);
46                 }
47             };
48         } else {
49             b += '<' + (o.tag = o.tag || 'div');
50             Ext.iterate(o, function(attr, val){
51                 if(!/tag|children|cn|html$/i.test(attr)){
52                     if (Ext.isObject(val)) {
53                         b += ' ' + attr + '="';
54                         Ext.iterate(val, function(key, keyVal){
55                             b += key + ':' + keyVal + ';';
56                         });
57                         b += '"';
58                     }else{
59                         b += ' ' + ({cls : 'class', htmlFor : 'for'}[attr] || attr) + '="' + val + '"';
60                     }
61                 }
62             });
63             
64             if (emptyTags.test(o.tag)) {
65                 b += '/>';
66             } else {
67                 b += '>';
68                 if ((cn = o.children || o.cn)) {
69                     b += createHtml(cn);
70                 } else if(o.html){
71                     b += o.html;
72                 }
73                 b += '</' + o.tag + '>';
74             }
75         }
76         return b;
77     }
78
79     function ieTable(depth, s, h, e){
80         tempTableEl.innerHTML = [s, h, e].join('');
81         var i = -1,
82             el = tempTableEl,
83             ns;
84         while(++i < depth){
85             el = el.firstChild;
86         }
87
88         if(ns = el.nextSibling){
89             var df = document.createDocumentFragment();
90             while(el){
91                 ns = el.nextSibling;
92                 df.appendChild(el);
93                 el = ns;
94             }
95             el = df;
96         }
97         return el;
98     }
99
100     
101     function insertIntoTable(tag, where, el, html) {
102         var node,
103             before;
104
105         tempTableEl = tempTableEl || document.createElement('div');
106
107         if(tag == 'td' && (where == afterbegin || where == beforeend) ||
108            !/td|tr|tbody/i.test(tag) && (where == beforebegin || where == afterend)) {
109             return;
110         }
111         before = where == beforebegin ? el :
112                  where == afterend ? el.nextSibling :
113                  where == afterbegin ? el.firstChild : null;
114
115         if (where == beforebegin || where == afterend) {
116             el = el.parentNode;
117         }
118
119         if (tag == 'td' || (tag == 'tr' && (where == beforeend || where == afterbegin))) {
120             node = ieTable(4, trs, html, tre);
121         } else if ((tag == 'tbody' && (where == beforeend || where == afterbegin)) ||
122                    (tag == 'tr' && (where == beforebegin || where == afterend))) {
123             node = ieTable(3, tbs, html, tbe);
124         } else {
125             node = ieTable(2, ts, html, te);
126         }
127         el.insertBefore(node, before);
128         return node;
129     }
130
131
132     pub = {
133         
134         markup : function(o){
135             return createHtml(o);
136         },
137         
138         
139         applyStyles : function(el, styles){
140             if(styles){
141                 var i = 0,
142                     len,
143                     style;
144
145                 el = Ext.fly(el);
146                 if(Ext.isFunction(styles)){
147                     styles = styles.call();
148                 }
149                 if(Ext.isString(styles)){
150                     styles = styles.trim().split(/\s*(?::|;)\s*/);
151                     for(len = styles.length; i < len;){
152                         el.setStyle(styles[i++], styles[i++]);
153                     }
154                 }else if (Ext.isObject(styles)){
155                     el.setStyle(styles);
156                 }
157             }
158         },
159
160         
161         insertHtml : function(where, el, html){
162             var hash = {},
163                 hashVal,
164                 setStart,
165                 range,
166                 frag,
167                 rangeEl,
168                 rs;
169
170             where = where.toLowerCase();
171             
172             hash[beforebegin] = ['BeforeBegin', 'previousSibling'];
173             hash[afterend] = ['AfterEnd', 'nextSibling'];
174
175             if (el.insertAdjacentHTML) {
176                 if(tableRe.test(el.tagName) && (rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html))){
177                     return rs;
178                 }
179                 
180                 hash[afterbegin] = ['AfterBegin', 'firstChild'];
181                 hash[beforeend] = ['BeforeEnd', 'lastChild'];
182                 if ((hashVal = hash[where])) {
183                     el.insertAdjacentHTML(hashVal[0], html);
184                     return el[hashVal[1]];
185                 }
186             } else {
187                 range = el.ownerDocument.createRange();
188                 setStart = 'setStart' + (/end/i.test(where) ? 'After' : 'Before');
189                 if (hash[where]) {
190                     range[setStart](el);
191                     frag = range.createContextualFragment(html);
192                     el.parentNode.insertBefore(frag, where == beforebegin ? el : el.nextSibling);
193                     return el[(where == beforebegin ? 'previous' : 'next') + 'Sibling'];
194                 } else {
195                     rangeEl = (where == afterbegin ? 'first' : 'last') + 'Child';
196                     if (el.firstChild) {
197                         range[setStart](el[rangeEl]);
198                         frag = range.createContextualFragment(html);
199                         if(where == afterbegin){
200                             el.insertBefore(frag, el.firstChild);
201                         }else{
202                             el.appendChild(frag);
203                         }
204                     } else {
205                         el.innerHTML = html;
206                     }
207                     return el[rangeEl];
208                 }
209             }
210             throw 'Illegal insertion point -> "' + where + '"';
211         },
212
213         
214         insertBefore : function(el, o, returnElement){
215             return doInsert(el, o, returnElement, beforebegin);
216         },
217
218         
219         insertAfter : function(el, o, returnElement){
220             return doInsert(el, o, returnElement, afterend, 'nextSibling');
221         },
222
223         
224         insertFirst : function(el, o, returnElement){
225             return doInsert(el, o, returnElement, afterbegin, 'firstChild');
226         },
227
228         
229         append : function(el, o, returnElement){
230             return doInsert(el, o, returnElement, beforeend, '', true);
231         },
232
233         
234         overwrite : function(el, o, returnElement){
235             el = Ext.getDom(el);
236             el.innerHTML = createHtml(o);
237             return returnElement ? Ext.get(el.firstChild) : el.firstChild;
238         },
239
240         createHtml : createHtml
241     };
242     return pub;
243 }();
244 Ext.apply(Ext.DomHelper,
245 function(){
246         var pub,
247                 afterbegin = 'afterbegin',
248         afterend = 'afterend',
249         beforebegin = 'beforebegin',
250         beforeend = 'beforeend';
251
252         
253     function doInsert(el, o, returnElement, pos, sibling, append){
254         el = Ext.getDom(el);
255         var newNode;
256         if (pub.useDom) {
257             newNode = createDom(o, null);
258             if (append) {
259                     el.appendChild(newNode);
260             } else {
261                         (sibling == 'firstChild' ? el : el.parentNode).insertBefore(newNode, el[sibling] || el);
262             }
263         } else {
264             newNode = Ext.DomHelper.insertHtml(pos, el, Ext.DomHelper.createHtml(o));
265         }
266         return returnElement ? Ext.get(newNode, true) : newNode;
267     }
268
269         
270     
271     function createDom(o, parentNode){
272         var el,
273                 doc = document,
274                 useSet,
275                 attr,
276                 val,
277                 cn;
278
279         if (Ext.isArray(o)) {                       
280             el = doc.createDocumentFragment(); 
281                 Ext.each(o, function(v) {
282                 createDom(v, el);
283             });
284         } else if (Ext.isString(o)) {         
285             el = doc.createTextNode(o);
286         } else {
287             el = doc.createElement( o.tag || 'div' );
288             useSet = !!el.setAttribute; 
289             Ext.iterate(o, function(attr, val){
290                 if(!/tag|children|cn|html|style/.test(attr)){
291                         if(attr == 'cls'){
292                             el.className = val;
293                         }else{
294                         if(useSet){
295                             el.setAttribute(attr, val);
296                         }else{
297                             el[attr] = val;
298                         }
299                         }
300                 }
301             });
302             Ext.DomHelper.applyStyles(el, o.style);
303
304             if ((cn = o.children || o.cn)) {
305                 createDom(cn, el);
306             } else if (o.html) {
307                 el.innerHTML = o.html;
308             }
309         }
310         if(parentNode){
311            parentNode.appendChild(el);
312         }
313         return el;
314     }
315
316         pub = {
317                 
318             createTemplate : function(o){
319                 var html = Ext.DomHelper.createHtml(o);
320                 return new Ext.Template(html);
321             },
322
323                 
324             useDom : false,
325
326             
327             insertBefore : function(el, o, returnElement){
328                 return doInsert(el, o, returnElement, beforebegin);
329             },
330
331             
332             insertAfter : function(el, o, returnElement){
333                 return doInsert(el, o, returnElement, afterend, 'nextSibling');
334             },
335
336             
337             insertFirst : function(el, o, returnElement){
338                 return doInsert(el, o, returnElement, afterbegin, 'firstChild');
339             },
340
341             
342             append: function(el, o, returnElement){
343             return doInsert(el, o, returnElement, beforeend, '', true);
344         },
345
346             
347         createDom: createDom
348         };
349         return pub;
350 }());
351 Ext.Template = function(html){
352     var me = this,
353         a = arguments,
354         buf = [];
355
356     if (Ext.isArray(html)) {
357         html = html.join("");
358     } else if (a.length > 1) {
359             Ext.each(a, function(v) {
360             if (Ext.isObject(v)) {
361                 Ext.apply(me, v);
362             } else {
363                 buf.push(v);
364             }
365         });
366         html = buf.join('');
367     }
368
369     
370     me.html = html;
371     
372     if (me.compiled) {
373         me.compile();
374     }
375 };
376 Ext.Template.prototype = {
377     
378     re : /\{([\w-]+)\}/g,
379     
380
381     
382     applyTemplate : function(values){
383                 var me = this;
384
385         return me.compiled ?
386                         me.compiled(values) :
387                                 me.html.replace(me.re, function(m, name){
388                                 return values[name] !== undefined ? values[name] : "";
389                         });
390         },
391
392     
393     set : function(html, compile){
394             var me = this;
395         me.html = html;
396         me.compiled = null;
397         return compile ? me.compile() : me;
398     },
399
400     
401     compile : function(){
402         var me = this,
403                 sep = Ext.isGecko ? "+" : ",";
404
405         function fn(m, name){                        
406                 name = "values['" + name + "']";
407                 return "'"+ sep + '(' + name + " == undefined ? '' : " + name + ')' + sep + "'";
408         }
409                 
410         eval("this.compiled = function(values){ return " + (Ext.isGecko ? "'" : "['") +
411              me.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
412              (Ext.isGecko ?  "';};" : "'].join('');};"));
413         return me;
414     },
415
416     
417     insertFirst: function(el, values, returnElement){
418         return this.doInsert('afterBegin', el, values, returnElement);
419     },
420
421     
422     insertBefore: function(el, values, returnElement){
423         return this.doInsert('beforeBegin', el, values, returnElement);
424     },
425
426     
427     insertAfter : function(el, values, returnElement){
428         return this.doInsert('afterEnd', el, values, returnElement);
429     },
430
431     
432     append : function(el, values, returnElement){
433         return this.doInsert('beforeEnd', el, values, returnElement);
434     },
435
436     doInsert : function(where, el, values, returnEl){
437         el = Ext.getDom(el);
438         var newNode = Ext.DomHelper.insertHtml(where, el, this.applyTemplate(values));
439         return returnEl ? Ext.get(newNode, true) : newNode;
440     },
441
442     
443     overwrite : function(el, values, returnElement){
444         el = Ext.getDom(el);
445         el.innerHTML = this.applyTemplate(values);
446         return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;
447     }
448 };
449
450 Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate;
451
452
453 Ext.Template.from = function(el, config){
454     el = Ext.getDom(el);
455     return new Ext.Template(el.value || el.innerHTML, config || '');
456 };
457 Ext.apply(Ext.Template.prototype, {
458     
459     disableFormats : false,                             
460     
461
462     
463     re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
464
465     
466     applyTemplate : function(values){
467                 var me = this,
468                         useF = me.disableFormats !== true,
469                 fm = Ext.util.Format, 
470                 tpl = me;           
471             
472         if(me.compiled){
473             return me.compiled(values);
474         }
475         function fn(m, name, format, args){
476             if (format && useF) {
477                 if (format.substr(0, 5) == "this.") {
478                     return tpl.call(format.substr(5), values[name], values);
479                 } else {
480                     if (args) {
481                         
482                         
483                         
484                         var re = /^\s*['"](.*)["']\s*$/;
485                         args = args.split(',');
486                         for(var i = 0, len = args.length; i < len; i++){
487                             args[i] = args[i].replace(re, "$1");
488                         }
489                         args = [values[name]].concat(args);
490                     } else {
491                         args = [values[name]];
492                     }
493                     return fm[format].apply(fm, args);
494                 }
495             } else {
496                 return values[name] !== undefined ? values[name] : "";
497             }
498         }
499         return me.html.replace(me.re, fn);
500     },
501                 
502     
503     compile : function(){
504         var me = this,
505                 fm = Ext.util.Format,
506                 useF = me.disableFormats !== true,
507                 sep = Ext.isGecko ? "+" : ",",
508                 body;
509         
510         function fn(m, name, format, args){
511             if(format && useF){
512                 args = args ? ',' + args : "";
513                 if(format.substr(0, 5) != "this."){
514                     format = "fm." + format + '(';
515                 }else{
516                     format = 'this.call("'+ format.substr(5) + '", ';
517                     args = ", values";
518                 }
519             }else{
520                 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
521             }
522             return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
523         }
524         
525         
526         if(Ext.isGecko){
527             body = "this.compiled = function(values){ return '" +
528                    me.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
529                     "';};";
530         }else{
531             body = ["this.compiled = function(values){ return ['"];
532             body.push(me.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn));
533             body.push("'].join('');};");
534             body = body.join('');
535         }
536         eval(body);
537         return me;
538     },
539     
540     
541     call : function(fnName, value, allValues){
542         return this[fnName](value, allValues);
543     }
544 });
545 Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate; 
546
547 Ext.DomQuery = function(){
548     var cache = {}, 
549         simpleCache = {}, 
550         valueCache = {},
551         nonSpace = /\S/,
552         trimRe = /^\s+|\s+$/g,
553         tplRe = /\{(\d+)\}/g,
554         modeRe = /^(\s?[\/>+~]\s?|\s|$)/,
555         tagTokenRe = /^(#)?([\w-\*]+)/,
556         nthRe = /(\d*)n\+?(\d*)/, 
557         nthRe2 = /\D/,
558         
559             
560             
561             isIE = window.ActiveXObject ? true : false,
562             key = 30803;
563             
564     
565         
566         eval("var batch = 30803;");     
567
568     function child(p, index){
569         var i = 0,
570                 n = p.firstChild;
571         while(n){
572             if(n.nodeType == 1){
573                if(++i == index){
574                    return n;
575                }
576             }
577             n = n.nextSibling;
578         }
579         return null;
580     };
581
582     function next(n){
583         while((n = n.nextSibling) && n.nodeType != 1);
584         return n;
585     };
586
587     function prev(n){
588         while((n = n.previousSibling) && n.nodeType != 1);
589         return n;
590     };
591
592     function children(d){
593         var n = d.firstChild, ni = -1,
594                 nx;
595             while(n){
596                 nx = n.nextSibling;
597                 if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
598                     d.removeChild(n);
599                 }else{
600                     n.nodeIndex = ++ni;
601                 }
602                 n = nx;
603             }
604             return this;
605         };
606
607     function byClassName(c, a, v){
608         if(!v){
609             return c;
610         }
611         var r = [], ri = -1, cn;
612         for(var i = 0, ci; ci = c[i]; i++){
613             if((' '+ci.className+' ').indexOf(v) != -1){
614                 r[++ri] = ci;
615             }
616         }
617         return r;
618     };
619
620     function attrValue(n, attr){
621         if(!n.tagName && typeof n.length != "undefined"){
622             n = n[0];
623         }
624         if(!n){
625             return null;
626         }
627         if(attr == "for"){
628             return n.htmlFor;
629         }
630         if(attr == "class" || attr == "className"){
631             return n.className;
632         }
633         return n.getAttribute(attr) || n[attr];
634
635     };
636
637     function getNodes(ns, mode, tagName){
638         var result = [], ri = -1, cs;
639         if(!ns){
640             return result;
641         }
642         tagName = tagName || "*";
643         if(typeof ns.getElementsByTagName != "undefined"){
644             ns = [ns];
645         }
646         if(!mode){
647             for(var i = 0, ni; ni = ns[i]; i++){
648                 cs = ni.getElementsByTagName(tagName);
649                 for(var j = 0, ci; ci = cs[j]; j++){
650                     result[++ri] = ci;
651                 }
652             }
653         }else if(mode == "/" || mode == ">"){
654             var utag = tagName.toUpperCase();
655             for(var i = 0, ni, cn; ni = ns[i]; i++){
656                 cn = ni.childNodes;
657                 for(var j = 0, cj; cj = cn[j]; j++){
658                     if(cj.nodeName == utag || cj.nodeName == tagName  || tagName == '*'){
659                         result[++ri] = cj;
660                     }
661                 }
662             }
663         }else if(mode == "+"){
664             var utag = tagName.toUpperCase();
665             for(var i = 0, n; n = ns[i]; i++){
666                 while((n = n.nextSibling) && n.nodeType != 1);
667                 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
668                     result[++ri] = n;
669                 }
670             }
671         }else if(mode == "~"){
672             var utag = tagName.toUpperCase();
673             for(var i = 0, n; n = ns[i]; i++){
674                 while((n = n.nextSibling)){
675                     if (n.nodeName == utag || n.nodeName == tagName || tagName == '*'){
676                         result[++ri] = n;
677                     }
678                 }
679             }
680         }
681         return result;
682     };
683
684     function concat(a, b){
685         if(b.slice){
686             return a.concat(b);
687         }
688         for(var i = 0, l = b.length; i < l; i++){
689             a[a.length] = b[i];
690         }
691         return a;
692     }
693
694     function byTag(cs, tagName){
695         if(cs.tagName || cs == document){
696             cs = [cs];
697         }
698         if(!tagName){
699             return cs;
700         }
701         var r = [], ri = -1;
702         tagName = tagName.toLowerCase();
703         for(var i = 0, ci; ci = cs[i]; i++){
704             if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
705                 r[++ri] = ci;
706             }
707         }
708         return r;
709     };
710
711     function byId(cs, attr, id){
712         if(cs.tagName || cs == document){
713             cs = [cs];
714         }
715         if(!id){
716             return cs;
717         }
718         var r = [], ri = -1;
719         for(var i = 0,ci; ci = cs[i]; i++){
720             if(ci && ci.id == id){
721                 r[++ri] = ci;
722                 return r;
723             }
724         }
725         return r;
726     };
727
728     function byAttribute(cs, attr, value, op, custom){
729         var r = [], 
730                 ri = -1, 
731                 st = custom=="{",
732                 f = Ext.DomQuery.operators[op];
733         for(var i = 0, ci; ci = cs[i]; i++){
734             if(ci.nodeType != 1){
735                 continue;
736             }
737             var a;
738             if(st){
739                 a = Ext.DomQuery.getStyle(ci, attr);
740             }
741             else if(attr == "class" || attr == "className"){
742                 a = ci.className;
743             }else if(attr == "for"){
744                 a = ci.htmlFor;
745             }else if(attr == "href"){
746                 a = ci.getAttribute("href", 2);
747             }else{
748                 a = ci.getAttribute(attr);
749             }
750             if((f && f(a, value)) || (!f && a)){
751                 r[++ri] = ci;
752             }
753         }
754         return r;
755     };
756
757     function byPseudo(cs, name, value){
758         return Ext.DomQuery.pseudos[name](cs, value);
759     };
760
761     function nodupIEXml(cs){
762         var d = ++key, 
763                 r;
764         cs[0].setAttribute("_nodup", d);
765         r = [cs[0]];
766         for(var i = 1, len = cs.length; i < len; i++){
767             var c = cs[i];
768             if(!c.getAttribute("_nodup") != d){
769                 c.setAttribute("_nodup", d);
770                 r[r.length] = c;
771             }
772         }
773         for(var i = 0, len = cs.length; i < len; i++){
774             cs[i].removeAttribute("_nodup");
775         }
776         return r;
777     }
778
779     function nodup(cs){
780         if(!cs){
781             return [];
782         }
783         var len = cs.length, c, i, r = cs, cj, ri = -1;
784         if(!len || typeof cs.nodeType != "undefined" || len == 1){
785             return cs;
786         }
787         if(isIE && typeof cs[0].selectSingleNode != "undefined"){
788             return nodupIEXml(cs);
789         }
790         var d = ++key;
791         cs[0]._nodup = d;
792         for(i = 1; c = cs[i]; i++){
793             if(c._nodup != d){
794                 c._nodup = d;
795             }else{
796                 r = [];
797                 for(var j = 0; j < i; j++){
798                     r[++ri] = cs[j];
799                 }
800                 for(j = i+1; cj = cs[j]; j++){
801                     if(cj._nodup != d){
802                         cj._nodup = d;
803                         r[++ri] = cj;
804                     }
805                 }
806                 return r;
807             }
808         }
809         return r;
810     }
811
812     function quickDiffIEXml(c1, c2){
813         var d = ++key,
814                 r = [];
815         for(var i = 0, len = c1.length; i < len; i++){
816             c1[i].setAttribute("_qdiff", d);
817         }        
818         for(var i = 0, len = c2.length; i < len; i++){
819             if(c2[i].getAttribute("_qdiff") != d){
820                 r[r.length] = c2[i];
821             }
822         }
823         for(var i = 0, len = c1.length; i < len; i++){
824            c1[i].removeAttribute("_qdiff");
825         }
826         return r;
827     }
828
829     function quickDiff(c1, c2){
830         var len1 = c1.length,
831                 d = ++key,
832                 r = [];
833         if(!len1){
834             return c2;
835         }
836         if(isIE && typeof c1[0].selectSingleNode != "undefined"){
837             return quickDiffIEXml(c1, c2);
838         }        
839         for(var i = 0; i < len1; i++){
840             c1[i]._qdiff = d;
841         }        
842         for(var i = 0, len = c2.length; i < len; i++){
843             if(c2[i]._qdiff != d){
844                 r[r.length] = c2[i];
845             }
846         }
847         return r;
848     }
849
850     function quickId(ns, mode, root, id){
851         if(ns == root){
852            var d = root.ownerDocument || root;
853            return d.getElementById(id);
854         }
855         ns = getNodes(ns, mode, "*");
856         return byId(ns, null, id);
857     }
858
859     return {
860         getStyle : function(el, name){
861             return Ext.fly(el).getStyle(name);
862         },
863         
864         compile : function(path, type){
865             type = type || "select";
866
867             var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"],
868                 q = path, mode, lq,
869                 tk = Ext.DomQuery.matchers,
870                 tklen = tk.length,
871                 mm,
872                 
873                 lmode = q.match(modeRe);
874             
875             if(lmode && lmode[1]){
876                 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
877                 q = q.replace(lmode[1], "");
878             }
879             
880             while(path.substr(0, 1)=="/"){
881                 path = path.substr(1);
882             }
883
884             while(q && lq != q){
885                 lq = q;
886                 var tm = q.match(tagTokenRe);
887                 if(type == "select"){
888                     if(tm){
889                         if(tm[1] == "#"){
890                             fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
891                         }else{
892                             fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
893                         }
894                         q = q.replace(tm[0], "");
895                     }else if(q.substr(0, 1) != '@'){
896                         fn[fn.length] = 'n = getNodes(n, mode, "*");';
897                     }
898                 }else{
899                     if(tm){
900                         if(tm[1] == "#"){
901                             fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
902                         }else{
903                             fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
904                         }
905                         q = q.replace(tm[0], "");
906                     }
907                 }
908                 while(!(mm = q.match(modeRe))){
909                     var matched = false;
910                     for(var j = 0; j < tklen; j++){
911                         var t = tk[j];
912                         var m = q.match(t.re);
913                         if(m){
914                             fn[fn.length] = t.select.replace(tplRe, function(x, i){
915                                                     return m[i];
916                                                 });
917                             q = q.replace(m[0], "");
918                             matched = true;
919                             break;
920                         }
921                     }
922                     
923                     if(!matched){
924                         throw 'Error parsing selector, parsing failed at "' + q + '"';
925                     }
926                 }
927                 if(mm[1]){
928                     fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';
929                     q = q.replace(mm[1], "");
930                 }
931             }
932             fn[fn.length] = "return nodup(n);\n}";
933             eval(fn.join(""));
934             return f;
935         },
936
937         
938         select : function(path, root, type){
939             if(!root || root == document){
940                 root = document;
941             }
942             if(typeof root == "string"){
943                 root = document.getElementById(root);
944             }
945             var paths = path.split(","),
946                 results = [];
947             for(var i = 0, len = paths.length; i < len; i++){
948                 var p = paths[i].replace(trimRe, "");
949                 if(!cache[p]){
950                     cache[p] = Ext.DomQuery.compile(p);
951                     if(!cache[p]){
952                         throw p + " is not a valid selector";
953                     }
954                 }
955                 var result = cache[p](root);
956                 if(result && result != document){
957                     results = results.concat(result);
958                 }
959             }
960             if(paths.length > 1){
961                 return nodup(results);
962             }
963             return results;
964         },
965
966         
967         selectNode : function(path, root){
968             return Ext.DomQuery.select(path, root)[0];
969         },
970
971         
972         selectValue : function(path, root, defaultValue){
973             path = path.replace(trimRe, "");
974             if(!valueCache[path]){
975                 valueCache[path] = Ext.DomQuery.compile(path, "select");
976             }
977             var n = valueCache[path](root), v;
978             n = n[0] ? n[0] : n;
979             
980             if (typeof n.normalize == 'function') n.normalize();
981             
982             v = (n && n.firstChild ? n.firstChild.nodeValue : null);
983             return ((v === null||v === undefined||v==='') ? defaultValue : v);
984         },
985
986         
987         selectNumber : function(path, root, defaultValue){
988             var v = Ext.DomQuery.selectValue(path, root, defaultValue || 0);
989             return parseFloat(v);
990         },
991
992         
993         is : function(el, ss){
994             if(typeof el == "string"){
995                 el = document.getElementById(el);
996             }
997             var isArray = Ext.isArray(el),
998                 result = Ext.DomQuery.filter(isArray ? el : [el], ss);
999             return isArray ? (result.length == el.length) : (result.length > 0);
1000         },
1001
1002         
1003         filter : function(els, ss, nonMatches){
1004             ss = ss.replace(trimRe, "");
1005             if(!simpleCache[ss]){
1006                 simpleCache[ss] = Ext.DomQuery.compile(ss, "simple");
1007             }
1008             var result = simpleCache[ss](els);
1009             return nonMatches ? quickDiff(result, els) : result;
1010         },
1011
1012         
1013         matchers : [{
1014                 re: /^\.([\w-]+)/,
1015                 select: 'n = byClassName(n, null, " {1} ");'
1016             }, {
1017                 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
1018                 select: 'n = byPseudo(n, "{1}", "{2}");'
1019             },{
1020                 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
1021                 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
1022             }, {
1023                 re: /^#([\w-]+)/,
1024                 select: 'n = byId(n, null, "{1}");'
1025             },{
1026                 re: /^@([\w-]+)/,
1027                 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
1028             }
1029         ],
1030
1031         
1032         operators : {
1033             "=" : function(a, v){
1034                 return a == v;
1035             },
1036             "!=" : function(a, v){
1037                 return a != v;
1038             },
1039             "^=" : function(a, v){
1040                 return a && a.substr(0, v.length) == v;
1041             },
1042             "$=" : function(a, v){
1043                 return a && a.substr(a.length-v.length) == v;
1044             },
1045             "*=" : function(a, v){
1046                 return a && a.indexOf(v) !== -1;
1047             },
1048             "%=" : function(a, v){
1049                 return (a % v) == 0;
1050             },
1051             "|=" : function(a, v){
1052                 return a && (a == v || a.substr(0, v.length+1) == v+'-');
1053             },
1054             "~=" : function(a, v){
1055                 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
1056             }
1057         },
1058
1059         
1060         pseudos : {
1061             "first-child" : function(c){
1062                 var r = [], ri = -1, n;
1063                 for(var i = 0, ci; ci = n = c[i]; i++){
1064                     while((n = n.previousSibling) && n.nodeType != 1);
1065                     if(!n){
1066                         r[++ri] = ci;
1067                     }
1068                 }
1069                 return r;
1070             },
1071
1072             "last-child" : function(c){
1073                 var r = [], ri = -1, n;
1074                 for(var i = 0, ci; ci = n = c[i]; i++){
1075                     while((n = n.nextSibling) && n.nodeType != 1);
1076                     if(!n){
1077                         r[++ri] = ci;
1078                     }
1079                 }
1080                 return r;
1081             },
1082
1083             "nth-child" : function(c, a) {
1084                 var r = [], ri = -1,
1085                         m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a),
1086                         f = (m[1] || 1) - 0, l = m[2] - 0;
1087                 for(var i = 0, n; n = c[i]; i++){
1088                     var pn = n.parentNode;
1089                     if (batch != pn._batch) {
1090                         var j = 0;
1091                         for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
1092                             if(cn.nodeType == 1){
1093                                cn.nodeIndex = ++j;
1094                             }
1095                         }
1096                         pn._batch = batch;
1097                     }
1098                     if (f == 1) {
1099                         if (l == 0 || n.nodeIndex == l){
1100                             r[++ri] = n;
1101                         }
1102                     } else if ((n.nodeIndex + l) % f == 0){
1103                         r[++ri] = n;
1104                     }
1105                 }
1106
1107                 return r;
1108             },
1109
1110             "only-child" : function(c){
1111                 var r = [], ri = -1;;
1112                 for(var i = 0, ci; ci = c[i]; i++){
1113                     if(!prev(ci) && !next(ci)){
1114                         r[++ri] = ci;
1115                     }
1116                 }
1117                 return r;
1118             },
1119
1120             "empty" : function(c){
1121                 var r = [], ri = -1;
1122                 for(var i = 0, ci; ci = c[i]; i++){
1123                     var cns = ci.childNodes, j = 0, cn, empty = true;
1124                     while(cn = cns[j]){
1125                         ++j;
1126                         if(cn.nodeType == 1 || cn.nodeType == 3){
1127                             empty = false;
1128                             break;
1129                         }
1130                     }
1131                     if(empty){
1132                         r[++ri] = ci;
1133                     }
1134                 }
1135                 return r;
1136             },
1137
1138             "contains" : function(c, v){
1139                 var r = [], ri = -1;
1140                 for(var i = 0, ci; ci = c[i]; i++){
1141                     if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
1142                         r[++ri] = ci;
1143                     }
1144                 }
1145                 return r;
1146             },
1147
1148             "nodeValue" : function(c, v){
1149                 var r = [], ri = -1;
1150                 for(var i = 0, ci; ci = c[i]; i++){
1151                     if(ci.firstChild && ci.firstChild.nodeValue == v){
1152                         r[++ri] = ci;
1153                     }
1154                 }
1155                 return r;
1156             },
1157
1158             "checked" : function(c){
1159                 var r = [], ri = -1;
1160                 for(var i = 0, ci; ci = c[i]; i++){
1161                     if(ci.checked == true){
1162                         r[++ri] = ci;
1163                     }
1164                 }
1165                 return r;
1166             },
1167
1168             "not" : function(c, ss){
1169                 return Ext.DomQuery.filter(c, ss, true);
1170             },
1171
1172             "any" : function(c, selectors){
1173                 var ss = selectors.split('|'),
1174                         r = [], ri = -1, s;
1175                 for(var i = 0, ci; ci = c[i]; i++){
1176                     for(var j = 0; s = ss[j]; j++){
1177                         if(Ext.DomQuery.is(ci, s)){
1178                             r[++ri] = ci;
1179                             break;
1180                         }
1181                     }
1182                 }
1183                 return r;
1184             },
1185
1186             "odd" : function(c){
1187                 return this["nth-child"](c, "odd");
1188             },
1189
1190             "even" : function(c){
1191                 return this["nth-child"](c, "even");
1192             },
1193
1194             "nth" : function(c, a){
1195                 return c[a-1] || [];
1196             },
1197
1198             "first" : function(c){
1199                 return c[0] || [];
1200             },
1201
1202             "last" : function(c){
1203                 return c[c.length-1] || [];
1204             },
1205
1206             "has" : function(c, ss){
1207                 var s = Ext.DomQuery.select,
1208                         r = [], ri = -1;
1209                 for(var i = 0, ci; ci = c[i]; i++){
1210                     if(s(ss, ci).length > 0){
1211                         r[++ri] = ci;
1212                     }
1213                 }
1214                 return r;
1215             },
1216
1217             "next" : function(c, ss){
1218                 var is = Ext.DomQuery.is,
1219                         r = [], ri = -1;
1220                 for(var i = 0, ci; ci = c[i]; i++){
1221                     var n = next(ci);
1222                     if(n && is(n, ss)){
1223                         r[++ri] = ci;
1224                     }
1225                 }
1226                 return r;
1227             },
1228
1229             "prev" : function(c, ss){
1230                 var is = Ext.DomQuery.is,
1231                         r = [], ri = -1;
1232                 for(var i = 0, ci; ci = c[i]; i++){
1233                     var n = prev(ci);
1234                     if(n && is(n, ss)){
1235                         r[++ri] = ci;
1236                     }
1237                 }
1238                 return r;
1239             }
1240         }
1241     };
1242 }();
1243
1244
1245 Ext.query = Ext.DomQuery.select;
1246
1247 Ext.util.DelayedTask = function(fn, scope, args){
1248     var me = this,
1249         id,     
1250         call = function(){
1251                 clearInterval(id);
1252                 id = null;
1253                 fn.apply(scope, args || []);
1254             };
1255             
1256     
1257     me.delay = function(delay, newFn, newScope, newArgs){
1258         me.cancel();
1259         fn = newFn || fn;
1260         scope = newScope || scope;
1261         args = newArgs || args;
1262         id = setInterval(call, delay);
1263     };
1264
1265     
1266     me.cancel = function(){
1267         if(id){
1268             clearInterval(id);
1269             id = null;
1270         }
1271     };
1272 };(function(){
1273
1274 var EXTUTIL = Ext.util,
1275     TOARRAY = Ext.toArray,
1276     EACH = Ext.each,
1277     ISOBJECT = Ext.isObject,
1278     TRUE = true,
1279     FALSE = false;
1280
1281 EXTUTIL.Observable = function(){
1282     
1283     var me = this, e = me.events;
1284     if(me.listeners){
1285         me.on(me.listeners);
1286         delete me.listeners;
1287     }
1288     me.events = e || {};
1289 };
1290
1291 EXTUTIL.Observable.prototype = {
1292     
1293     filterOptRe : /^(?:scope|delay|buffer|single)$/,
1294
1295     
1296     fireEvent : function(){
1297         var a = TOARRAY(arguments),
1298             ename = a[0].toLowerCase(),
1299             me = this,
1300             ret = TRUE,
1301             ce = me.events[ename],
1302             q,
1303             c;
1304         if (me.eventsSuspended === TRUE) {
1305             if (q = me.eventQueue) {
1306                 q.push(a);
1307             }
1308         }
1309         else if(ISOBJECT(ce) && ce.bubble){
1310             if(ce.fire.apply(ce, a.slice(1)) === FALSE) {
1311                 return FALSE;
1312             }
1313             c = me.getBubbleTarget && me.getBubbleTarget();
1314             if(c && c.enableBubble) {
1315                 if(!c.events[ename] || !Ext.isObject(c.events[ename]) || !c.events[ename].bubble) {
1316                     c.enableBubble(ename);
1317                 }
1318                 return c.fireEvent.apply(c, a);
1319             }
1320         }
1321         else {
1322             if (ISOBJECT(ce)) {
1323                 a.shift();
1324                 ret = ce.fire.apply(ce, a);
1325             }
1326         }
1327         return ret;
1328     },
1329
1330     
1331     addListener : function(eventName, fn, scope, o){
1332         var me = this,
1333             e,
1334             oe,
1335             isF,
1336         ce;
1337         if (ISOBJECT(eventName)) {
1338             o = eventName;
1339             for (e in o){
1340                 oe = o[e];
1341                 if (!me.filterOptRe.test(e)) {
1342                     me.addListener(e, oe.fn || oe, oe.scope || o.scope, oe.fn ? oe : o);
1343                 }
1344             }
1345         } else {
1346             eventName = eventName.toLowerCase();
1347             ce = me.events[eventName] || TRUE;
1348             if (Ext.isBoolean(ce)) {
1349                 me.events[eventName] = ce = new EXTUTIL.Event(me, eventName);
1350             }
1351             ce.addListener(fn, scope, ISOBJECT(o) ? o : {});
1352         }
1353     },
1354
1355     
1356     removeListener : function(eventName, fn, scope){
1357         var ce = this.events[eventName.toLowerCase()];
1358         if (ISOBJECT(ce)) {
1359             ce.removeListener(fn, scope);
1360         }
1361     },
1362
1363     
1364     purgeListeners : function(){
1365         var events = this.events,
1366             evt,
1367             key;
1368         for(key in events){
1369             evt = events[key];
1370             if(ISOBJECT(evt)){
1371                 evt.clearListeners();
1372             }
1373         }
1374     },
1375
1376     
1377     addEvents : function(o){
1378         var me = this;
1379         me.events = me.events || {};
1380         if (Ext.isString(o)) {
1381             var a = arguments,
1382                 i = a.length;
1383             while(i--) {
1384                 me.events[a[i]] = me.events[a[i]] || TRUE;
1385             }
1386         } else {
1387             Ext.applyIf(me.events, o);
1388         }
1389     },
1390
1391     
1392     hasListener : function(eventName){
1393         var e = this.events[eventName];
1394         return ISOBJECT(e) && e.listeners.length > 0;
1395     },
1396
1397     
1398     suspendEvents : function(queueSuspended){
1399         this.eventsSuspended = TRUE;
1400         if(queueSuspended && !this.eventQueue){
1401             this.eventQueue = [];
1402         }
1403     },
1404
1405     
1406     resumeEvents : function(){
1407         var me = this,
1408             queued = me.eventQueue || [];
1409         me.eventsSuspended = FALSE;
1410         delete me.eventQueue;
1411         EACH(queued, function(e) {
1412             me.fireEvent.apply(me, e);
1413         });
1414     }
1415 };
1416
1417 var OBSERVABLE = EXTUTIL.Observable.prototype;
1418
1419 OBSERVABLE.on = OBSERVABLE.addListener;
1420
1421 OBSERVABLE.un = OBSERVABLE.removeListener;
1422
1423
1424 EXTUTIL.Observable.releaseCapture = function(o){
1425     o.fireEvent = OBSERVABLE.fireEvent;
1426 };
1427
1428 function createTargeted(h, o, scope){
1429     return function(){
1430         if(o.target == arguments[0]){
1431             h.apply(scope, TOARRAY(arguments));
1432         }
1433     };
1434 };
1435
1436 function createBuffered(h, o, fn, scope){
1437     fn.task = new EXTUTIL.DelayedTask();
1438     return function(){
1439         fn.task.delay(o.buffer, h, scope, TOARRAY(arguments));
1440     };
1441 }
1442
1443 function createSingle(h, e, fn, scope){
1444     return function(){
1445         e.removeListener(fn, scope);
1446         return h.apply(scope, arguments);
1447     };
1448 }
1449
1450 function createDelayed(h, o, fn, scope){
1451     return function(){
1452         var task = new EXTUTIL.DelayedTask();
1453         if(!fn.tasks) {
1454             fn.tasks = [];
1455         }
1456         fn.tasks.push(task);
1457         task.delay(o.delay || 10, h, scope, TOARRAY(arguments));
1458     };
1459 };
1460
1461 EXTUTIL.Event = function(obj, name){
1462     this.name = name;
1463     this.obj = obj;
1464     this.listeners = [];
1465 };
1466
1467 EXTUTIL.Event.prototype = {
1468     addListener : function(fn, scope, options){
1469         var me = this,
1470             l;
1471         scope = scope || me.obj;
1472         if(!me.isListening(fn, scope)){
1473             l = me.createListener(fn, scope, options);
1474             if(me.firing){ 
1475                 me.listeners = me.listeners.slice(0);
1476             }
1477             me.listeners.push(l);
1478         }
1479     },
1480
1481     createListener: function(fn, scope, o){
1482         o = o || {}, scope = scope || this.obj;
1483         var l = {
1484             fn: fn,
1485             scope: scope,
1486             options: o
1487         }, h = fn;
1488         if(o.target){
1489             h = createTargeted(h, o, scope);
1490         }
1491         if(o.delay){
1492             h = createDelayed(h, o, fn, scope);
1493         }
1494         if(o.single){
1495             h = createSingle(h, this, fn, scope);
1496         }
1497         if(o.buffer){
1498             h = createBuffered(h, o, fn, scope);
1499         }
1500         l.fireFn = h;
1501         return l;
1502     },
1503
1504     findListener : function(fn, scope){
1505         var list = this.listeners,
1506             i = list.length,
1507             l,
1508             s;
1509         while(i--) {
1510             l = list[i];
1511             if(l) {
1512                 s = l.scope;
1513                 if(l.fn == fn && (s == scope || s == this.obj)){
1514                     return i;
1515                 }
1516             }
1517         }
1518         return -1;
1519     },
1520
1521     isListening : function(fn, scope){
1522         return this.findListener(fn, scope) != -1;
1523     },
1524
1525     removeListener : function(fn, scope){
1526         var index,
1527             l,
1528             k,
1529             me = this,
1530             ret = FALSE;
1531         if((index = me.findListener(fn, scope)) != -1){
1532             if (me.firing) {
1533                 me.listeners = me.listeners.slice(0);
1534             }
1535             l = me.listeners[index].fn;
1536             
1537             if(l.task) {
1538                 l.task.cancel();
1539                 delete l.task;
1540             }
1541             
1542             k = l.tasks && l.tasks.length;
1543             if(k) {
1544                 while(k--) {
1545                     l.tasks[k].cancel();
1546                 }
1547                 delete l.tasks;
1548             }
1549             me.listeners.splice(index, 1);
1550             ret = TRUE;
1551         }
1552         return ret;
1553     },
1554
1555     
1556     clearListeners : function(){
1557         var me = this,
1558             l = me.listeners,
1559             i = l.length;
1560         while(i--) {
1561             me.removeListener(l[i].fn, l[i].scope);
1562         }
1563     },
1564
1565     fire : function(){
1566         var me = this,
1567             args = TOARRAY(arguments),
1568             listeners = me.listeners,
1569             len = listeners.length,
1570             i = 0,
1571             l;
1572
1573         if(len > 0){
1574             me.firing = TRUE;
1575             for (; i < len; i++) {
1576                 l = listeners[i];
1577                 if(l && l.fireFn.apply(l.scope || me.obj || window, args) === FALSE) {
1578                     return (me.firing = FALSE);
1579                 }
1580             }
1581         }
1582         me.firing = FALSE;
1583         return TRUE;
1584     }
1585 };
1586 })();
1587 Ext.apply(Ext.util.Observable.prototype, function(){
1588     
1589     
1590     
1591     function getMethodEvent(method){
1592         var e = (this.methodEvents = this.methodEvents ||
1593         {})[method], returnValue, v, cancel, obj = this;
1594
1595         if (!e) {
1596             this.methodEvents[method] = e = {};
1597             e.originalFn = this[method];
1598             e.methodName = method;
1599             e.before = [];
1600             e.after = [];
1601
1602             var makeCall = function(fn, scope, args){
1603                 if (!Ext.isEmpty(v = fn.apply(scope || obj, args))) {
1604                     if (Ext.isObject(v)) {
1605                         returnValue = !Ext.isEmpty(v.returnValue) ? v.returnValue : v;
1606                         cancel = !!v.cancel;
1607                     }
1608                     else
1609                         if (v === false) {
1610                             cancel = true;
1611                         }
1612                         else {
1613                             returnValue = v;
1614                         }
1615                 }
1616             };
1617
1618             this[method] = function(){
1619                 var args = Ext.toArray(arguments);
1620                 returnValue = v = undefined;
1621                 cancel = false;
1622
1623                 Ext.each(e.before, function(b){
1624                     makeCall(b.fn, b.scope, args);
1625                     if (cancel) {
1626                         return returnValue;
1627                     }
1628                 });
1629
1630                 if (!Ext.isEmpty(v = e.originalFn.apply(obj, args))) {
1631                     returnValue = v;
1632                 }
1633                 Ext.each(e.after, function(a){
1634                     makeCall(a.fn, a.scope, args);
1635                     if (cancel) {
1636                         return returnValue;
1637                     }
1638                 });
1639                 return returnValue;
1640             };
1641         }
1642         return e;
1643     }
1644
1645     return {
1646         
1647         
1648         
1649         beforeMethod : function(method, fn, scope){
1650             getMethodEvent.call(this, method).before.push({
1651                 fn: fn,
1652                 scope: scope
1653             });
1654         },
1655
1656         
1657         afterMethod : function(method, fn, scope){
1658             getMethodEvent.call(this, method).after.push({
1659                 fn: fn,
1660                 scope: scope
1661             });
1662         },
1663
1664         removeMethodListener: function(method, fn, scope){
1665             var e = getMethodEvent.call(this, method), found = false;
1666             Ext.each(e.before, function(b, i, arr){
1667                 if (b.fn == fn && b.scope == scope) {
1668                     arr.splice(i, 1);
1669                     found = true;
1670                     return false;
1671                 }
1672             });
1673             if (!found) {
1674                 Ext.each(e.after, function(a, i, arr){
1675                     if (a.fn == fn && a.scope == scope) {
1676                         arr.splice(i, 1);
1677                         return false;
1678                     }
1679                 });
1680             }
1681         },
1682
1683         
1684         relayEvents : function(o, events){
1685             var me = this;
1686             function createHandler(ename){
1687                 return function(){
1688                     return me.fireEvent.apply(me, [ename].concat(Ext.toArray(arguments)));
1689                 };
1690             }
1691             Ext.each(events, function(ename){
1692                 me.events[ename] = me.events[ename] || true;
1693                 o.on(ename, createHandler(ename), me);
1694             });
1695         },
1696
1697         
1698         enableBubble : function(events){
1699             var me = this;
1700             if(!Ext.isEmpty(events)){
1701                 events = Ext.isArray(events) ? events : Ext.toArray(arguments);
1702                 Ext.each(events, function(ename){
1703                     ename = ename.toLowerCase();
1704                     var ce = me.events[ename] || true;
1705                     if (Ext.isBoolean(ce)) {
1706                         ce = new Ext.util.Event(me, ename);
1707                         me.events[ename] = ce;
1708                     }
1709                     ce.bubble = true;
1710                 });
1711             }
1712         }
1713     };
1714 }());
1715
1716
1717
1718 Ext.util.Observable.capture = function(o, fn, scope){
1719     o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
1720 };
1721
1722
1723
1724 Ext.util.Observable.observeClass = function(c, listeners){
1725     if(c){
1726       if(!c.fireEvent){
1727           Ext.apply(c, new Ext.util.Observable());
1728           Ext.util.Observable.capture(c.prototype, c.fireEvent, c);
1729       }
1730       if(Ext.isObject(listeners)){
1731           c.on(listeners);
1732       }
1733       return c;
1734    }
1735 };
1736 Ext.EventManager = function(){
1737     var docReadyEvent,
1738         docReadyProcId,
1739         docReadyState = false,
1740         E = Ext.lib.Event,
1741         D = Ext.lib.Dom,
1742         DOC = document,
1743         WINDOW = window,
1744         IEDEFERED = "ie-deferred-loader",
1745         DOMCONTENTLOADED = "DOMContentLoaded",
1746         propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/,
1747         
1748         specialElCache = [];
1749
1750      function getId(el){
1751         var id = false,
1752             i = 0,
1753             len = specialElCache.length,
1754             id = false,
1755             skip = false,
1756             o;
1757         if(el){
1758             if(el.getElementById || el.navigator){
1759                 
1760                 for(; i < len; ++i){
1761                     o = specialElCache[i];
1762                     if(o.el === el){
1763                         id = o.id;
1764                         break;
1765                     }
1766                 }
1767                 if(!id){
1768                     
1769                     id = Ext.id(el);
1770                     specialElCache.push({
1771                         id: id,
1772                         el: el
1773                     });
1774                     skip = true;
1775                 }
1776             }else{
1777                 id = Ext.id(el);
1778             }
1779             if(!Ext.elCache[id]){
1780                 Ext.Element.addToCache(new Ext.Element(el), id);
1781                 if(skip){
1782                     Ext.elCache[id].skipGC = true;
1783                 }
1784             }
1785         }
1786         return id;
1787      };
1788
1789     
1790     function addListener(el, ename, fn, wrap, scope){
1791         el = Ext.getDom(el);
1792         var id = getId(el),
1793             es = Ext.elCache[id].events,
1794             wfn;
1795
1796         wfn = E.on(el, ename, wrap);
1797         es[ename] = es[ename] || [];
1798         es[ename].push([fn, wrap, scope, wfn]);
1799
1800         
1801         
1802         if(ename == "mousewheel" && el.addEventListener){ 
1803             var args = ["DOMMouseScroll", wrap, false];
1804             el.addEventListener.apply(el, args);
1805             Ext.EventManager.addListener(WINDOW, 'unload', function(){
1806                 el.removeEventListener.apply(el, args);
1807             });
1808         }
1809         if(ename == "mousedown" && el == document){ 
1810             Ext.EventManager.stoppedMouseDownEvent.addListener(wrap);
1811         }
1812     };
1813
1814     function fireDocReady(){
1815         if(!docReadyState){
1816             Ext.isReady = docReadyState = true;
1817             if(docReadyProcId){
1818                 clearInterval(docReadyProcId);
1819             }
1820             if(Ext.isGecko || Ext.isOpera) {
1821                 DOC.removeEventListener(DOMCONTENTLOADED, fireDocReady, false);
1822             }
1823             if(Ext.isIE){
1824                 var defer = DOC.getElementById(IEDEFERED);
1825                 if(defer){
1826                     defer.onreadystatechange = null;
1827                     defer.parentNode.removeChild(defer);
1828                 }
1829             }
1830             if(docReadyEvent){
1831                 docReadyEvent.fire();
1832                 docReadyEvent.listeners = []; 
1833             }
1834         }
1835     };
1836
1837     function initDocReady(){
1838         var COMPLETE = "complete";
1839
1840         docReadyEvent = new Ext.util.Event();
1841         if (Ext.isGecko || Ext.isOpera) {
1842             DOC.addEventListener(DOMCONTENTLOADED, fireDocReady, false);
1843         } else if (Ext.isIE){
1844             DOC.write("<s"+'cript id=' + IEDEFERED + ' defer="defer" src="/'+'/:"></s'+"cript>");
1845             DOC.getElementById(IEDEFERED).onreadystatechange = function(){
1846                 if(this.readyState == COMPLETE){
1847                     fireDocReady();
1848                 }
1849             };
1850         } else if (Ext.isWebKit){
1851             docReadyProcId = setInterval(function(){
1852                 if(DOC.readyState == COMPLETE) {
1853                     fireDocReady();
1854                  }
1855             }, 10);
1856         }
1857         
1858         E.on(WINDOW, "load", fireDocReady);
1859     };
1860
1861     function createTargeted(h, o){
1862         return function(){
1863             var args = Ext.toArray(arguments);
1864             if(o.target == Ext.EventObject.setEvent(args[0]).target){
1865                 h.apply(this, args);
1866             }
1867         };
1868     };
1869
1870     function createBuffered(h, o, fn){
1871         fn.task = new Ext.util.DelayedTask(h);
1872         var w = function(e){
1873             
1874             fn.task.delay(o.buffer, h, null, [new Ext.EventObjectImpl(e)]);
1875         };
1876         return w;
1877     };
1878
1879     function createSingle(h, el, ename, fn, scope){
1880         return function(e){
1881             Ext.EventManager.removeListener(el, ename, fn, scope);
1882             h(e);
1883         };
1884     };
1885
1886     function createDelayed(h, o, fn){
1887         return function(e){
1888             var task = new Ext.util.DelayedTask(h);
1889             if(!fn.tasks) {
1890                 fn.tasks = [];
1891             }
1892             fn.tasks.push(task);
1893             task.delay(o.delay || 10, h, null, [new Ext.EventObjectImpl(e)]);
1894         };
1895     };
1896
1897     function listen(element, ename, opt, fn, scope){
1898         var o = !Ext.isObject(opt) ? {} : opt,
1899             el = Ext.getDom(element);
1900
1901         fn = fn || o.fn;
1902         scope = scope || o.scope;
1903
1904         if(!el){
1905             throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
1906         }
1907         function h(e){
1908             
1909             if(!Ext){
1910                 return;
1911             }
1912             e = Ext.EventObject.setEvent(e);
1913             var t;
1914             if (o.delegate) {
1915                 if(!(t = e.getTarget(o.delegate, el))){
1916                     return;
1917                 }
1918             } else {
1919                 t = e.target;
1920             }
1921             if (o.stopEvent) {
1922                 e.stopEvent();
1923             }
1924             if (o.preventDefault) {
1925                e.preventDefault();
1926             }
1927             if (o.stopPropagation) {
1928                 e.stopPropagation();
1929             }
1930             if (o.normalized) {
1931                 e = e.browserEvent;
1932             }
1933
1934             fn.call(scope || el, e, t, o);
1935         };
1936         if(o.target){
1937             h = createTargeted(h, o);
1938         }
1939         if(o.delay){
1940             h = createDelayed(h, o, fn);
1941         }
1942         if(o.single){
1943             h = createSingle(h, el, ename, fn, scope);
1944         }
1945         if(o.buffer){
1946             h = createBuffered(h, o, fn);
1947         }
1948
1949         addListener(el, ename, fn, h, scope);
1950         return h;
1951     };
1952
1953     var pub = {
1954         
1955         addListener : function(element, eventName, fn, scope, options){
1956             if(Ext.isObject(eventName)){
1957                 var o = eventName, e, val;
1958                 for(e in o){
1959                     val = o[e];
1960                     if(!propRe.test(e)){
1961                         if(Ext.isFunction(val)){
1962                             
1963                             listen(element, e, o, val, o.scope);
1964                         }else{
1965                             
1966                             listen(element, e, val);
1967                         }
1968                     }
1969                 }
1970             } else {
1971                 listen(element, eventName, options, fn, scope);
1972             }
1973         },
1974
1975         
1976         removeListener : function(el, eventName, fn, scope){
1977             el = Ext.getDom(el);
1978             var id = getId(el),
1979                 f = el && (Ext.elCache[id].events)[eventName] || [],
1980                 wrap, i, l, k, wf;
1981
1982             for (i = 0, len = f.length; i < len; i++) {
1983                 if (Ext.isArray(f[i]) && f[i][0] == fn && (!scope || f[i][2] == scope)) {
1984                     if(fn.task) {
1985                         fn.task.cancel();
1986                         delete fn.task;
1987                     }
1988                     k = fn.tasks && fn.tasks.length;
1989                     if(k) {
1990                         while(k--) {
1991                             fn.tasks[k].cancel();
1992                         }
1993                         delete fn.tasks;
1994                     }
1995                     wf = wrap = f[i][1];
1996                     if (E.extAdapter) {
1997                         wf = f[i][3];
1998                     }
1999                     E.un(el, eventName, wf);
2000                     f.splice(i,1);
2001                     if (f.length === 0) {
2002                         delete Ext.elCache[id].events[eventName];
2003                     }
2004                     for (k in Ext.elCache[id].events) {
2005                         return false;
2006                     }
2007                     Ext.elCache[id].events = {};
2008                     return false;
2009                 }
2010             }
2011
2012             
2013             if(eventName == "mousewheel" && el.addEventListener && wrap){
2014                 el.removeEventListener("DOMMouseScroll", wrap, false);
2015             }
2016
2017             if(eventName == "mousedown" && el == DOC && wrap){ 
2018                 Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);
2019             }
2020         },
2021
2022         
2023         removeAll : function(el){
2024             el = Ext.getDom(el);
2025             var id = getId(el),
2026                 ec = Ext.elCache[id] || {},
2027                 es = ec.events || {},
2028                 f, i, len, ename, fn, k;
2029
2030             for(ename in es){
2031                 if(es.hasOwnProperty(ename)){
2032                     f = es[ename];
2033                     for (i = 0, len = f.length; i < len; i++) {
2034                         fn = f[i][0];
2035                         if(fn.task) {
2036                             fn.task.cancel();
2037                             delete fn.task;
2038                         }
2039                         if(fn.tasks && (k = fn.tasks.length)) {
2040                             while(k--) {
2041                                 fn.tasks[k].cancel();
2042                             }
2043                             delete fn.tasks;
2044                         }
2045                         E.un(el, ename, E.extAdapter ? f[i][3] : f[i][1]);
2046                     }
2047                 }
2048             }
2049             if (Ext.elCache[id]) {
2050                 Ext.elCache[id].events = {};
2051             }
2052         },
2053
2054         getListeners : function(el, eventName) {
2055             el = Ext.getDom(el);
2056             var id = getId(el),
2057                 ec = Ext.elCache[id] || {},
2058                 es = ec.events || {},
2059                 results = [];
2060             if (es && es[eventName]) {
2061                 return es[eventName];
2062             } else {
2063                 return null;
2064             }
2065         },
2066
2067         purgeElement : function(el, recurse, eventName) {
2068             el = Ext.getDom(el);
2069             var id = getId(el),
2070                 ec = Ext.elCache[id] || {},
2071                 es = ec.events || {},
2072                 i, f, len;
2073             if (eventName) {
2074                 if (es && es.hasOwnProperty(eventName)) {
2075                     f = es[eventName];
2076                     for (i = 0, len = f.length; i < len; i++) {
2077                         Ext.EventManager.removeListener(el, eventName, f[i][0]);
2078                     }
2079                 }
2080             } else {
2081                 Ext.EventManager.removeAll(el);
2082             }
2083             if (recurse && el && el.childNodes) {
2084                 for (i = 0, len = el.childNodes.length; i < len; i++) {
2085                     Ext.EventManager.purgeElement(el.childNodes[i], recurse, eventName);
2086                 }
2087             }
2088         },
2089
2090         _unload : function() {
2091             var el;
2092             for (el in Ext.elCache) {
2093                 Ext.EventManager.removeAll(el);
2094             }
2095         },
2096         
2097         onDocumentReady : function(fn, scope, options){
2098             if(docReadyState){ 
2099                 docReadyEvent.addListener(fn, scope, options);
2100                 docReadyEvent.fire();
2101                 docReadyEvent.listeners = []; 
2102             } else {
2103                 if(!docReadyEvent) initDocReady();
2104                 options = options || {};
2105                 options.delay = options.delay || 1;
2106                 docReadyEvent.addListener(fn, scope, options);
2107             }
2108         }
2109     };
2110      
2111     pub.on = pub.addListener;
2112     
2113     pub.un = pub.removeListener;
2114
2115     pub.stoppedMouseDownEvent = new Ext.util.Event();
2116     return pub;
2117 }();
2118
2119 Ext.onReady = Ext.EventManager.onDocumentReady;
2120
2121
2122
2123 (function(){
2124
2125     var initExtCss = function(){
2126         
2127         var bd = document.body || document.getElementsByTagName('body')[0];
2128         if(!bd){ return false; }
2129         var cls = [' ',
2130                 Ext.isIE ? "ext-ie " + (Ext.isIE6 ? 'ext-ie6' : (Ext.isIE7 ? 'ext-ie7' : 'ext-ie8'))
2131                 : Ext.isGecko ? "ext-gecko " + (Ext.isGecko2 ? 'ext-gecko2' : 'ext-gecko3')
2132                 : Ext.isOpera ? "ext-opera"
2133                 : Ext.isWebKit ? "ext-webkit" : ""];
2134
2135         if(Ext.isSafari){
2136             cls.push("ext-safari " + (Ext.isSafari2 ? 'ext-safari2' : (Ext.isSafari3 ? 'ext-safari3' : 'ext-safari4')));
2137         }else if(Ext.isChrome){
2138             cls.push("ext-chrome");
2139         }
2140
2141         if(Ext.isMac){
2142             cls.push("ext-mac");
2143         }
2144         if(Ext.isLinux){
2145             cls.push("ext-linux");
2146         }
2147
2148         if(Ext.isStrict || Ext.isBorderBox){ 
2149             var p = bd.parentNode;
2150             if(p){
2151                 p.className += Ext.isStrict ? ' ext-strict' : ' ext-border-box';
2152             }
2153         }
2154         bd.className += cls.join(' ');
2155         return true;
2156     }
2157
2158     if(!initExtCss()){
2159         Ext.onReady(initExtCss);
2160     }
2161 })();
2162
2163
2164
2165 Ext.EventObject = function(){
2166     var E = Ext.lib.Event,
2167         
2168         safariKeys = {
2169             3 : 13, 
2170             63234 : 37, 
2171             63235 : 39, 
2172             63232 : 38, 
2173             63233 : 40, 
2174             63276 : 33, 
2175             63277 : 34, 
2176             63272 : 46, 
2177             63273 : 36, 
2178             63275 : 35  
2179         },
2180         
2181         btnMap = Ext.isIE ? {1:0,4:1,2:2} :
2182                 (Ext.isWebKit ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
2183
2184     Ext.EventObjectImpl = function(e){
2185         if(e){
2186             this.setEvent(e.browserEvent || e);
2187         }
2188     };
2189
2190     Ext.EventObjectImpl.prototype = {
2191            
2192         setEvent : function(e){
2193             var me = this;
2194             if(e == me || (e && e.browserEvent)){ 
2195                 return e;
2196             }
2197             me.browserEvent = e;
2198             if(e){
2199                 
2200                 me.button = e.button ? btnMap[e.button] : (e.which ? e.which - 1 : -1);
2201                 if(e.type == 'click' && me.button == -1){
2202                     me.button = 0;
2203                 }
2204                 me.type = e.type;
2205                 me.shiftKey = e.shiftKey;
2206                 
2207                 me.ctrlKey = e.ctrlKey || e.metaKey || false;
2208                 me.altKey = e.altKey;
2209                 
2210                 me.keyCode = e.keyCode;
2211                 me.charCode = e.charCode;
2212                 
2213                 me.target = E.getTarget(e);
2214                 
2215                 me.xy = E.getXY(e);
2216             }else{
2217                 me.button = -1;
2218                 me.shiftKey = false;
2219                 me.ctrlKey = false;
2220                 me.altKey = false;
2221                 me.keyCode = 0;
2222                 me.charCode = 0;
2223                 me.target = null;
2224                 me.xy = [0, 0];
2225             }
2226             return me;
2227         },
2228
2229         
2230         stopEvent : function(){
2231             var me = this;
2232             if(me.browserEvent){
2233                 if(me.browserEvent.type == 'mousedown'){
2234                     Ext.EventManager.stoppedMouseDownEvent.fire(me);
2235                 }
2236                 E.stopEvent(me.browserEvent);
2237             }
2238         },
2239
2240         
2241         preventDefault : function(){
2242             if(this.browserEvent){
2243                 E.preventDefault(this.browserEvent);
2244             }
2245         },
2246
2247         
2248         stopPropagation : function(){
2249             var me = this;
2250             if(me.browserEvent){
2251                 if(me.browserEvent.type == 'mousedown'){
2252                     Ext.EventManager.stoppedMouseDownEvent.fire(me);
2253                 }
2254                 E.stopPropagation(me.browserEvent);
2255             }
2256         },
2257
2258         
2259         getCharCode : function(){
2260             return this.charCode || this.keyCode;
2261         },
2262
2263         
2264         getKey : function(){
2265             return this.normalizeKey(this.keyCode || this.charCode)
2266         },
2267
2268         
2269         normalizeKey: function(k){
2270             return Ext.isSafari ? (safariKeys[k] || k) : k;
2271         },
2272
2273         
2274         getPageX : function(){
2275             return this.xy[0];
2276         },
2277
2278         
2279         getPageY : function(){
2280             return this.xy[1];
2281         },
2282
2283         
2284         getXY : function(){
2285             return this.xy;
2286         },
2287
2288         
2289         getTarget : function(selector, maxDepth, returnEl){
2290             return selector ? Ext.fly(this.target).findParent(selector, maxDepth, returnEl) : (returnEl ? Ext.get(this.target) : this.target);
2291         },
2292
2293         
2294         getRelatedTarget : function(){
2295             return this.browserEvent ? E.getRelatedTarget(this.browserEvent) : null;
2296         },
2297
2298         
2299         getWheelDelta : function(){
2300             var e = this.browserEvent;
2301             var delta = 0;
2302             if(e.wheelDelta){ 
2303                 delta = e.wheelDelta/120;
2304             }else if(e.detail){ 
2305                 delta = -e.detail/3;
2306             }
2307             return delta;
2308         },
2309
2310         
2311         within : function(el, related, allowEl){
2312             if(el){
2313                 var t = this[related ? "getRelatedTarget" : "getTarget"]();
2314                 return t && ((allowEl ? (t == Ext.getDom(el)) : false) || Ext.fly(el).contains(t));
2315             }
2316             return false;
2317         }
2318      };
2319
2320     return new Ext.EventObjectImpl();
2321 }();
2322
2323
2324 Ext.apply(Ext.EventManager, function(){
2325    var resizeEvent,
2326        resizeTask,
2327        textEvent,
2328        textSize,
2329        D = Ext.lib.Dom,
2330        propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/,
2331        curWidth = 0,
2332        curHeight = 0,
2333        
2334        
2335        
2336        useKeydown = Ext.isWebKit ?
2337                    Ext.num(navigator.userAgent.match(/AppleWebKit\/(\d+)/)[1]) >= 525 :
2338                    !((Ext.isGecko && !Ext.isWindows) || Ext.isOpera);
2339
2340    return {
2341        
2342        doResizeEvent: function(){
2343            var h = D.getViewHeight(),
2344                w = D.getViewWidth();
2345
2346            
2347            if(curHeight != h || curWidth != w){
2348                resizeEvent.fire(curWidth = w, curHeight = h);
2349            }
2350        },
2351
2352        
2353        onWindowResize : function(fn, scope, options){
2354            if(!resizeEvent){
2355                resizeEvent = new Ext.util.Event();
2356                resizeTask = new Ext.util.DelayedTask(this.doResizeEvent);
2357                Ext.EventManager.on(window, "resize", this.fireWindowResize, this);
2358            }
2359            resizeEvent.addListener(fn, scope, options);
2360        },
2361
2362        
2363        fireWindowResize : function(){
2364            if(resizeEvent){
2365                if((Ext.isIE||Ext.isAir) && resizeTask){
2366                    resizeTask.delay(50);
2367                }else{
2368                    resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
2369                }
2370            }
2371        },
2372
2373        
2374        onTextResize : function(fn, scope, options){
2375            if(!textEvent){
2376                textEvent = new Ext.util.Event();
2377                var textEl = new Ext.Element(document.createElement('div'));
2378                textEl.dom.className = 'x-text-resize';
2379                textEl.dom.innerHTML = 'X';
2380                textEl.appendTo(document.body);
2381                textSize = textEl.dom.offsetHeight;
2382                setInterval(function(){
2383                    if(textEl.dom.offsetHeight != textSize){
2384                        textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
2385                    }
2386                }, this.textResizeInterval);
2387            }
2388            textEvent.addListener(fn, scope, options);
2389        },
2390
2391        
2392        removeResizeListener : function(fn, scope){
2393            if(resizeEvent){
2394                resizeEvent.removeListener(fn, scope);
2395            }
2396        },
2397
2398        
2399        fireResize : function(){
2400            if(resizeEvent){
2401                resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
2402            }
2403        },
2404
2405         
2406        textResizeInterval : 50,
2407
2408        
2409        ieDeferSrc : false,
2410
2411        
2412        
2413        useKeydown: useKeydown
2414    };
2415 }());
2416
2417 Ext.EventManager.on = Ext.EventManager.addListener;
2418
2419
2420 Ext.apply(Ext.EventObjectImpl.prototype, {
2421    
2422    BACKSPACE: 8,
2423    
2424    TAB: 9,
2425    
2426    NUM_CENTER: 12,
2427    
2428    ENTER: 13,
2429    
2430    RETURN: 13,
2431    
2432    SHIFT: 16,
2433    
2434    CTRL: 17,
2435    CONTROL : 17, 
2436    
2437    ALT: 18,
2438    
2439    PAUSE: 19,
2440    
2441    CAPS_LOCK: 20,
2442    
2443    ESC: 27,
2444    
2445    SPACE: 32,
2446    
2447    PAGE_UP: 33,
2448    PAGEUP : 33, 
2449    
2450    PAGE_DOWN: 34,
2451    PAGEDOWN : 34, 
2452    
2453    END: 35,
2454    
2455    HOME: 36,
2456    
2457    LEFT: 37,
2458    
2459    UP: 38,
2460    
2461    RIGHT: 39,
2462    
2463    DOWN: 40,
2464    
2465    PRINT_SCREEN: 44,
2466    
2467    INSERT: 45,
2468    
2469    DELETE: 46,
2470    
2471    ZERO: 48,
2472    
2473    ONE: 49,
2474    
2475    TWO: 50,
2476    
2477    THREE: 51,
2478    
2479    FOUR: 52,
2480    
2481    FIVE: 53,
2482    
2483    SIX: 54,
2484    
2485    SEVEN: 55,
2486    
2487    EIGHT: 56,
2488    
2489    NINE: 57,
2490    
2491    A: 65,
2492    
2493    B: 66,
2494    
2495    C: 67,
2496    
2497    D: 68,
2498    
2499    E: 69,
2500    
2501    F: 70,
2502    
2503    G: 71,
2504    
2505    H: 72,
2506    
2507    I: 73,
2508    
2509    J: 74,
2510    
2511    K: 75,
2512    
2513    L: 76,
2514    
2515    M: 77,
2516    
2517    N: 78,
2518    
2519    O: 79,
2520    
2521    P: 80,
2522    
2523    Q: 81,
2524    
2525    R: 82,
2526    
2527    S: 83,
2528    
2529    T: 84,
2530    
2531    U: 85,
2532    
2533    V: 86,
2534    
2535    W: 87,
2536    
2537    X: 88,
2538    
2539    Y: 89,
2540    
2541    Z: 90,
2542    
2543    CONTEXT_MENU: 93,
2544    
2545    NUM_ZERO: 96,
2546    
2547    NUM_ONE: 97,
2548    
2549    NUM_TWO: 98,
2550    
2551    NUM_THREE: 99,
2552    
2553    NUM_FOUR: 100,
2554    
2555    NUM_FIVE: 101,
2556    
2557    NUM_SIX: 102,
2558    
2559    NUM_SEVEN: 103,
2560    
2561    NUM_EIGHT: 104,
2562    
2563    NUM_NINE: 105,
2564    
2565    NUM_MULTIPLY: 106,
2566    
2567    NUM_PLUS: 107,
2568    
2569    NUM_MINUS: 109,
2570    
2571    NUM_PERIOD: 110,
2572    
2573    NUM_DIVISION: 111,
2574    
2575    F1: 112,
2576    
2577    F2: 113,
2578    
2579    F3: 114,
2580    
2581    F4: 115,
2582    
2583    F5: 116,
2584    
2585    F6: 117,
2586    
2587    F7: 118,
2588    
2589    F8: 119,
2590    
2591    F9: 120,
2592    
2593    F10: 121,
2594    
2595    F11: 122,
2596    
2597    F12: 123,
2598
2599    
2600    isNavKeyPress : function(){
2601        var me = this,
2602            k = this.normalizeKey(me.keyCode);
2603        return (k >= 33 && k <= 40) ||  
2604        k == me.RETURN ||
2605        k == me.TAB ||
2606        k == me.ESC;
2607    },
2608
2609    isSpecialKey : function(){
2610        var k = this.normalizeKey(this.keyCode);
2611        return (this.type == 'keypress' && this.ctrlKey) ||
2612        this.isNavKeyPress() ||
2613        (k == this.BACKSPACE) || 
2614        (k >= 16 && k <= 20) || 
2615        (k >= 44 && k <= 45);   
2616    },
2617
2618    getPoint : function(){
2619        return new Ext.lib.Point(this.xy[0], this.xy[1]);
2620    },
2621
2622    
2623    hasModifier : function(){
2624        return ((this.ctrlKey || this.altKey) || this.shiftKey);
2625    }
2626 });
2627 (function(){
2628 var DOC = document;
2629
2630 Ext.Element = function(element, forceNew){
2631     var dom = typeof element == "string" ?
2632               DOC.getElementById(element) : element,
2633         id;
2634
2635     if(!dom) return null;
2636
2637     id = dom.id;
2638
2639     if(!forceNew && id && Ext.elCache[id]){ 
2640         return Ext.elCache[id].el;
2641     }
2642
2643     
2644     this.dom = dom;
2645
2646     
2647     this.id = id || Ext.id(dom);
2648 };
2649
2650 var D = Ext.lib.Dom,
2651     DH = Ext.DomHelper,
2652     E = Ext.lib.Event,
2653     A = Ext.lib.Anim,
2654     El = Ext.Element,
2655     EC = Ext.elCache;
2656
2657 El.prototype = {
2658     
2659     set : function(o, useSet){
2660         var el = this.dom,
2661             attr,
2662             val,
2663             useSet = (useSet !== false) && !!el.setAttribute;
2664
2665         for(attr in o){
2666             if (o.hasOwnProperty(attr)) {
2667                 val = o[attr];
2668                 if (attr == 'style') {
2669                     DH.applyStyles(el, val);
2670                 } else if (attr == 'cls') {
2671                     el.className = val;
2672                 } else if (useSet) {
2673                     el.setAttribute(attr, val);
2674                 } else {
2675                     el[attr] = val;
2676                 }
2677             }
2678         }
2679         return this;
2680     },
2681
2682
2683     
2684     
2685     
2686     
2687     
2688     
2689     
2690     
2691     
2692     
2693
2694
2695     
2696     
2697     
2698
2699
2700
2701     
2702     
2703     
2704     
2705     
2706     
2707
2708
2709     
2710     
2711     
2712     
2713     
2714     
2715
2716
2717     
2718     
2719     
2720
2721
2722     
2723     
2724     
2725     
2726     
2727     
2728     
2729
2730     
2731     defaultUnit : "px",
2732
2733     
2734     is : function(simpleSelector){
2735         return Ext.DomQuery.is(this.dom, simpleSelector);
2736     },
2737
2738     
2739     focus : function(defer,  dom) {
2740         var me = this,
2741             dom = dom || me.dom;
2742         try{
2743             if(Number(defer)){
2744                 me.focus.defer(defer, null, [null, dom]);
2745             }else{
2746                 dom.focus();
2747             }
2748         }catch(e){}
2749         return me;
2750     },
2751
2752     
2753     blur : function() {
2754         try{
2755             this.dom.blur();
2756         }catch(e){}
2757         return this;
2758     },
2759
2760     
2761     getValue : function(asNumber){
2762         var val = this.dom.value;
2763         return asNumber ? parseInt(val, 10) : val;
2764     },
2765
2766     
2767     addListener : function(eventName, fn, scope, options){
2768         Ext.EventManager.on(this.dom,  eventName, fn, scope || this, options);
2769         return this;
2770     },
2771
2772     
2773     removeListener : function(eventName, fn, scope){
2774         Ext.EventManager.removeListener(this.dom,  eventName, fn, scope || this);
2775         return this;
2776     },
2777
2778     
2779     removeAllListeners : function(){
2780         Ext.EventManager.removeAll(this.dom);
2781         return this;
2782     },
2783
2784     
2785     purgeAllListeners : function() {
2786         Ext.EventManager.purgeElement(this, true);
2787         return this;
2788     },
2789     
2790     addUnits : function(size){
2791         if(size === "" || size == "auto" || size === undefined){
2792             size = size || '';
2793         } else if(!isNaN(size) || !unitPattern.test(size)){
2794             size = size + (this.defaultUnit || 'px');
2795         }
2796         return size;
2797     },
2798
2799     
2800     load : function(url, params, cb){
2801         Ext.Ajax.request(Ext.apply({
2802             params: params,
2803             url: url.url || url,
2804             callback: cb,
2805             el: this.dom,
2806             indicatorText: url.indicatorText || ''
2807         }, Ext.isObject(url) ? url : {}));
2808         return this;
2809     },
2810
2811     
2812     isBorderBox : function(){
2813         return noBoxAdjust[(this.dom.tagName || "").toLowerCase()] || Ext.isBorderBox;
2814     },
2815
2816     
2817     remove : function(){
2818         var me = this,
2819             dom = me.dom;
2820
2821         if (dom) {
2822             delete me.dom;
2823             Ext.removeNode(dom);
2824         }
2825     },
2826
2827     
2828     hover : function(overFn, outFn, scope, options){
2829         var me = this;
2830         me.on('mouseenter', overFn, scope || me.dom, options);
2831         me.on('mouseleave', outFn, scope || me.dom, options);
2832         return me;
2833     },
2834
2835     
2836     contains : function(el){
2837         return !el ? false : Ext.lib.Dom.isAncestor(this.dom, el.dom ? el.dom : el);
2838     },
2839
2840     
2841     getAttributeNS : function(ns, name){
2842         return this.getAttribute(name, ns);
2843     },
2844
2845     
2846     getAttribute : Ext.isIE ? function(name, ns){
2847         var d = this.dom,
2848             type = typeof d[ns + ":" + name];
2849
2850         if(['undefined', 'unknown'].indexOf(type) == -1){
2851             return d[ns + ":" + name];
2852         }
2853         return d[name];
2854     } : function(name, ns){
2855         var d = this.dom;
2856         return d.getAttributeNS(ns, name) || d.getAttribute(ns + ":" + name) || d.getAttribute(name) || d[name];
2857     },
2858
2859     
2860     update : function(html) {
2861         if (this.dom) {
2862             this.dom.innerHTML = html;
2863         }
2864         return this;
2865     }
2866 };
2867
2868 var ep = El.prototype;
2869
2870 El.addMethods = function(o){
2871    Ext.apply(ep, o);
2872 };
2873
2874
2875 ep.on = ep.addListener;
2876
2877
2878 ep.un = ep.removeListener;
2879
2880
2881 ep.autoBoxAdjust = true;
2882
2883
2884 var unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i,
2885     docEl;
2886
2887
2888
2889
2890 El.get = function(el){
2891     var ex,
2892         elm,
2893         id;
2894     if(!el){ return null; }
2895     if (typeof el == "string") { 
2896         if (!(elm = DOC.getElementById(el))) {
2897             return null;
2898         }
2899         if (EC[el] && EC[el].el) {
2900             ex = EC[el].el;
2901             ex.dom = elm;
2902         } else {
2903             ex = El.addToCache(new El(elm));
2904         }
2905         return ex;
2906     } else if (el.tagName) { 
2907         if(!(id = el.id)){
2908             id = Ext.id(el);
2909         }
2910         if (EC[id] && EC[id].el) {
2911             ex = EC[id].el;
2912             ex.dom = el;
2913         } else {
2914             ex = El.addToCache(new El(el));
2915         }
2916         return ex;
2917     } else if (el instanceof El) {
2918         if(el != docEl){
2919             el.dom = DOC.getElementById(el.id) || el.dom; 
2920                                                           
2921         }
2922         return el;
2923     } else if(el.isComposite) {
2924         return el;
2925     } else if(Ext.isArray(el)) {
2926         return El.select(el);
2927     } else if(el == DOC) {
2928         
2929         if(!docEl){
2930             var f = function(){};
2931             f.prototype = El.prototype;
2932             docEl = new f();
2933             docEl.dom = DOC;
2934         }
2935         return docEl;
2936     }
2937     return null;
2938 };
2939
2940 El.addToCache = function(el, id){
2941     id = id || el.id;    
2942     EC[id] = {
2943         el:  el,
2944         data: {},
2945         events: {}
2946     };
2947     return el;
2948 };
2949
2950
2951 El.data = function(el, key, value){
2952     el = El.get(el);
2953     if (!el) {
2954         return null;
2955     }
2956     var c = EC[el.id].data;
2957     if(arguments.length == 2){
2958         return c[key];
2959     }else{
2960         return (c[key] = value);
2961     }
2962 };
2963
2964
2965
2966
2967 function garbageCollect(){
2968     if(!Ext.enableGarbageCollector){
2969         clearInterval(El.collectorThreadId);
2970     } else {
2971         var eid,
2972             el,
2973             d,
2974             o;
2975
2976         for(eid in EC){
2977             o = EC[eid];
2978             if(o.skipGC){
2979                 continue;
2980             }
2981             el = o.el;
2982             d = el.dom;
2983             
2984             
2985             
2986             
2987             
2988             
2989             
2990             
2991             
2992             
2993             
2994             
2995             
2996             
2997             
2998             
2999             
3000             if(!d || !d.parentNode || (!d.offsetParent && !DOC.getElementById(eid))){
3001                 if(Ext.enableListenerCollection){
3002                     Ext.EventManager.removeAll(d);
3003                 }
3004                 delete EC[eid];
3005             }
3006         }
3007         
3008         if (Ext.isIE) {
3009             var t = {};
3010             for (eid in EC) {
3011                 t[eid] = EC[eid];
3012             }
3013             EC = Ext.elCache = t;
3014         }
3015     }
3016 }
3017 El.collectorThreadId = setInterval(garbageCollect, 30000);
3018
3019 var flyFn = function(){};
3020 flyFn.prototype = El.prototype;
3021
3022
3023 El.Flyweight = function(dom){
3024     this.dom = dom;
3025 };
3026
3027 El.Flyweight.prototype = new flyFn();
3028 El.Flyweight.prototype.isFlyweight = true;
3029 El._flyweights = {};
3030
3031
3032 El.fly = function(el, named){
3033     var ret = null;
3034     named = named || '_global';
3035
3036     if (el = Ext.getDom(el)) {
3037         (El._flyweights[named] = El._flyweights[named] || new El.Flyweight()).dom = el;
3038         ret = El._flyweights[named];
3039     }
3040     return ret;
3041 };
3042
3043
3044 Ext.get = El.get;
3045
3046
3047 Ext.fly = El.fly;
3048
3049
3050 var noBoxAdjust = Ext.isStrict ? {
3051     select:1
3052 } : {
3053     input:1, select:1, textarea:1
3054 };
3055 if(Ext.isIE || Ext.isGecko){
3056     noBoxAdjust['button'] = 1;
3057 }
3058
3059
3060 Ext.EventManager.on(window, 'unload', function(){
3061     delete EC;
3062     delete El._flyweights;
3063 });
3064 })();
3065
3066 Ext.Element.addMethods({
3067     
3068     swallowEvent : function(eventName, preventDefault){
3069         var me = this;
3070         function fn(e){
3071             e.stopPropagation();
3072             if(preventDefault){
3073                 e.preventDefault();
3074             }
3075         }
3076         if(Ext.isArray(eventName)){
3077             Ext.each(eventName, function(e) {
3078                  me.on(e, fn);
3079             });
3080             return me;
3081         }
3082         me.on(eventName, fn);
3083         return me;
3084     },
3085
3086     
3087     relayEvent : function(eventName, observable){
3088         this.on(eventName, function(e){
3089             observable.fireEvent(eventName, e);
3090         });
3091     },
3092
3093     
3094     clean : function(forceReclean){
3095         var me = this,
3096             dom = me.dom,
3097             n = dom.firstChild,
3098             ni = -1;
3099
3100         if(Ext.Element.data(dom, 'isCleaned') && forceReclean !== true){
3101             return me;
3102         }
3103
3104         while(n){
3105             var nx = n.nextSibling;
3106             if(n.nodeType == 3 && !/\S/.test(n.nodeValue)){
3107                 dom.removeChild(n);
3108             }else{
3109                 n.nodeIndex = ++ni;
3110             }
3111             n = nx;
3112         }
3113         Ext.Element.data(dom, 'isCleaned', true);
3114         return me;
3115     },
3116
3117     
3118     load : function(){
3119         var um = this.getUpdater();
3120         um.update.apply(um, arguments);
3121         return this;
3122     },
3123
3124     
3125     getUpdater : function(){
3126         return this.updateManager || (this.updateManager = new Ext.Updater(this));
3127     },
3128
3129     
3130     update : function(html, loadScripts, callback){
3131         if (!this.dom) {
3132             return this;
3133         }
3134         html = html || "";
3135
3136         if(loadScripts !== true){
3137             this.dom.innerHTML = html;
3138             if(Ext.isFunction(callback)){
3139                 callback();
3140             }
3141             return this;
3142         }
3143
3144         var id = Ext.id(),
3145             dom = this.dom;
3146
3147         html += '<span id="' + id + '"></span>';
3148
3149         Ext.lib.Event.onAvailable(id, function(){
3150             var DOC = document,
3151                 hd = DOC.getElementsByTagName("head")[0],
3152                 re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig,
3153                 srcRe = /\ssrc=([\'\"])(.*?)\1/i,
3154                 typeRe = /\stype=([\'\"])(.*?)\1/i,
3155                 match,
3156                 attrs,
3157                 srcMatch,
3158                 typeMatch,
3159                 el,
3160                 s;
3161
3162             while((match = re.exec(html))){
3163                 attrs = match[1];
3164                 srcMatch = attrs ? attrs.match(srcRe) : false;
3165                 if(srcMatch && srcMatch[2]){
3166                    s = DOC.createElement("script");
3167                    s.src = srcMatch[2];
3168                    typeMatch = attrs.match(typeRe);
3169                    if(typeMatch && typeMatch[2]){
3170                        s.type = typeMatch[2];
3171                    }
3172                    hd.appendChild(s);
3173                 }else if(match[2] && match[2].length > 0){
3174                     if(window.execScript) {
3175                        window.execScript(match[2]);
3176                     } else {
3177                        window.eval(match[2]);
3178                     }
3179                 }
3180             }
3181             el = DOC.getElementById(id);
3182             if(el){Ext.removeNode(el);}
3183             if(Ext.isFunction(callback)){
3184                 callback();
3185             }
3186         });
3187         dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
3188         return this;
3189     },
3190
3191     
3192     removeAllListeners : function(){
3193         this.removeAnchor();
3194         Ext.EventManager.removeAll(this.dom);
3195         return this;
3196     },
3197
3198     
3199     createProxy : function(config, renderTo, matchBox){
3200         config = Ext.isObject(config) ? config : {tag : "div", cls: config};
3201
3202         var me = this,
3203             proxy = renderTo ? Ext.DomHelper.append(renderTo, config, true) :
3204                                Ext.DomHelper.insertBefore(me.dom, config, true);
3205
3206         if(matchBox && me.setBox && me.getBox){ 
3207            proxy.setBox(me.getBox());
3208         }
3209         return proxy;
3210     }
3211 });
3212
3213 Ext.Element.prototype.getUpdateManager = Ext.Element.prototype.getUpdater;
3214
3215 Ext.Element.addMethods({
3216     
3217     getAnchorXY : function(anchor, local, s){
3218         
3219         
3220                 anchor = (anchor || "tl").toLowerCase();
3221         s = s || {};
3222         
3223         var me = this,        
3224                 vp = me.dom == document.body || me.dom == document,
3225                 w = s.width || vp ? Ext.lib.Dom.getViewWidth() : me.getWidth(),
3226                 h = s.height || vp ? Ext.lib.Dom.getViewHeight() : me.getHeight(),                              
3227                 xy,             
3228                 r = Math.round,
3229                 o = me.getXY(),
3230                 scroll = me.getScroll(),
3231                 extraX = vp ? scroll.left : !local ? o[0] : 0,
3232                 extraY = vp ? scroll.top : !local ? o[1] : 0,
3233                 hash = {
3234                         c  : [r(w * 0.5), r(h * 0.5)],
3235                         t  : [r(w * 0.5), 0],
3236                         l  : [0, r(h * 0.5)],
3237                         r  : [w, r(h * 0.5)],
3238                         b  : [r(w * 0.5), h],
3239                         tl : [0, 0],    
3240                         bl : [0, h],
3241                         br : [w, h],
3242                         tr : [w, 0]
3243                 };
3244         
3245         xy = hash[anchor];      
3246         return [xy[0] + extraX, xy[1] + extraY]; 
3247     },
3248
3249     
3250     anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){        
3251             var me = this,
3252             dom = me.dom,
3253             scroll = !Ext.isEmpty(monitorScroll),
3254             action = function(){
3255                 Ext.fly(dom).alignTo(el, alignment, offsets, animate);
3256                 Ext.callback(callback, Ext.fly(dom));
3257             },
3258             anchor = this.getAnchor();
3259             
3260         
3261         this.removeAnchor();
3262         Ext.apply(anchor, {
3263             fn: action,
3264             scroll: scroll
3265         });
3266
3267         Ext.EventManager.onWindowResize(action, null);
3268         
3269         if(scroll){
3270             Ext.EventManager.on(window, 'scroll', action, null,
3271                 {buffer: !isNaN(monitorScroll) ? monitorScroll : 50});
3272         }
3273         action.call(me); 
3274         return me;
3275     },
3276     
3277     
3278     removeAnchor : function(){
3279         var me = this,
3280             anchor = this.getAnchor();
3281             
3282         if(anchor && anchor.fn){
3283             Ext.EventManager.removeResizeListener(anchor.fn);
3284             if(anchor.scroll){
3285                 Ext.EventManager.un(window, 'scroll', anchor.fn);
3286             }
3287             delete anchor.fn;
3288         }
3289         return me;
3290     },
3291     
3292     
3293     getAnchor : function(){
3294         var data = Ext.Element.data,
3295             dom = this.dom;
3296             if (!dom) {
3297                 return;
3298             }
3299             var anchor = data(dom, '_anchor');
3300             
3301         if(!anchor){
3302             anchor = data(dom, '_anchor', {});
3303         }
3304         return anchor;
3305     },
3306
3307     
3308     getAlignToXY : function(el, p, o){      
3309         el = Ext.get(el);
3310         
3311         if(!el || !el.dom){
3312             throw "Element.alignToXY with an element that doesn't exist";
3313         }
3314         
3315         o = o || [0,0];
3316         p = (!p || p == "?" ? "tl-bl?" : (!/-/.test(p) && p !== "" ? "tl-" + p : p || "tl-bl")).toLowerCase();       
3317                 
3318         var me = this,
3319                 d = me.dom,
3320                 a1,
3321                 a2,
3322                 x,
3323                 y,
3324                 
3325                 w,
3326                 h,
3327                 r,
3328                 dw = Ext.lib.Dom.getViewWidth() -10, 
3329                 dh = Ext.lib.Dom.getViewHeight()-10, 
3330                 p1y,
3331                 p1x,            
3332                 p2y,
3333                 p2x,
3334                 swapY,
3335                 swapX,
3336                 doc = document,
3337                 docElement = doc.documentElement,
3338                 docBody = doc.body,
3339                 scrollX = (docElement.scrollLeft || docBody.scrollLeft || 0)+5,
3340                 scrollY = (docElement.scrollTop || docBody.scrollTop || 0)+5,
3341                 c = false, 
3342                 p1 = "", 
3343                 p2 = "",
3344                 m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
3345         
3346         if(!m){
3347            throw "Element.alignTo with an invalid alignment " + p;
3348         }
3349         
3350         p1 = m[1]; 
3351         p2 = m[2]; 
3352         c = !!m[3];
3353
3354         
3355         
3356         a1 = me.getAnchorXY(p1, true);
3357         a2 = el.getAnchorXY(p2, false);
3358
3359         x = a2[0] - a1[0] + o[0];
3360         y = a2[1] - a1[1] + o[1];
3361
3362         if(c){    
3363                w = me.getWidth();
3364            h = me.getHeight();
3365            r = el.getRegion();       
3366            
3367            
3368            
3369            p1y = p1.charAt(0);
3370            p1x = p1.charAt(p1.length-1);
3371            p2y = p2.charAt(0);
3372            p2x = p2.charAt(p2.length-1);
3373            swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
3374            swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));          
3375            
3376
3377            if (x + w > dw + scrollX) {
3378                 x = swapX ? r.left-w : dw+scrollX-w;
3379            }
3380            if (x < scrollX) {
3381                x = swapX ? r.right : scrollX;
3382            }
3383            if (y + h > dh + scrollY) {
3384                 y = swapY ? r.top-h : dh+scrollY-h;
3385             }
3386            if (y < scrollY){
3387                y = swapY ? r.bottom : scrollY;
3388            }
3389         }
3390         return [x,y];
3391     },
3392
3393     
3394     alignTo : function(element, position, offsets, animate){
3395             var me = this;
3396         return me.setXY(me.getAlignToXY(element, position, offsets),
3397                                 me.preanim && !!animate ? me.preanim(arguments, 3) : false);
3398     },
3399     
3400     
3401     adjustForConstraints : function(xy, parent, offsets){
3402         return this.getConstrainToXY(parent || document, false, offsets, xy) ||  xy;
3403     },
3404
3405     
3406     getConstrainToXY : function(el, local, offsets, proposedXY){   
3407             var os = {top:0, left:0, bottom:0, right: 0};
3408
3409         return function(el, local, offsets, proposedXY){
3410             el = Ext.get(el);
3411             offsets = offsets ? Ext.applyIf(offsets, os) : os;
3412
3413             var vw, vh, vx = 0, vy = 0;
3414             if(el.dom == document.body || el.dom == document){
3415                 vw =Ext.lib.Dom.getViewWidth();
3416                 vh = Ext.lib.Dom.getViewHeight();
3417             }else{
3418                 vw = el.dom.clientWidth;
3419                 vh = el.dom.clientHeight;
3420                 if(!local){
3421                     var vxy = el.getXY();
3422                     vx = vxy[0];
3423                     vy = vxy[1];
3424                 }
3425             }
3426
3427             var s = el.getScroll();
3428
3429             vx += offsets.left + s.left;
3430             vy += offsets.top + s.top;
3431
3432             vw -= offsets.right;
3433             vh -= offsets.bottom;
3434
3435             var vr = vx+vw;
3436             var vb = vy+vh;
3437
3438             var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
3439             var x = xy[0], y = xy[1];
3440             var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
3441
3442             
3443             var moved = false;
3444
3445             
3446             if((x + w) > vr){
3447                 x = vr - w;
3448                 moved = true;
3449             }
3450             if((y + h) > vb){
3451                 y = vb - h;
3452                 moved = true;
3453             }
3454             
3455             if(x < vx){
3456                 x = vx;
3457                 moved = true;
3458             }
3459             if(y < vy){
3460                 y = vy;
3461                 moved = true;
3462             }
3463             return moved ? [x, y] : false;
3464         };
3465     }(),
3466             
3467             
3468                 
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521     
3522     
3523     getCenterXY : function(){
3524         return this.getAlignToXY(document, 'c-c');
3525     },
3526
3527     
3528     center : function(centerIn){
3529         return this.alignTo(centerIn || document, 'c-c');        
3530     }    
3531 });
3532
3533 Ext.Element.addMethods(function(){
3534         var PARENTNODE = 'parentNode',
3535                 NEXTSIBLING = 'nextSibling',
3536                 PREVIOUSSIBLING = 'previousSibling',
3537                 DQ = Ext.DomQuery,
3538                 GET = Ext.get;
3539         
3540         return {
3541                 
3542             findParent : function(simpleSelector, maxDepth, returnEl){
3543                 var p = this.dom,
3544                         b = document.body, 
3545                         depth = 0,                      
3546                         stopEl;         
3547             if(Ext.isGecko && Object.prototype.toString.call(p) == '[object XULElement]') {
3548                 return null;
3549             }
3550                 maxDepth = maxDepth || 50;
3551                 if (isNaN(maxDepth)) {
3552                     stopEl = Ext.getDom(maxDepth);
3553                     maxDepth = Number.MAX_VALUE;
3554                 }
3555                 while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
3556                     if(DQ.is(p, simpleSelector)){
3557                         return returnEl ? GET(p) : p;
3558                     }
3559                     depth++;
3560                     p = p.parentNode;
3561                 }
3562                 return null;
3563             },
3564         
3565             
3566             findParentNode : function(simpleSelector, maxDepth, returnEl){
3567                 var p = Ext.fly(this.dom.parentNode, '_internal');
3568                 return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
3569             },
3570         
3571             
3572             up : function(simpleSelector, maxDepth){
3573                 return this.findParentNode(simpleSelector, maxDepth, true);
3574             },
3575         
3576             
3577             select : function(selector){
3578                 return Ext.Element.select(selector, this.dom);
3579             },
3580         
3581             
3582             query : function(selector){
3583                 return DQ.select(selector, this.dom);
3584             },
3585         
3586             
3587             child : function(selector, returnDom){
3588                 var n = DQ.selectNode(selector, this.dom);
3589                 return returnDom ? n : GET(n);
3590             },
3591         
3592             
3593             down : function(selector, returnDom){
3594                 var n = DQ.selectNode(" > " + selector, this.dom);
3595                 return returnDom ? n : GET(n);
3596             },
3597         
3598                  
3599             parent : function(selector, returnDom){
3600                 return this.matchNode(PARENTNODE, PARENTNODE, selector, returnDom);
3601             },
3602         
3603              
3604             next : function(selector, returnDom){
3605                 return this.matchNode(NEXTSIBLING, NEXTSIBLING, selector, returnDom);
3606             },
3607         
3608             
3609             prev : function(selector, returnDom){
3610                 return this.matchNode(PREVIOUSSIBLING, PREVIOUSSIBLING, selector, returnDom);
3611             },
3612         
3613         
3614             
3615             first : function(selector, returnDom){
3616                 return this.matchNode(NEXTSIBLING, 'firstChild', selector, returnDom);
3617             },
3618         
3619             
3620             last : function(selector, returnDom){
3621                 return this.matchNode(PREVIOUSSIBLING, 'lastChild', selector, returnDom);
3622             },
3623             
3624             matchNode : function(dir, start, selector, returnDom){
3625                 var n = this.dom[start];
3626                 while(n){
3627                     if(n.nodeType == 1 && (!selector || DQ.is(n, selector))){
3628                         return !returnDom ? GET(n) : n;
3629                     }
3630                     n = n[dir];
3631                 }
3632                 return null;
3633             }   
3634     }
3635 }());
3636 Ext.Element.addMethods({
3637     
3638     select : function(selector, unique){
3639         return Ext.Element.select(selector, unique, this.dom);
3640     }
3641 });
3642 Ext.Element.addMethods(
3643 function() {
3644         var GETDOM = Ext.getDom,
3645                 GET = Ext.get,
3646                 DH = Ext.DomHelper;
3647         
3648         return {
3649             
3650             appendChild: function(el){        
3651                 return GET(el).appendTo(this);        
3652             },
3653         
3654             
3655             appendTo: function(el){        
3656                 GETDOM(el).appendChild(this.dom);        
3657                 return this;
3658             },
3659         
3660             
3661             insertBefore: function(el){                   
3662                 (el = GETDOM(el)).parentNode.insertBefore(this.dom, el);
3663                 return this;
3664             },
3665         
3666             
3667             insertAfter: function(el){
3668                 (el = GETDOM(el)).parentNode.insertBefore(this.dom, el.nextSibling);
3669                 return this;
3670             },
3671         
3672             
3673             insertFirst: function(el, returnDom){
3674             el = el || {};
3675             if(el.nodeType || el.dom || typeof el == 'string'){ 
3676                 el = GETDOM(el);
3677                 this.dom.insertBefore(el, this.dom.firstChild);
3678                 return !returnDom ? GET(el) : el;
3679             }else{ 
3680                 return this.createChild(el, this.dom.firstChild, returnDom);
3681             }
3682         },
3683         
3684             
3685             replace: function(el){
3686                 el = GET(el);
3687                 this.insertBefore(el);
3688                 el.remove();
3689                 return this;
3690             },
3691         
3692             
3693             replaceWith: function(el){
3694                     var me = this;
3695                 
3696             if(el.nodeType || el.dom || typeof el == 'string'){
3697                 el = GETDOM(el);
3698                 me.dom.parentNode.insertBefore(el, me.dom);
3699             }else{
3700                 el = DH.insertBefore(me.dom, el);
3701             }
3702                 
3703                 delete Ext.elCache[me.id];
3704                 Ext.removeNode(me.dom);      
3705                 me.id = Ext.id(me.dom = el);
3706                 Ext.Element.addToCache(me.isFlyweight ? new Ext.Element(me.dom) : me);     
3707             return me;
3708             },
3709             
3710                 
3711                 createChild: function(config, insertBefore, returnDom){
3712                     config = config || {tag:'div'};
3713                     return insertBefore ? 
3714                            DH.insertBefore(insertBefore, config, returnDom !== true) :  
3715                            DH[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config,  returnDom !== true);
3716                 },
3717                 
3718                 
3719                 wrap: function(config, returnDom){        
3720                     var newEl = DH.insertBefore(this.dom, config || {tag: "div"}, !returnDom);
3721                     newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
3722                     return newEl;
3723                 },
3724                 
3725                 
3726                 insertHtml : function(where, html, returnEl){
3727                     var el = DH.insertHtml(where, this.dom, html);
3728                     return returnEl ? Ext.get(el) : el;
3729                 }
3730         }
3731 }());
3732 Ext.apply(Ext.Element.prototype, function() {
3733         var GETDOM = Ext.getDom,
3734                 GET = Ext.get,
3735                 DH = Ext.DomHelper;
3736         
3737         return {        
3738                 
3739             insertSibling: function(el, where, returnDom){
3740                 var me = this,
3741                         rt,
3742                 isAfter = (where || 'before').toLowerCase() == 'after',
3743                 insertEl;
3744                         
3745                 if(Ext.isArray(el)){
3746                 insertEl = me;
3747                     Ext.each(el, function(e) {
3748                             rt = Ext.fly(insertEl, '_internal').insertSibling(e, where, returnDom);
3749                     if(isAfter){
3750                         insertEl = rt;
3751                     }
3752                     });
3753                     return rt;
3754                 }
3755                         
3756                 el = el || {};
3757                 
3758             if(el.nodeType || el.dom){
3759                 rt = me.dom.parentNode.insertBefore(GETDOM(el), isAfter ? me.dom.nextSibling : me.dom);
3760                 if (!returnDom) {
3761                     rt = GET(rt);
3762                 }
3763             }else{
3764                 if (isAfter && !me.dom.nextSibling) {
3765                     rt = DH.append(me.dom.parentNode, el, !returnDom);
3766                 } else {                    
3767                     rt = DH[isAfter ? 'insertAfter' : 'insertBefore'](me.dom, el, !returnDom);
3768                 }
3769             }
3770                 return rt;
3771             }
3772     };
3773 }());
3774 Ext.Element.addMethods(function(){
3775     
3776     var propCache = {},
3777         camelRe = /(-[a-z])/gi,
3778         classReCache = {},
3779         view = document.defaultView,
3780         propFloat = Ext.isIE ? 'styleFloat' : 'cssFloat',
3781         opacityRe = /alpha\(opacity=(.*)\)/i,
3782         trimRe = /^\s+|\s+$/g,
3783         EL = Ext.Element,
3784         PADDING = "padding",
3785         MARGIN = "margin",
3786         BORDER = "border",
3787         LEFT = "-left",
3788         RIGHT = "-right",
3789         TOP = "-top",
3790         BOTTOM = "-bottom",
3791         WIDTH = "-width",
3792         MATH = Math,
3793         HIDDEN = 'hidden',
3794         ISCLIPPED = 'isClipped',
3795         OVERFLOW = 'overflow',
3796         OVERFLOWX = 'overflow-x',
3797         OVERFLOWY = 'overflow-y',
3798         ORIGINALCLIP = 'originalClip',
3799         
3800         borders = {l: BORDER + LEFT + WIDTH, r: BORDER + RIGHT + WIDTH, t: BORDER + TOP + WIDTH, b: BORDER + BOTTOM + WIDTH},
3801         paddings = {l: PADDING + LEFT, r: PADDING + RIGHT, t: PADDING + TOP, b: PADDING + BOTTOM},
3802         margins = {l: MARGIN + LEFT, r: MARGIN + RIGHT, t: MARGIN + TOP, b: MARGIN + BOTTOM},
3803         data = Ext.Element.data;
3804
3805
3806     
3807     function camelFn(m, a) {
3808         return a.charAt(1).toUpperCase();
3809     }
3810
3811     function chkCache(prop) {
3812         return propCache[prop] || (propCache[prop] = prop == 'float' ? propFloat : prop.replace(camelRe, camelFn));
3813     }
3814
3815     return {
3816         
3817         adjustWidth : function(width) {
3818             var me = this;
3819             var isNum = Ext.isNumber(width);
3820             if(isNum && me.autoBoxAdjust && !me.isBorderBox()){
3821                width -= (me.getBorderWidth("lr") + me.getPadding("lr"));
3822             }
3823             return (isNum && width < 0) ? 0 : width;
3824         },
3825
3826         
3827         adjustHeight : function(height) {
3828             var me = this;
3829             var isNum = Ext.isNumber(height);
3830             if(isNum && me.autoBoxAdjust && !me.isBorderBox()){
3831                height -= (me.getBorderWidth("tb") + me.getPadding("tb"));
3832             }
3833             return (isNum && height < 0) ? 0 : height;
3834         },
3835
3836
3837         
3838         addClass : function(className){
3839             var me = this, i, len, v;
3840             className = Ext.isArray(className) ? className : [className];
3841             for (i=0, len = className.length; i < len; i++) {
3842                 v = className[i];
3843                 if (v) {
3844                     me.dom.className += (!me.hasClass(v) && v ? " " + v : "");
3845                 };
3846             };
3847             return me;
3848         },
3849
3850         
3851         radioClass : function(className){
3852             var cn = this.dom.parentNode.childNodes, v;
3853             className = Ext.isArray(className) ? className : [className];
3854             for (var i=0, len = cn.length; i < len; i++) {
3855                 v = cn[i];
3856                 if(v && v.nodeType == 1) {
3857                     Ext.fly(v, '_internal').removeClass(className);
3858                 }
3859             };
3860             return this.addClass(className);
3861         },
3862
3863         
3864         removeClass : function(className){
3865             var me = this, v;
3866             className = Ext.isArray(className) ? className : [className];
3867             if (me.dom && me.dom.className) {
3868                 for (var i=0, len=className.length; i < len; i++) {
3869                     v = className[i];
3870                     if(v) {
3871                         me.dom.className = me.dom.className.replace(
3872                             classReCache[v] = classReCache[v] || new RegExp('(?:^|\\s+)' + v + '(?:\\s+|$)', "g"), " "
3873                         );
3874                     }
3875                 };
3876             }
3877             return me;
3878         },
3879
3880         
3881         toggleClass : function(className){
3882             return this.hasClass(className) ? this.removeClass(className) : this.addClass(className);
3883         },
3884
3885         
3886         hasClass : function(className){
3887             return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
3888         },
3889
3890         
3891         replaceClass : function(oldClassName, newClassName){
3892             return this.removeClass(oldClassName).addClass(newClassName);
3893         },
3894
3895         isStyle : function(style, val) {
3896             return this.getStyle(style) == val;
3897         },
3898
3899         
3900         getStyle : function(){
3901             return view && view.getComputedStyle ?
3902                 function(prop){
3903                     var el = this.dom,
3904                         v,
3905                         cs,
3906                         out,
3907                         display,
3908                         wk = Ext.isWebKit,
3909                         display;
3910                         
3911                     if(el == document){
3912                         return null;
3913                     }
3914                     prop = chkCache(prop);
3915                     
3916                     if(wk && /marginRight/.test(prop)){
3917                         display = this.getStyle('display');
3918                         el.style.display = 'inline-block';
3919                     }
3920                     out = (v = el.style[prop]) ? v :
3921                            (cs = view.getComputedStyle(el, "")) ? cs[prop] : null;
3922
3923                     
3924                     if(wk){
3925                         if(out == 'rgba(0, 0, 0, 0)'){
3926                             out = 'transparent';
3927                         }else if(display){
3928                             el.style.display = display;
3929                         }
3930                     }
3931                     return out;
3932                 } :
3933                 function(prop){
3934                     var el = this.dom,
3935                         m,
3936                         cs;
3937
3938                     if(el == document) return null;
3939                     if (prop == 'opacity') {
3940                         if (el.style.filter.match) {
3941                             if(m = el.style.filter.match(opacityRe)){
3942                                 var fv = parseFloat(m[1]);
3943                                 if(!isNaN(fv)){
3944                                     return fv ? fv / 100 : 0;
3945                                 }
3946                             }
3947                         }
3948                         return 1;
3949                     }
3950                     prop = chkCache(prop);
3951                     return el.style[prop] || ((cs = el.currentStyle) ? cs[prop] : null);
3952                 };
3953         }(),
3954
3955         
3956         getColor : function(attr, defaultValue, prefix){
3957             var v = this.getStyle(attr),
3958                 color = Ext.isDefined(prefix) ? prefix : '#',
3959                 h;
3960
3961             if(!v || /transparent|inherit/.test(v)){
3962                 return defaultValue;
3963             }
3964             if(/^r/.test(v)){
3965                 Ext.each(v.slice(4, v.length -1).split(','), function(s){
3966                     h = parseInt(s, 10);
3967                     color += (h < 16 ? '0' : '') + h.toString(16);
3968                 });
3969             }else{
3970                 v = v.replace('#', '');
3971                 color += v.length == 3 ? v.replace(/^(\w)(\w)(\w)$/, '$1$1$2$2$3$3') : v;
3972             }
3973             return(color.length > 5 ? color.toLowerCase() : defaultValue);
3974         },
3975
3976         
3977         setStyle : function(prop, value){
3978             var tmp,
3979                 style,
3980                 camel;
3981             if (!Ext.isObject(prop)) {
3982                 tmp = {};
3983                 tmp[prop] = value;
3984                 prop = tmp;
3985             }
3986             for (style in prop) {
3987                 value = prop[style];
3988                 style == 'opacity' ?
3989                     this.setOpacity(value) :
3990                     this.dom.style[chkCache(style)] = value;
3991             }
3992             return this;
3993         },
3994
3995         
3996          setOpacity : function(opacity, animate){
3997             var me = this,
3998                 s = me.dom.style;
3999
4000             if(!animate || !me.anim){
4001                 if(Ext.isIE){
4002                     var opac = opacity < 1 ? 'alpha(opacity=' + opacity * 100 + ')' : '',
4003                     val = s.filter.replace(opacityRe, '').replace(trimRe, '');
4004
4005                     s.zoom = 1;
4006                     s.filter = val + (val.length > 0 ? ' ' : '') + opac;
4007                 }else{
4008                     s.opacity = opacity;
4009                 }
4010             }else{
4011                 me.anim({opacity: {to: opacity}}, me.preanim(arguments, 1), null, .35, 'easeIn');
4012             }
4013             return me;
4014         },
4015
4016         
4017         clearOpacity : function(){
4018             var style = this.dom.style;
4019             if(Ext.isIE){
4020                 if(!Ext.isEmpty(style.filter)){
4021                     style.filter = style.filter.replace(opacityRe, '').replace(trimRe, '');
4022                 }
4023             }else{
4024                 style.opacity = style['-moz-opacity'] = style['-khtml-opacity'] = '';
4025             }
4026             return this;
4027         },
4028
4029         
4030         getHeight : function(contentHeight){
4031             var me = this,
4032                 dom = me.dom,
4033                 hidden = Ext.isIE && me.isStyle('display', 'none'),
4034                 h = MATH.max(dom.offsetHeight, hidden ? 0 : dom.clientHeight) || 0;
4035
4036             h = !contentHeight ? h : h - me.getBorderWidth("tb") - me.getPadding("tb");
4037             return h < 0 ? 0 : h;
4038         },
4039
4040         
4041         getWidth : function(contentWidth){
4042             var me = this,
4043                 dom = me.dom,
4044                 hidden = Ext.isIE && me.isStyle('display', 'none'),
4045                 w = MATH.max(dom.offsetWidth, hidden ? 0 : dom.clientWidth) || 0;
4046             w = !contentWidth ? w : w - me.getBorderWidth("lr") - me.getPadding("lr");
4047             return w < 0 ? 0 : w;
4048         },
4049
4050         
4051         setWidth : function(width, animate){
4052             var me = this;
4053             width = me.adjustWidth(width);
4054             !animate || !me.anim ?
4055                 me.dom.style.width = me.addUnits(width) :
4056                 me.anim({width : {to : width}}, me.preanim(arguments, 1));
4057             return me;
4058         },
4059
4060         
4061          setHeight : function(height, animate){
4062             var me = this;
4063             height = me.adjustHeight(height);
4064             !animate || !me.anim ?
4065                 me.dom.style.height = me.addUnits(height) :
4066                 me.anim({height : {to : height}}, me.preanim(arguments, 1));
4067             return me;
4068         },
4069
4070         
4071         getBorderWidth : function(side){
4072             return this.addStyles(side, borders);
4073         },
4074
4075         
4076         getPadding : function(side){
4077             return this.addStyles(side, paddings);
4078         },
4079
4080         
4081         clip : function(){
4082             var me = this,
4083                 dom = me.dom;
4084
4085             if(!data(dom, ISCLIPPED)){
4086                 data(dom, ISCLIPPED, true);
4087                 data(dom, ORIGINALCLIP, {
4088                     o: me.getStyle(OVERFLOW),
4089                     x: me.getStyle(OVERFLOWX),
4090                     y: me.getStyle(OVERFLOWY)
4091                 });
4092                 me.setStyle(OVERFLOW, HIDDEN);
4093                 me.setStyle(OVERFLOWX, HIDDEN);
4094                 me.setStyle(OVERFLOWY, HIDDEN);
4095             }
4096             return me;
4097         },
4098
4099         
4100         unclip : function(){
4101             var me = this,
4102                 dom = me.dom;
4103
4104             if(data(dom, ISCLIPPED)){
4105                 data(dom, ISCLIPPED, false);
4106                 var o = data(dom, ORIGINALCLIP);
4107                 if(o.o){
4108                     me.setStyle(OVERFLOW, o.o);
4109                 }
4110                 if(o.x){
4111                     me.setStyle(OVERFLOWX, o.x);
4112                 }
4113                 if(o.y){
4114                     me.setStyle(OVERFLOWY, o.y);
4115                 }
4116             }
4117             return me;
4118         },
4119
4120         
4121         addStyles : function(sides, styles){
4122             var val = 0,
4123                 m = sides.match(/\w/g),
4124                 s;
4125             for (var i=0, len=m.length; i<len; i++) {
4126                 s = m[i] && parseInt(this.getStyle(styles[m[i]]), 10);
4127                 if (s) {
4128                     val += MATH.abs(s);
4129                 }
4130             }
4131             return val;
4132         },
4133
4134         margins : margins
4135     }
4136 }()
4137 );
4138
4139
4140
4141 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>';
4142
4143 Ext.Element.addMethods(function(){
4144     var INTERNAL = "_internal",
4145         pxMatch = /(\d+)px/;
4146     return {
4147         
4148         applyStyles : function(style){
4149             Ext.DomHelper.applyStyles(this.dom, style);
4150             return this;
4151         },
4152
4153         
4154         getStyles : function(){
4155             var ret = {};
4156             Ext.each(arguments, function(v) {
4157                ret[v] = this.getStyle(v);
4158             },
4159             this);
4160             return ret;
4161         },
4162
4163         
4164         getStyleSize : function(){
4165             var me = this,
4166                 w,
4167                 h,
4168                 d = this.dom,
4169                 s = d.style;
4170             if(s.width && s.width != 'auto'){
4171                 w = parseInt(s.width, 10);
4172                 if(me.isBorderBox()){
4173                    w -= me.getFrameWidth('lr');
4174                 }
4175             }
4176             if(s.height && s.height != 'auto'){
4177                 h = parseInt(s.height, 10);
4178                 if(me.isBorderBox()){
4179                    h -= me.getFrameWidth('tb');
4180                 }
4181             }
4182             return {width: w || me.getWidth(true), height: h || me.getHeight(true)};
4183         },
4184
4185         
4186         setOverflow : function(v){
4187             var dom = this.dom;
4188             if(v=='auto' && Ext.isMac && Ext.isGecko2){ 
4189                 dom.style.overflow = 'hidden';
4190                 (function(){dom.style.overflow = 'auto';}).defer(1);
4191             }else{
4192                 dom.style.overflow = v;
4193             }
4194         },
4195
4196        
4197         boxWrap : function(cls){
4198             cls = cls || 'x-box';
4199             var el = Ext.get(this.insertHtml("beforeBegin", "<div class='" + cls + "'>" + String.format(Ext.Element.boxMarkup, cls) + "</div>"));        
4200             Ext.DomQuery.selectNode('.' + cls + '-mc', el.dom).appendChild(this.dom);
4201             return el;
4202         },
4203
4204         
4205         setSize : function(width, height, animate){
4206             var me = this;
4207             if(Ext.isObject(width)){ 
4208                 height = width.height;
4209                 width = width.width;
4210             }
4211             width = me.adjustWidth(width);
4212             height = me.adjustHeight(height);
4213             if(!animate || !me.anim){
4214                 me.dom.style.width = me.addUnits(width);
4215                 me.dom.style.height = me.addUnits(height);
4216             }else{
4217                 me.anim({width: {to: width}, height: {to: height}}, me.preanim(arguments, 2));
4218             }
4219             return me;
4220         },
4221
4222         
4223         getComputedHeight : function(){
4224             var me = this,
4225                 h = Math.max(me.dom.offsetHeight, me.dom.clientHeight);
4226             if(!h){
4227                 h = parseInt(me.getStyle('height'), 10) || 0;
4228                 if(!me.isBorderBox()){
4229                     h += me.getFrameWidth('tb');
4230                 }
4231             }
4232             return h;
4233         },
4234
4235         
4236         getComputedWidth : function(){
4237             var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
4238             if(!w){
4239                 w = parseInt(this.getStyle('width'), 10) || 0;
4240                 if(!this.isBorderBox()){
4241                     w += this.getFrameWidth('lr');
4242                 }
4243             }
4244             return w;
4245         },
4246
4247         
4248         getFrameWidth : function(sides, onlyContentBox){
4249             return onlyContentBox && this.isBorderBox() ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
4250         },
4251
4252         
4253         addClassOnOver : function(className){
4254             this.hover(
4255                 function(){
4256                     Ext.fly(this, INTERNAL).addClass(className);
4257                 },
4258                 function(){
4259                     Ext.fly(this, INTERNAL).removeClass(className);
4260                 }
4261             );
4262             return this;
4263         },
4264
4265         
4266         addClassOnFocus : function(className){
4267             this.on("focus", function(){
4268                 Ext.fly(this, INTERNAL).addClass(className);
4269             }, this.dom);
4270             this.on("blur", function(){
4271                 Ext.fly(this, INTERNAL).removeClass(className);
4272             }, this.dom);
4273             return this;
4274         },
4275
4276         
4277         addClassOnClick : function(className){
4278             var dom = this.dom;
4279             this.on("mousedown", function(){
4280                 Ext.fly(dom, INTERNAL).addClass(className);
4281                 var d = Ext.getDoc(),
4282                     fn = function(){
4283                         Ext.fly(dom, INTERNAL).removeClass(className);
4284                         d.removeListener("mouseup", fn);
4285                     };
4286                 d.on("mouseup", fn);
4287             });
4288             return this;
4289         },
4290
4291         
4292         getViewSize : function(contentBox){
4293             var doc = document,
4294                 me = this,
4295                 d = me.dom,
4296                 extdom = Ext.lib.Dom,
4297                 isDoc = (d == doc || d == doc.body),
4298                 isBB, w, h, tbBorder = 0, lrBorder = 0,
4299                 tbPadding = 0, lrPadding = 0;
4300             if (isDoc) {
4301                 return { width: extdom.getViewWidth(), height: extdom.getViewHeight() };
4302             }
4303             isBB = me.isBorderBox();
4304             tbBorder = me.getBorderWidth('tb');
4305             lrBorder = me.getBorderWidth('lr');
4306             tbPadding = me.getPadding('tb');
4307             lrPadding = me.getPadding('lr');
4308
4309             
4310             
4311             if (w = me.getStyle('width').match(pxMatch)){
4312                 if ((w = parseInt(w[1], 10)) && isBB){
4313                     
4314                     w -= (lrBorder + lrPadding);
4315                 }
4316                 if (!contentBox){
4317                     w += lrPadding;
4318                 }
4319             } else {
4320                 if (!(w = d.clientWidth) && (w = d.offsetWidth)){
4321                     w -= lrBorder;
4322                 }
4323                 if (w && contentBox){
4324                     w -= lrPadding;
4325                 }
4326             }
4327
4328             
4329             
4330             if (h = me.getStyle('height').match(pxMatch)){
4331                 if ((h = parseInt(h[1], 10)) && isBB){
4332                     
4333                     h -= (tbBorder + tbPadding);
4334                 }
4335                 if (!contentBox){
4336                     h += tbPadding;
4337                 }
4338             } else {
4339                 if (!(h = d.clientHeight) && (h = d.offsetHeight)){
4340                     h -= tbBorder;
4341                 }
4342                 if (h && contentBox){
4343                     h -= tbPadding;
4344                 }
4345             }
4346
4347             return {
4348                 width : w,
4349                 height : h
4350             };
4351         },
4352
4353         
4354         getSize : function(contentSize){
4355             return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
4356         },
4357
4358         
4359         repaint : function(){
4360             var dom = this.dom;
4361             this.addClass("x-repaint");
4362             setTimeout(function(){
4363                 Ext.fly(dom).removeClass("x-repaint");
4364             }, 1);
4365             return this;
4366         },
4367
4368         
4369         unselectable : function(){
4370             this.dom.unselectable = "on";
4371             return this.swallowEvent("selectstart", true).
4372                         applyStyles("-moz-user-select:none;-khtml-user-select:none;").
4373                         addClass("x-unselectable");
4374         },
4375
4376         
4377         getMargins : function(side){
4378             var me = this,
4379                 key,
4380                 hash = {t:"top", l:"left", r:"right", b: "bottom"},
4381                 o = {};
4382
4383             if (!side) {
4384                 for (key in me.margins){
4385                     o[hash[key]] = parseInt(me.getStyle(me.margins[key]), 10) || 0;
4386                 }
4387                 return o;
4388             } else {
4389                 return me.addStyles.call(me, side, me.margins);
4390             }
4391         }
4392     };
4393 }());
4394
4395 (function(){
4396 var D = Ext.lib.Dom,
4397         LEFT = "left",
4398         RIGHT = "right",
4399         TOP = "top",
4400         BOTTOM = "bottom",
4401         POSITION = "position",
4402         STATIC = "static",
4403         RELATIVE = "relative",
4404         AUTO = "auto",
4405         ZINDEX = "z-index";
4406
4407 Ext.Element.addMethods({
4408         
4409     getX : function(){
4410         return D.getX(this.dom);
4411     },
4412
4413     
4414     getY : function(){
4415         return D.getY(this.dom);
4416     },
4417
4418     
4419     getXY : function(){
4420         return D.getXY(this.dom);
4421     },
4422
4423     
4424     getOffsetsTo : function(el){
4425         var o = this.getXY(),
4426                 e = Ext.fly(el, '_internal').getXY();
4427         return [o[0]-e[0],o[1]-e[1]];
4428     },
4429
4430     
4431     setX : function(x, animate){            
4432             return this.setXY([x, this.getY()], this.animTest(arguments, animate, 1));
4433     },
4434
4435     
4436     setY : function(y, animate){            
4437             return this.setXY([this.getX(), y], this.animTest(arguments, animate, 1));
4438     },
4439
4440     
4441     setLeft : function(left){
4442         this.setStyle(LEFT, this.addUnits(left));
4443         return this;
4444     },
4445
4446     
4447     setTop : function(top){
4448         this.setStyle(TOP, this.addUnits(top));
4449         return this;
4450     },
4451
4452     
4453     setRight : function(right){
4454         this.setStyle(RIGHT, this.addUnits(right));
4455         return this;
4456     },
4457
4458     
4459     setBottom : function(bottom){
4460         this.setStyle(BOTTOM, this.addUnits(bottom));
4461         return this;
4462     },
4463
4464     
4465     setXY : function(pos, animate){
4466             var me = this;
4467         if(!animate || !me.anim){
4468             D.setXY(me.dom, pos);
4469         }else{
4470             me.anim({points: {to: pos}}, me.preanim(arguments, 1), 'motion');
4471         }
4472         return me;
4473     },
4474
4475     
4476     setLocation : function(x, y, animate){
4477         return this.setXY([x, y], this.animTest(arguments, animate, 2));
4478     },
4479
4480     
4481     moveTo : function(x, y, animate){
4482         return this.setXY([x, y], this.animTest(arguments, animate, 2));        
4483     },    
4484     
4485     
4486     getLeft : function(local){
4487             return !local ? this.getX() : parseInt(this.getStyle(LEFT), 10) || 0;
4488     },
4489
4490     
4491     getRight : function(local){
4492             var me = this;
4493             return !local ? me.getX() + me.getWidth() : (me.getLeft(true) + me.getWidth()) || 0;
4494     },
4495
4496     
4497     getTop : function(local) {
4498             return !local ? this.getY() : parseInt(this.getStyle(TOP), 10) || 0;
4499     },
4500
4501     
4502     getBottom : function(local){
4503             var me = this;
4504             return !local ? me.getY() + me.getHeight() : (me.getTop(true) + me.getHeight()) || 0;
4505     },
4506
4507     
4508     position : function(pos, zIndex, x, y){
4509             var me = this;
4510             
4511         if(!pos && me.isStyle(POSITION, STATIC)){           
4512             me.setStyle(POSITION, RELATIVE);           
4513         } else if(pos) {
4514             me.setStyle(POSITION, pos);
4515         }
4516         if(zIndex){
4517             me.setStyle(ZINDEX, zIndex);
4518         }
4519         if(x || y) me.setXY([x || false, y || false]);
4520     },
4521
4522     
4523     clearPositioning : function(value){
4524         value = value || '';
4525         this.setStyle({
4526             left : value,
4527             right : value,
4528             top : value,
4529             bottom : value,
4530             "z-index" : "",
4531             position : STATIC
4532         });
4533         return this;
4534     },
4535
4536     
4537     getPositioning : function(){
4538         var l = this.getStyle(LEFT);
4539         var t = this.getStyle(TOP);
4540         return {
4541             "position" : this.getStyle(POSITION),
4542             "left" : l,
4543             "right" : l ? "" : this.getStyle(RIGHT),
4544             "top" : t,
4545             "bottom" : t ? "" : this.getStyle(BOTTOM),
4546             "z-index" : this.getStyle(ZINDEX)
4547         };
4548     },
4549     
4550     
4551     setPositioning : function(pc){
4552             var me = this,
4553                 style = me.dom.style;
4554                 
4555         me.setStyle(pc);
4556         
4557         if(pc.right == AUTO){
4558             style.right = "";
4559         }
4560         if(pc.bottom == AUTO){
4561             style.bottom = "";
4562         }
4563         
4564         return me;
4565     },    
4566         
4567     
4568     translatePoints : function(x, y){                
4569             y = isNaN(x[1]) ? y : x[1];
4570         x = isNaN(x[0]) ? x : x[0];
4571         var me = this,
4572                 relative = me.isStyle(POSITION, RELATIVE),
4573                 o = me.getXY(),
4574                 l = parseInt(me.getStyle(LEFT), 10),
4575                 t = parseInt(me.getStyle(TOP), 10);
4576         
4577         l = !isNaN(l) ? l : (relative ? 0 : me.dom.offsetLeft);
4578         t = !isNaN(t) ? t : (relative ? 0 : me.dom.offsetTop);        
4579
4580         return {left: (x - o[0] + l), top: (y - o[1] + t)}; 
4581     },
4582     
4583     animTest : function(args, animate, i) {
4584         return !!animate && this.preanim ? this.preanim(args, i) : false;
4585     }
4586 });
4587 })();
4588 Ext.Element.addMethods({
4589     
4590     setBox : function(box, adjust, animate){
4591         var me = this,
4592                 w = box.width, 
4593                 h = box.height;
4594         if((adjust && !me.autoBoxAdjust) && !me.isBorderBox()){
4595            w -= (me.getBorderWidth("lr") + me.getPadding("lr"));
4596            h -= (me.getBorderWidth("tb") + me.getPadding("tb"));
4597         }
4598         me.setBounds(box.x, box.y, w, h, me.animTest.call(me, arguments, animate, 2));
4599         return me;
4600     },
4601
4602     
4603         getBox : function(contentBox, local) {      
4604             var me = this,
4605                 xy,
4606                 left,
4607                 top,
4608                 getBorderWidth = me.getBorderWidth,
4609                 getPadding = me.getPadding, 
4610                 l,
4611                 r,
4612                 t,
4613                 b;
4614         if(!local){
4615             xy = me.getXY();
4616         }else{
4617             left = parseInt(me.getStyle("left"), 10) || 0;
4618             top = parseInt(me.getStyle("top"), 10) || 0;
4619             xy = [left, top];
4620         }
4621         var el = me.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
4622         if(!contentBox){
4623             bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
4624         }else{
4625             l = getBorderWidth.call(me, "l") + getPadding.call(me, "l");
4626             r = getBorderWidth.call(me, "r") + getPadding.call(me, "r");
4627             t = getBorderWidth.call(me, "t") + getPadding.call(me, "t");
4628             b = getBorderWidth.call(me, "b") + getPadding.call(me, "b");
4629             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)};
4630         }
4631         bx.right = bx.x + bx.width;
4632         bx.bottom = bx.y + bx.height;
4633         return bx;
4634         },
4635         
4636     
4637      move : function(direction, distance, animate){
4638         var me = this,          
4639                 xy = me.getXY(),
4640                 x = xy[0],
4641                 y = xy[1],              
4642                 left = [x - distance, y],
4643                 right = [x + distance, y],
4644                 top = [x, y - distance],
4645                 bottom = [x, y + distance],
4646                 hash = {
4647                         l :     left,
4648                         left : left,
4649                         r : right,
4650                         right : right,
4651                         t : top,
4652                         top : top,
4653                         up : top,
4654                         b : bottom, 
4655                         bottom : bottom,
4656                         down : bottom                           
4657                 };
4658         
4659             direction = direction.toLowerCase();    
4660             me.moveTo(hash[direction][0], hash[direction][1], me.animTest.call(me, arguments, animate, 2));
4661     },
4662     
4663     
4664      setLeftTop : function(left, top){
4665             var me = this,
4666                 style = me.dom.style;
4667         style.left = me.addUnits(left);
4668         style.top = me.addUnits(top);
4669         return me;
4670     },
4671     
4672     
4673     getRegion : function(){
4674         return Ext.lib.Dom.getRegion(this.dom);
4675     },
4676     
4677     
4678     setBounds : function(x, y, width, height, animate){
4679             var me = this;
4680         if (!animate || !me.anim) {
4681             me.setSize(width, height);
4682             me.setLocation(x, y);
4683         } else {
4684             me.anim({points: {to: [x, y]}, 
4685                          width: {to: me.adjustWidth(width)}, 
4686                          height: {to: me.adjustHeight(height)}},
4687                      me.preanim(arguments, 4), 
4688                      'motion');
4689         }
4690         return me;
4691     },
4692
4693     
4694     setRegion : function(region, animate) {
4695         return this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.animTest.call(this, arguments, animate, 1));
4696     }
4697 });
4698 Ext.Element.addMethods({
4699     
4700     isScrollable : function(){
4701         var dom = this.dom;
4702         return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
4703     },
4704
4705     
4706     scrollTo : function(side, value){
4707         this.dom["scroll" + (/top/i.test(side) ? "Top" : "Left")] = value;
4708         return this;
4709     },
4710
4711     
4712     getScroll : function(){
4713         var d = this.dom, 
4714             doc = document,
4715             body = doc.body,
4716             docElement = doc.documentElement,
4717             l,
4718             t,
4719             ret;
4720
4721         if(d == doc || d == body){
4722             if(Ext.isIE && Ext.isStrict){
4723                 l = docElement.scrollLeft; 
4724                 t = docElement.scrollTop;
4725             }else{
4726                 l = window.pageXOffset;
4727                 t = window.pageYOffset;
4728             }
4729             ret = {left: l || (body ? body.scrollLeft : 0), top: t || (body ? body.scrollTop : 0)};
4730         }else{
4731             ret = {left: d.scrollLeft, top: d.scrollTop};
4732         }
4733         return ret;
4734     }
4735 });
4736 Ext.Element.addMethods({
4737     
4738     scrollTo : function(side, value, animate){
4739         var top = /top/i.test(side), 
4740                 me = this,
4741                 dom = me.dom,
4742             prop;
4743         if (!animate || !me.anim) {
4744             prop = 'scroll' + (top ? 'Top' : 'Left'), 
4745             dom[prop] = value;
4746         }else{
4747             prop = 'scroll' + (top ? 'Left' : 'Top'), 
4748             me.anim({scroll: {to: top ? [dom[prop], value] : [value, dom[prop]]}},
4749                          me.preanim(arguments, 2), 'scroll');
4750         }
4751         return me;
4752     },
4753     
4754     
4755     scrollIntoView : function(container, hscroll){
4756         var c = Ext.getDom(container) || Ext.getBody().dom,
4757                 el = this.dom,
4758                 o = this.getOffsetsTo(c),
4759             l = o[0] + c.scrollLeft,
4760             t = o[1] + c.scrollTop,
4761             b = t + el.offsetHeight,
4762             r = l + el.offsetWidth,
4763                 ch = c.clientHeight,
4764                 ct = parseInt(c.scrollTop, 10),
4765                 cl = parseInt(c.scrollLeft, 10),
4766                 cb = ct + ch,
4767                 cr = cl + c.clientWidth;
4768
4769         if (el.offsetHeight > ch || t < ct) {
4770                 c.scrollTop = t;
4771         } else if (b > cb){
4772             c.scrollTop = b-ch;
4773         }
4774         c.scrollTop = c.scrollTop; 
4775
4776         if(hscroll !== false){
4777                         if(el.offsetWidth > c.clientWidth || l < cl){
4778                 c.scrollLeft = l;
4779             }else if(r > cr){
4780                 c.scrollLeft = r - c.clientWidth;
4781             }
4782             c.scrollLeft = c.scrollLeft;
4783         }
4784         return this;
4785     },
4786
4787     
4788     scrollChildIntoView : function(child, hscroll){
4789         Ext.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
4790     },
4791     
4792     
4793      scroll : function(direction, distance, animate){
4794          if(!this.isScrollable()){
4795              return;
4796          }
4797          var el = this.dom,
4798             l = el.scrollLeft, t = el.scrollTop,
4799             w = el.scrollWidth, h = el.scrollHeight,
4800             cw = el.clientWidth, ch = el.clientHeight,
4801             scrolled = false, v,
4802             hash = {
4803                 l: Math.min(l + distance, w-cw),
4804                 r: v = Math.max(l - distance, 0),
4805                 t: Math.max(t - distance, 0),
4806                 b: Math.min(t + distance, h-ch)
4807             };
4808             hash.d = hash.b;
4809             hash.u = hash.t;
4810             
4811          direction = direction.substr(0, 1);
4812          if((v = hash[direction]) > -1){
4813             scrolled = true;
4814             this.scrollTo(direction == 'l' || direction == 'r' ? 'left' : 'top', v, this.preanim(arguments, 2));
4815          }
4816          return scrolled;
4817     }
4818 });
4819
4820 Ext.Element.VISIBILITY = 1;
4821
4822 Ext.Element.DISPLAY = 2;
4823
4824 Ext.Element.addMethods(function(){
4825     var VISIBILITY = "visibility",
4826         DISPLAY = "display",
4827         HIDDEN = "hidden",
4828         NONE = "none",      
4829         ORIGINALDISPLAY = 'originalDisplay',
4830         VISMODE = 'visibilityMode',
4831         ELDISPLAY = Ext.Element.DISPLAY,
4832         data = Ext.Element.data,
4833         getDisplay = function(dom){
4834             var d = data(dom, ORIGINALDISPLAY);
4835             if(d === undefined){
4836                 data(dom, ORIGINALDISPLAY, d = '');
4837             }
4838             return d;
4839         },
4840         getVisMode = function(dom){
4841             var m = data(dom, VISMODE);
4842             if(m === undefined){
4843                 data(dom, VISMODE, m = 1)
4844             }
4845             return m;
4846         };
4847     
4848     return {
4849         
4850         originalDisplay : "",
4851         visibilityMode : 1,
4852         
4853         
4854         setVisibilityMode : function(visMode){  
4855             data(this.dom, VISMODE, visMode);
4856             return this;
4857         },
4858         
4859         
4860         animate : function(args, duration, onComplete, easing, animType){       
4861             this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
4862             return this;
4863         },
4864     
4865         
4866         anim : function(args, opt, animType, defaultDur, defaultEase, cb){
4867             animType = animType || 'run';
4868             opt = opt || {};
4869             var me = this,              
4870                 anim = Ext.lib.Anim[animType](
4871                     me.dom, 
4872                     args,
4873                     (opt.duration || defaultDur) || .35,
4874                     (opt.easing || defaultEase) || 'easeOut',
4875                     function(){
4876                         if(cb) cb.call(me);
4877                         if(opt.callback) opt.callback.call(opt.scope || me, me, opt);
4878                     },
4879                     me
4880                 );
4881             opt.anim = anim;
4882             return anim;
4883         },
4884     
4885         
4886         preanim : function(a, i){
4887             return !a[i] ? false : (Ext.isObject(a[i]) ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
4888         },
4889         
4890         
4891         isVisible : function() {
4892             return !this.isStyle(VISIBILITY, HIDDEN) && !this.isStyle(DISPLAY, NONE);
4893         },
4894         
4895         
4896          setVisible : function(visible, animate){
4897             var me = this,
4898                 dom = me.dom,
4899                 isDisplay = getVisMode(this.dom) == ELDISPLAY;
4900                 
4901             if (!animate || !me.anim) {
4902                 if(isDisplay){
4903                     me.setDisplayed(visible);
4904                 }else{
4905                     me.fixDisplay();
4906                     dom.style.visibility = visible ? "visible" : HIDDEN;
4907                 }
4908             }else{
4909                 
4910                 if(visible){
4911                     me.setOpacity(.01);
4912                     me.setVisible(true);
4913                 }
4914                 me.anim({opacity: { to: (visible?1:0) }},
4915                         me.preanim(arguments, 1),
4916                         null,
4917                         .35,
4918                         'easeIn',
4919                         function(){
4920                              if(!visible){
4921                                  dom.style[isDisplay ? DISPLAY : VISIBILITY] = (isDisplay) ? NONE : HIDDEN;                     
4922                                  Ext.fly(dom).setOpacity(1);
4923                              }
4924                         });
4925             }
4926             return me;
4927         },
4928     
4929         
4930         toggle : function(animate){
4931             var me = this;
4932             me.setVisible(!me.isVisible(), me.preanim(arguments, 0));
4933             return me;
4934         },
4935     
4936         
4937         setDisplayed : function(value) {            
4938             if(typeof value == "boolean"){
4939                value = value ? getDisplay(this.dom) : NONE;
4940             }
4941             this.setStyle(DISPLAY, value);
4942             return this;
4943         },
4944         
4945         
4946         fixDisplay : function(){
4947             var me = this;
4948             if(me.isStyle(DISPLAY, NONE)){
4949                 me.setStyle(VISIBILITY, HIDDEN);
4950                 me.setStyle(DISPLAY, getDisplay(this.dom)); 
4951                 if(me.isStyle(DISPLAY, NONE)){ 
4952                     me.setStyle(DISPLAY, "block");
4953                 }
4954             }
4955         },
4956     
4957         
4958         hide : function(animate){
4959             this.setVisible(false, this.preanim(arguments, 0));
4960             return this;
4961         },
4962     
4963         
4964         show : function(animate){
4965             this.setVisible(true, this.preanim(arguments, 0));
4966             return this;
4967         }
4968     }
4969 }());
4970 Ext.Element.addMethods(
4971 function(){
4972     var VISIBILITY = "visibility",
4973         DISPLAY = "display",
4974         HIDDEN = "hidden",
4975         NONE = "none",
4976             XMASKED = "x-masked",
4977                 XMASKEDRELATIVE = "x-masked-relative",
4978         data = Ext.Element.data;
4979                 
4980         return {
4981                 
4982             isVisible : function(deep) {
4983                 var vis = !this.isStyle(VISIBILITY,HIDDEN) && !this.isStyle(DISPLAY,NONE),
4984                         p = this.dom.parentNode;
4985                 if(deep !== true || !vis){
4986                     return vis;
4987                 }               
4988                 while(p && !/body/i.test(p.tagName)){
4989                     if(!Ext.fly(p, '_isVisible').isVisible()){
4990                         return false;
4991                     }
4992                     p = p.parentNode;
4993                 }
4994                 return true;
4995             },
4996             
4997             
4998             isDisplayed : function() {
4999                 return !this.isStyle(DISPLAY, NONE);
5000             },
5001             
5002                 
5003             enableDisplayMode : function(display){          
5004                 this.setVisibilityMode(Ext.Element.DISPLAY);
5005                 if(!Ext.isEmpty(display)){
5006                 data(this.dom, 'originalDisplay', display);
5007             }
5008                 return this;
5009             },
5010             
5011                 
5012             mask : function(msg, msgCls){
5013                     var me = this,
5014                         dom = me.dom,
5015                         dh = Ext.DomHelper,
5016                         EXTELMASKMSG = "ext-el-mask-msg",
5017                 el, 
5018                 mask;
5019                         
5020                 if(me.getStyle("position") == "static"){
5021                     me.addClass(XMASKEDRELATIVE);
5022                 }
5023                 if((el = data(dom, 'maskMsg'))){
5024                     el.remove();
5025                 }
5026                 if((el = data(dom, 'mask'))){
5027                     el.remove();
5028                 }
5029         
5030             mask = dh.append(dom, {cls : "ext-el-mask"}, true);
5031                 data(dom, 'mask', mask);
5032         
5033                 me.addClass(XMASKED);
5034                 mask.setDisplayed(true);
5035                 if(typeof msg == 'string'){
5036                 var mm = dh.append(dom, {cls : EXTELMASKMSG, cn:{tag:'div'}}, true);
5037                 data(dom, 'maskMsg', mm);
5038                     mm.dom.className = msgCls ? EXTELMASKMSG + " " + msgCls : EXTELMASKMSG;
5039                     mm.dom.firstChild.innerHTML = msg;
5040                     mm.setDisplayed(true);
5041                     mm.center(me);
5042                 }
5043                 if(Ext.isIE && !(Ext.isIE7 && Ext.isStrict) && me.getStyle('height') == 'auto'){ 
5044                     mask.setSize(undefined, me.getHeight());
5045                 }
5046                 return mask;
5047             },
5048         
5049             
5050             unmask : function(){
5051                     var me = this,
5052                 dom = me.dom,
5053                         mask = data(dom, 'mask'),
5054                         maskMsg = data(dom, 'maskMsg');
5055                 if(mask){
5056                     if(maskMsg){
5057                         maskMsg.remove();
5058                     data(dom, 'maskMsg', undefined);
5059                     }
5060                     mask.remove();
5061                 data(dom, 'mask', undefined);
5062                 }
5063                 me.removeClass([XMASKED, XMASKEDRELATIVE]);
5064             },
5065         
5066             
5067             isMasked : function(){
5068             var m = data(this.dom, 'mask');
5069                 return m && m.isVisible();
5070             },
5071             
5072             
5073             createShim : function(){
5074                 var el = document.createElement('iframe'),              
5075                         shim;
5076                 el.frameBorder = '0';
5077                 el.className = 'ext-shim';
5078                 el.src = Ext.SSL_SECURE_URL;
5079                 shim = Ext.get(this.dom.parentNode.insertBefore(el, this.dom));
5080                 shim.autoBoxAdjust = false;
5081                 return shim;
5082             }
5083     };
5084 }());
5085 Ext.Element.addMethods({
5086     
5087     addKeyListener : function(key, fn, scope){
5088         var config;
5089         if(!Ext.isObject(key) || Ext.isArray(key)){
5090             config = {
5091                 key: key,
5092                 fn: fn,
5093                 scope: scope
5094             };
5095         }else{
5096             config = {
5097                 key : key.key,
5098                 shift : key.shift,
5099                 ctrl : key.ctrl,
5100                 alt : key.alt,
5101                 fn: fn,
5102                 scope: scope
5103             };
5104         }
5105         return new Ext.KeyMap(this, config);
5106     },
5107
5108     
5109     addKeyMap : function(config){
5110         return new Ext.KeyMap(this, config);
5111     }
5112 });(function(){
5113     
5114     var NULL = null,
5115         UNDEFINED = undefined,
5116         TRUE = true,
5117         FALSE = false,
5118         SETX = "setX",
5119         SETY = "setY",
5120         SETXY = "setXY",
5121         LEFT = "left",
5122         BOTTOM = "bottom",
5123         TOP = "top",
5124         RIGHT = "right",
5125         HEIGHT = "height",
5126         WIDTH = "width",
5127         POINTS = "points",
5128         HIDDEN = "hidden",
5129         ABSOLUTE = "absolute",
5130         VISIBLE = "visible",
5131         MOTION = "motion",
5132         POSITION = "position",
5133         EASEOUT = "easeOut",
5134         
5135         flyEl = new Ext.Element.Flyweight(),
5136         queues = {},
5137         getObject = function(o){
5138             return o || {};
5139         },
5140         fly = function(dom){
5141             flyEl.dom = dom;
5142             flyEl.id = Ext.id(dom);
5143             return flyEl;
5144         },
5145         
5146         getQueue = function(id){
5147             if(!queues[id]){
5148                 queues[id] = [];
5149             }
5150             return queues[id];
5151         },
5152         setQueue = function(id, value){
5153             queues[id] = value;
5154         };
5155         
5156
5157 Ext.enableFx = TRUE;
5158
5159
5160 Ext.Fx = {
5161     
5162     
5163     
5164     switchStatements : function(key, fn, argHash){
5165         return fn.apply(this, argHash[key]);
5166     },
5167     
5168     
5169     slideIn : function(anchor, o){ 
5170         o = getObject(o);
5171         var me = this,
5172             dom = me.dom,
5173             st = dom.style,
5174             xy,
5175             r,
5176             b,              
5177             wrap,               
5178             after,
5179             st,
5180             args, 
5181             pt,
5182             bw,
5183             bh;
5184             
5185         anchor = anchor || "t";
5186
5187         me.queueFx(o, function(){            
5188             xy = fly(dom).getXY();
5189             
5190             fly(dom).fixDisplay();            
5191             
5192             
5193             r = fly(dom).getFxRestore();      
5194             b = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: dom.offsetWidth, height: dom.offsetHeight};
5195             b.right = b.x + b.width;
5196             b.bottom = b.y + b.height;
5197             
5198             
5199             fly(dom).setWidth(b.width).setHeight(b.height);            
5200             
5201             
5202             wrap = fly(dom).fxWrap(r.pos, o, HIDDEN);
5203             
5204             st.visibility = VISIBLE;
5205             st.position = ABSOLUTE;
5206             
5207             
5208             function after(){
5209                  fly(dom).fxUnwrap(wrap, r.pos, o);
5210                  st.width = r.width;
5211                  st.height = r.height;
5212                  fly(dom).afterFx(o);
5213             }
5214             
5215             
5216             pt = {to: [b.x, b.y]}; 
5217             bw = {to: b.width};
5218             bh = {to: b.height};
5219                 
5220             function argCalc(wrap, style, ww, wh, sXY, sXYval, s1, s2, w, h, p){                    
5221                 var ret = {};
5222                 fly(wrap).setWidth(ww).setHeight(wh);
5223                 if(fly(wrap)[sXY]){
5224                     fly(wrap)[sXY](sXYval);                  
5225                 }
5226                 style[s1] = style[s2] = "0";                    
5227                 if(w){
5228                     ret.width = w
5229                 };
5230                 if(h){
5231                     ret.height = h;
5232                 }
5233                 if(p){
5234                     ret.points = p;
5235                 }
5236                 return ret;
5237             };
5238
5239             args = fly(dom).switchStatements(anchor.toLowerCase(), argCalc, {
5240                     t  : [wrap, st, b.width, 0, NULL, NULL, LEFT, BOTTOM, NULL, bh, NULL],
5241                     l  : [wrap, st, 0, b.height, NULL, NULL, RIGHT, TOP, bw, NULL, NULL],
5242                     r  : [wrap, st, b.width, b.height, SETX, b.right, LEFT, TOP, NULL, NULL, pt],
5243                     b  : [wrap, st, b.width, b.height, SETY, b.bottom, LEFT, TOP, NULL, bh, pt],
5244                     tl : [wrap, st, 0, 0, NULL, NULL, RIGHT, BOTTOM, bw, bh, pt],
5245                     bl : [wrap, st, 0, 0, SETY, b.y + b.height, RIGHT, TOP, bw, bh, pt],
5246                     br : [wrap, st, 0, 0, SETXY, [b.right, b.bottom], LEFT, TOP, bw, bh, pt],
5247                     tr : [wrap, st, 0, 0, SETX, b.x + b.width, LEFT, BOTTOM, bw, bh, pt]
5248                 });
5249             
5250             st.visibility = VISIBLE;
5251             fly(wrap).show();
5252
5253             arguments.callee.anim = fly(wrap).fxanim(args,
5254                 o,
5255                 MOTION,
5256                 .5,
5257                 EASEOUT, 
5258                 after);
5259         });
5260         return me;
5261     },
5262     
5263     
5264     slideOut : function(anchor, o){
5265         o = getObject(o);
5266         var me = this,
5267             dom = me.dom,
5268             st = dom.style,
5269             xy = me.getXY(),
5270             wrap,
5271             r,
5272             b,
5273             a,
5274             zero = {to: 0}; 
5275                     
5276         anchor = anchor || "t";
5277
5278         me.queueFx(o, function(){
5279             
5280             
5281             r = fly(dom).getFxRestore(); 
5282             b = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: dom.offsetWidth, height: dom.offsetHeight};
5283             b.right = b.x + b.width;
5284             b.bottom = b.y + b.height;
5285                 
5286             
5287             fly(dom).setWidth(b.width).setHeight(b.height);
5288
5289             
5290             wrap = fly(dom).fxWrap(r.pos, o, VISIBLE);
5291                 
5292             st.visibility = VISIBLE;
5293             st.position = ABSOLUTE;
5294             fly(wrap).setWidth(b.width).setHeight(b.height);            
5295
5296             function after(){
5297                 o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();                
5298                 fly(dom).fxUnwrap(wrap, r.pos, o);
5299                 st.width = r.width;
5300                 st.height = r.height;
5301                 fly(dom).afterFx(o);
5302             }            
5303             
5304             function argCalc(style, s1, s2, p1, v1, p2, v2, p3, v3){                    
5305                 var ret = {};
5306                 
5307                 style[s1] = style[s2] = "0";
5308                 ret[p1] = v1;               
5309                 if(p2){
5310                     ret[p2] = v2;               
5311                 }
5312                 if(p3){
5313                     ret[p3] = v3;
5314                 }
5315                 
5316                 return ret;
5317             };
5318             
5319             a = fly(dom).switchStatements(anchor.toLowerCase(), argCalc, {
5320                 t  : [st, LEFT, BOTTOM, HEIGHT, zero],
5321                 l  : [st, RIGHT, TOP, WIDTH, zero],
5322                 r  : [st, LEFT, TOP, WIDTH, zero, POINTS, {to : [b.right, b.y]}],
5323                 b  : [st, LEFT, TOP, HEIGHT, zero, POINTS, {to : [b.x, b.bottom]}],
5324                 tl : [st, RIGHT, BOTTOM, WIDTH, zero, HEIGHT, zero],
5325                 bl : [st, RIGHT, TOP, WIDTH, zero, HEIGHT, zero, POINTS, {to : [b.x, b.bottom]}],
5326                 br : [st, LEFT, TOP, WIDTH, zero, HEIGHT, zero, POINTS, {to : [b.x + b.width, b.bottom]}],
5327                 tr : [st, LEFT, BOTTOM, WIDTH, zero, HEIGHT, zero, POINTS, {to : [b.right, b.y]}]
5328             });
5329             
5330             arguments.callee.anim = fly(wrap).fxanim(a,
5331                 o,
5332                 MOTION,
5333                 .5,
5334                 EASEOUT, 
5335                 after);
5336         });
5337         return me;
5338     },
5339
5340     
5341     puff : function(o){
5342         o = getObject(o);
5343         var me = this,
5344             dom = me.dom,
5345             st = dom.style,
5346             width,
5347             height,
5348             r;
5349
5350         me.queueFx(o, function(){
5351             width = fly(dom).getWidth();
5352             height = fly(dom).getHeight();
5353             fly(dom).clearOpacity();
5354             fly(dom).show();
5355
5356             
5357             r = fly(dom).getFxRestore();                   
5358             
5359             function after(){
5360                 o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();                  
5361                 fly(dom).clearOpacity();  
5362                 fly(dom).setPositioning(r.pos);
5363                 st.width = r.width;
5364                 st.height = r.height;
5365                 st.fontSize = '';
5366                 fly(dom).afterFx(o);
5367             }   
5368
5369             arguments.callee.anim = fly(dom).fxanim({
5370                     width : {to : fly(dom).adjustWidth(width * 2)},
5371                     height : {to : fly(dom).adjustHeight(height * 2)},
5372                     points : {by : [-width * .5, -height * .5]},
5373                     opacity : {to : 0},
5374                     fontSize: {to : 200, unit: "%"}
5375                 },
5376                 o,
5377                 MOTION,
5378                 .5,
5379                 EASEOUT,
5380                  after);
5381         });
5382         return me;
5383     },
5384
5385     
5386     switchOff : function(o){
5387         o = getObject(o);
5388         var me = this,
5389             dom = me.dom,
5390             st = dom.style,
5391             r;
5392
5393         me.queueFx(o, function(){
5394             fly(dom).clearOpacity();
5395             fly(dom).clip();
5396
5397             
5398             r = fly(dom).getFxRestore();
5399                 
5400             function after(){
5401                 o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();  
5402                 fly(dom).clearOpacity();
5403                 fly(dom).setPositioning(r.pos);
5404                 st.width = r.width;
5405                 st.height = r.height;   
5406                 fly(dom).afterFx(o);
5407             };
5408
5409             fly(dom).fxanim({opacity : {to : 0.3}}, 
5410                 NULL, 
5411                 NULL, 
5412                 .1, 
5413                 NULL, 
5414                 function(){                                 
5415                     fly(dom).clearOpacity();
5416                         (function(){                            
5417                             fly(dom).fxanim({
5418                                 height : {to : 1},
5419                                 points : {by : [0, fly(dom).getHeight() * .5]}
5420                             }, 
5421                             o, 
5422                             MOTION, 
5423                             0.3, 
5424                             'easeIn', 
5425                             after);
5426                         }).defer(100);
5427                 });
5428         });
5429         return me;
5430     },
5431
5432      
5433     highlight : function(color, o){
5434         o = getObject(o);
5435         var me = this,
5436             dom = me.dom,
5437             attr = o.attr || "backgroundColor",
5438             a = {},
5439             restore;
5440
5441         me.queueFx(o, function(){
5442             fly(dom).clearOpacity();
5443             fly(dom).show();
5444
5445             function after(){
5446                 dom.style[attr] = restore;
5447                 fly(dom).afterFx(o);
5448             }            
5449             restore = dom.style[attr];
5450             a[attr] = {from: color || "ffff9c", to: o.endColor || fly(dom).getColor(attr) || "ffffff"};
5451             arguments.callee.anim = fly(dom).fxanim(a,
5452                 o,
5453                 'color',
5454                 1,
5455                 'easeIn', 
5456                 after);
5457         });
5458         return me;
5459     },
5460
5461    
5462     frame : function(color, count, o){
5463         o = getObject(o);
5464         var me = this,
5465             dom = me.dom,
5466             proxy,
5467             active;
5468
5469         me.queueFx(o, function(){
5470             color = color || '#C3DAF9';
5471             if(color.length == 6){
5472                 color = '#' + color;
5473             }            
5474             count = count || 1;
5475             fly(dom).show();
5476
5477             var xy = fly(dom).getXY(),
5478                 b = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: dom.offsetWidth, height: dom.offsetHeight},
5479                 queue = function(){
5480                     proxy = fly(document.body || document.documentElement).createChild({
5481                         style:{
5482                             position : ABSOLUTE,
5483                             'z-index': 35000, 
5484                             border : '0px solid ' + color
5485                         }
5486                     });
5487                     return proxy.queueFx({}, animFn);
5488                 };
5489             
5490             
5491             arguments.callee.anim = {
5492                 isAnimated: true,
5493                 stop: function() {
5494                     count = 0;
5495                     proxy.stopFx();
5496                 }
5497             };
5498             
5499             function animFn(){
5500                 var scale = Ext.isBorderBox ? 2 : 1;
5501                 active = proxy.anim({
5502                     top : {from : b.y, to : b.y - 20},
5503                     left : {from : b.x, to : b.x - 20},
5504                     borderWidth : {from : 0, to : 10},
5505                     opacity : {from : 1, to : 0},
5506                     height : {from : b.height, to : b.height + 20 * scale},
5507                     width : {from : b.width, to : b.width + 20 * scale}
5508                 },{
5509                     duration: o.duration || 1,
5510                     callback: function() {
5511                         proxy.remove();
5512                         --count > 0 ? queue() : fly(dom).afterFx(o);
5513                     }
5514                 });
5515                 arguments.callee.anim = {
5516                     isAnimated: true,
5517                     stop: function(){
5518                         active.stop();
5519                     }
5520                 };
5521             };
5522             queue();
5523         });
5524         return me;
5525     },
5526
5527    
5528     pause : function(seconds){        
5529         var dom = this.dom,
5530             t;
5531
5532         this.queueFx({}, function(){
5533             t = setTimeout(function(){
5534                 fly(dom).afterFx({});
5535             }, seconds * 1000);
5536             arguments.callee.anim = {
5537                 isAnimated: true,
5538                 stop: function(){
5539                     clearTimeout(t);
5540                     fly(dom).afterFx({});
5541                 }
5542             };
5543         });
5544         return this;
5545     },
5546
5547    
5548     fadeIn : function(o){
5549         o = getObject(o);
5550         var me = this,
5551             dom = me.dom,
5552             to = o.endOpacity || 1;
5553         
5554         me.queueFx(o, function(){
5555             fly(dom).setOpacity(0);
5556             fly(dom).fixDisplay();
5557             dom.style.visibility = VISIBLE;
5558             arguments.callee.anim = fly(dom).fxanim({opacity:{to:to}},
5559                 o, NULL, .5, EASEOUT, function(){
5560                 if(to == 1){
5561                     fly(dom).clearOpacity();
5562                 }
5563                 fly(dom).afterFx(o);
5564             });
5565         });
5566         return me;
5567     },
5568
5569    
5570     fadeOut : function(o){
5571         o = getObject(o);
5572         var me = this,
5573             dom = me.dom,
5574             style = dom.style,
5575             to = o.endOpacity || 0;         
5576         
5577         me.queueFx(o, function(){  
5578             arguments.callee.anim = fly(dom).fxanim({ 
5579                 opacity : {to : to}},
5580                 o, 
5581                 NULL, 
5582                 .5, 
5583                 EASEOUT, 
5584                 function(){
5585                     if(to == 0){
5586                         Ext.Element.data(dom, 'visibilityMode') == Ext.Element.DISPLAY || o.useDisplay ? 
5587                             style.display = "none" :
5588                             style.visibility = HIDDEN;
5589                             
5590                         fly(dom).clearOpacity();
5591                     }
5592                     fly(dom).afterFx(o);
5593             });
5594         });
5595         return me;
5596     },
5597
5598    
5599     scale : function(w, h, o){
5600         this.shift(Ext.apply({}, o, {
5601             width: w,
5602             height: h
5603         }));
5604         return this;
5605     },
5606
5607    
5608     shift : function(o){
5609         o = getObject(o);
5610         var dom = this.dom,
5611             a = {};
5612                 
5613         this.queueFx(o, function(){
5614             for (var prop in o) {
5615                 if (o[prop] != UNDEFINED) {                                                 
5616                     a[prop] = {to : o[prop]};                   
5617                 }
5618             } 
5619             
5620             a.width ? a.width.to = fly(dom).adjustWidth(o.width) : a;
5621             a.height ? a.height.to = fly(dom).adjustWidth(o.height) : a;   
5622             
5623             if (a.x || a.y || a.xy) {
5624                 a.points = a.xy || 
5625                            {to : [ a.x ? a.x.to : fly(dom).getX(),
5626                                    a.y ? a.y.to : fly(dom).getY()]};                  
5627             }
5628
5629             arguments.callee.anim = fly(dom).fxanim(a,
5630                 o, 
5631                 MOTION, 
5632                 .35, 
5633                 EASEOUT, 
5634                 function(){
5635                     fly(dom).afterFx(o);
5636                 });
5637         });
5638         return this;
5639     },
5640
5641     
5642     ghost : function(anchor, o){
5643         o = getObject(o);
5644         var me = this,
5645             dom = me.dom,
5646             st = dom.style,
5647             a = {opacity: {to: 0}, points: {}},
5648             pt = a.points,
5649             r,
5650             w,
5651             h;
5652             
5653         anchor = anchor || "b";
5654
5655         me.queueFx(o, function(){
5656             
5657             r = fly(dom).getFxRestore();
5658             w = fly(dom).getWidth();
5659             h = fly(dom).getHeight();
5660             
5661             function after(){
5662                 o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();   
5663                 fly(dom).clearOpacity();
5664                 fly(dom).setPositioning(r.pos);
5665                 st.width = r.width;
5666                 st.height = r.height;
5667                 fly(dom).afterFx(o);
5668             }
5669                 
5670             pt.by = fly(dom).switchStatements(anchor.toLowerCase(), function(v1,v2){ return [v1, v2];}, {
5671                t  : [0, -h],
5672                l  : [-w, 0],
5673                r  : [w, 0],
5674                b  : [0, h],
5675                tl : [-w, -h],
5676                bl : [-w, h],
5677                br : [w, h],
5678                tr : [w, -h] 
5679             });
5680                 
5681             arguments.callee.anim = fly(dom).fxanim(a,
5682                 o,
5683                 MOTION,
5684                 .5,
5685                 EASEOUT, after);
5686         });
5687         return me;
5688     },
5689
5690     
5691     syncFx : function(){
5692         var me = this;
5693         me.fxDefaults = Ext.apply(me.fxDefaults || {}, {
5694             block : FALSE,
5695             concurrent : TRUE,
5696             stopFx : FALSE
5697         });
5698         return me;
5699     },
5700
5701     
5702     sequenceFx : function(){
5703         var me = this;
5704         me.fxDefaults = Ext.apply(me.fxDefaults || {}, {
5705             block : FALSE,
5706             concurrent : FALSE,
5707             stopFx : FALSE
5708         });
5709         return me;
5710     },
5711
5712     
5713     nextFx : function(){        
5714         var ef = getQueue(this.dom.id)[0];
5715         if(ef){
5716             ef.call(this);
5717         }
5718     },
5719
5720     
5721     hasActiveFx : function(){
5722         return getQueue(this.dom.id)[0];
5723     },
5724
5725     
5726     stopFx : function(finish){
5727         var me = this,
5728             id = me.dom.id;
5729         if(me.hasActiveFx()){
5730             var cur = getQueue(id)[0];
5731             if(cur && cur.anim){
5732                 if(cur.anim.isAnimated){
5733                     setQueue(id, [cur]); 
5734                     cur.anim.stop(finish !== undefined ? finish : TRUE);
5735                 }else{
5736                     setQueue(id, []);
5737                 }
5738             }
5739         }
5740         return me;
5741     },
5742
5743     
5744     beforeFx : function(o){
5745         if(this.hasActiveFx() && !o.concurrent){
5746            if(o.stopFx){
5747                this.stopFx();
5748                return TRUE;
5749            }
5750            return FALSE;
5751         }
5752         return TRUE;
5753     },
5754
5755     
5756     hasFxBlock : function(){
5757         var q = getQueue(this.dom.id);
5758         return q && q[0] && q[0].block;
5759     },
5760
5761     
5762     queueFx : function(o, fn){
5763         var me = fly(this.dom);
5764         if(!me.hasFxBlock()){
5765             Ext.applyIf(o, me.fxDefaults);
5766             if(!o.concurrent){
5767                 var run = me.beforeFx(o);
5768                 fn.block = o.block;
5769                 getQueue(me.dom.id).push(fn);
5770                 if(run){
5771                     me.nextFx();
5772                 }
5773             }else{
5774                 fn.call(me);
5775             }
5776         }
5777         return me;
5778     },
5779
5780     
5781     fxWrap : function(pos, o, vis){ 
5782         var dom = this.dom,
5783             wrap,
5784             wrapXY;
5785         if(!o.wrap || !(wrap = Ext.getDom(o.wrap))){            
5786             if(o.fixPosition){
5787                 wrapXY = fly(dom).getXY();
5788             }
5789             var div = document.createElement("div");
5790             div.style.visibility = vis;
5791             wrap = dom.parentNode.insertBefore(div, dom);
5792             fly(wrap).setPositioning(pos);
5793             if(fly(wrap).isStyle(POSITION, "static")){
5794                 fly(wrap).position("relative");
5795             }
5796             fly(dom).clearPositioning('auto');
5797             fly(wrap).clip();
5798             wrap.appendChild(dom);
5799             if(wrapXY){
5800                 fly(wrap).setXY(wrapXY);
5801             }
5802         }
5803         return wrap;
5804     },
5805
5806     
5807     fxUnwrap : function(wrap, pos, o){      
5808         var dom = this.dom;
5809         fly(dom).clearPositioning();
5810         fly(dom).setPositioning(pos);
5811         if(!o.wrap){
5812             var pn = fly(wrap).dom.parentNode;
5813             pn.insertBefore(dom, wrap); 
5814             fly(wrap).remove();
5815         }
5816     },
5817
5818     
5819     getFxRestore : function(){
5820         var st = this.dom.style;
5821         return {pos: this.getPositioning(), width: st.width, height : st.height};
5822     },
5823
5824     
5825     afterFx : function(o){
5826         var dom = this.dom,
5827             id = dom.id;
5828         if(o.afterStyle){
5829             fly(dom).setStyle(o.afterStyle);            
5830         }
5831         if(o.afterCls){
5832             fly(dom).addClass(o.afterCls);
5833         }
5834         if(o.remove == TRUE){
5835             fly(dom).remove();
5836         }
5837         if(o.callback){
5838             o.callback.call(o.scope, fly(dom));
5839         }
5840         if(!o.concurrent){
5841             getQueue(id).shift();
5842             fly(dom).nextFx();
5843         }
5844     },
5845
5846     
5847     fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
5848         animType = animType || 'run';
5849         opt = opt || {};
5850         var anim = Ext.lib.Anim[animType](
5851                 this.dom, 
5852                 args,
5853                 (opt.duration || defaultDur) || .35,
5854                 (opt.easing || defaultEase) || EASEOUT,
5855                 cb,            
5856                 this
5857             );
5858         opt.anim = anim;
5859         return anim;
5860     }
5861 };
5862
5863
5864 Ext.Fx.resize = Ext.Fx.scale;
5865
5866
5867
5868 Ext.Element.addMethods(Ext.Fx);
5869 })();
5870
5871 Ext.CompositeElementLite = function(els, root){
5872     
5873     this.elements = [];
5874     this.add(els, root);
5875     this.el = new Ext.Element.Flyweight();
5876 };
5877
5878 Ext.CompositeElementLite.prototype = {
5879     isComposite: true,    
5880     
5881     
5882     getElement : function(el){
5883         
5884         var e = this.el;
5885         e.dom = el;
5886         e.id = el.id;
5887         return e;
5888     },
5889     
5890     
5891     transformElement : function(el){
5892         return Ext.getDom(el);
5893     },
5894     
5895     
5896     getCount : function(){
5897         return this.elements.length;
5898     },    
5899     
5900     add : function(els, root){
5901         var me = this,
5902             elements = me.elements;
5903         if(!els){
5904             return this;
5905         }
5906         if(Ext.isString(els)){
5907             els = Ext.Element.selectorFunction(els, root);
5908         }else if(els.isComposite){
5909             els = els.elements;
5910         }else if(!Ext.isIterable(els)){
5911             els = [els];
5912         }
5913         
5914         for(var i = 0, len = els.length; i < len; ++i){
5915             elements.push(me.transformElement(els[i]));
5916         }
5917         return me;
5918     },
5919     
5920     invoke : function(fn, args){
5921         var me = this,
5922             els = me.elements,
5923             len = els.length, 
5924             e;
5925             
5926         for(i = 0; i<len; i++) {
5927             e = els[i];
5928             if(e){
5929                 Ext.Element.prototype[fn].apply(me.getElement(e), args);
5930             }
5931         }
5932         return me;
5933     },
5934     
5935     item : function(index){
5936         var me = this,
5937             el = me.elements[index],
5938             out = null;
5939
5940         if(el){
5941             out = me.getElement(el);
5942         }
5943         return out;
5944     },
5945
5946     
5947     addListener : function(eventName, handler, scope, opt){
5948         var els = this.elements,
5949             len = els.length,
5950             i, e;
5951         
5952         for(i = 0; i<len; i++) {
5953             e = els[i];
5954             if(e) {
5955                 Ext.EventManager.on(e, eventName, handler, scope || e, opt);
5956             }
5957         }
5958         return this;
5959     },
5960     
5961     each : function(fn, scope){       
5962         var me = this,
5963             els = me.elements,
5964             len = els.length,
5965             i, e;
5966         
5967         for(i = 0; i<len; i++) {
5968             e = els[i];
5969             if(e){
5970                 e = this.getElement(e);
5971                 if(fn.call(scope || e, e, me, i)){
5972                     break;
5973                 }
5974             }
5975         }
5976         return me;
5977     },
5978     
5979     
5980     fill : function(els){
5981         var me = this;
5982         me.elements = [];
5983         me.add(els);
5984         return me;
5985     },
5986     
5987     
5988     filter : function(selector){
5989         var els = [],
5990             me = this,
5991             elements = me.elements,
5992             fn = Ext.isFunction(selector) ? selector
5993                 : function(el){
5994                     return el.is(selector);
5995                 };
5996                 
5997         
5998         me.each(function(el, self, i){
5999             if(fn(el, i) !== false){
6000                 els[els.length] = me.transformElement(el);
6001             }
6002         });
6003         me.elements = els;
6004         return me;
6005     },
6006     
6007     
6008     indexOf : function(el){
6009         return this.elements.indexOf(this.transformElement(el));
6010     },
6011     
6012         
6013     replaceElement : function(el, replacement, domReplace){
6014         var index = !isNaN(el) ? el : this.indexOf(el),
6015             d;
6016         if(index > -1){
6017             replacement = Ext.getDom(replacement);
6018             if(domReplace){
6019                 d = this.elements[index];
6020                 d.parentNode.insertBefore(replacement, d);
6021                 Ext.removeNode(d);
6022             }
6023             this.elements.splice(index, 1, replacement);
6024         }
6025         return this;
6026     },
6027     
6028     
6029     clear : function(){
6030         this.elements = [];
6031     }
6032 };
6033
6034 Ext.CompositeElementLite.prototype.on = Ext.CompositeElementLite.prototype.addListener;
6035
6036 (function(){
6037 var fnName,
6038     ElProto = Ext.Element.prototype,
6039     CelProto = Ext.CompositeElementLite.prototype;
6040     
6041 for(fnName in ElProto){
6042     if(Ext.isFunction(ElProto[fnName])){
6043         (function(fnName){ 
6044             CelProto[fnName] = CelProto[fnName] || function(){
6045                 return this.invoke(fnName, arguments);
6046             };
6047         }).call(CelProto, fnName);
6048         
6049     }
6050 }
6051 })();
6052
6053 if(Ext.DomQuery){
6054     Ext.Element.selectorFunction = Ext.DomQuery.select;
6055
6056
6057
6058 Ext.Element.select = function(selector, root){
6059     var els;
6060     if(typeof selector == "string"){
6061         els = Ext.Element.selectorFunction(selector, root);
6062     }else if(selector.length !== undefined){
6063         els = selector;
6064     }else{
6065         throw "Invalid selector";
6066     }
6067     return new Ext.CompositeElementLite(els);
6068 };
6069
6070 Ext.select = Ext.Element.select;
6071 Ext.apply(Ext.CompositeElementLite.prototype, { 
6072         addElements : function(els, root){
6073         if(!els){
6074             return this;
6075         }
6076         if(typeof els == "string"){
6077             els = Ext.Element.selectorFunction(els, root);
6078         }
6079         var yels = this.elements;        
6080             Ext.each(els, function(e) {
6081                 yels.push(Ext.get(e));
6082         });
6083         return this;
6084     },
6085     
6086     
6087     first : function(){
6088         return this.item(0);
6089     },   
6090     
6091     
6092     last : function(){
6093         return this.item(this.getCount()-1);
6094     },
6095     
6096     
6097     contains : function(el){
6098         return this.indexOf(el) != -1;
6099     },
6100     
6101     
6102     removeElement : function(keys, removeDom){
6103         var me = this,
6104                 els = this.elements,        
6105                 el;             
6106             Ext.each(keys, function(val){
6107                     if ((el = (els[val] || els[val = me.indexOf(val)]))) {
6108                         if(removeDom){
6109                     if(el.dom){
6110                         el.remove();
6111                     }else{
6112                         Ext.removeNode(el);
6113                     }
6114                 }
6115                         els.splice(val, 1);                     
6116                         }
6117             });
6118         return this;
6119     }    
6120 });
6121
6122 Ext.CompositeElement = function(els, root){
6123     this.elements = [];
6124     this.add(els, root);
6125 };
6126
6127 Ext.extend(Ext.CompositeElement, Ext.CompositeElementLite, {
6128     
6129     
6130     getElement : function(el){
6131         
6132         return el;
6133     },
6134     
6135     
6136     transformElement : function(el){
6137         return Ext.get(el);
6138     }
6139
6140     
6141
6142     
6143
6144     
6145 });
6146
6147
6148 Ext.Element.select = function(selector, unique, root){
6149     var els;
6150     if(typeof selector == "string"){
6151         els = Ext.Element.selectorFunction(selector, root);
6152     }else if(selector.length !== undefined){
6153         els = selector;
6154     }else{
6155         throw "Invalid selector";
6156     }
6157
6158     return (unique === true) ? new Ext.CompositeElement(els) : new Ext.CompositeElementLite(els);
6159 };
6160
6161
6162 Ext.select = Ext.Element.select;(function(){
6163     var BEFOREREQUEST = "beforerequest",
6164         REQUESTCOMPLETE = "requestcomplete",
6165         REQUESTEXCEPTION = "requestexception",
6166         UNDEFINED = undefined,
6167         LOAD = 'load',
6168         POST = 'POST',
6169         GET = 'GET',
6170         WINDOW = window;
6171     
6172     
6173     Ext.data.Connection = function(config){    
6174         Ext.apply(this, config);
6175         this.addEvents(
6176             
6177             BEFOREREQUEST,
6178             
6179             REQUESTCOMPLETE,
6180             
6181             REQUESTEXCEPTION
6182         );
6183         Ext.data.Connection.superclass.constructor.call(this);
6184     };
6185
6186     Ext.extend(Ext.data.Connection, Ext.util.Observable, {
6187         
6188         
6189         
6190         
6191         
6192         timeout : 30000,
6193         
6194         autoAbort:false,
6195     
6196         
6197         disableCaching: true,
6198         
6199         
6200         disableCachingParam: '_dc',
6201         
6202         
6203         request : function(o){
6204             var me = this;
6205             if(me.fireEvent(BEFOREREQUEST, me, o)){
6206                 if (o.el) {
6207                     if(!Ext.isEmpty(o.indicatorText)){
6208                         me.indicatorText = '<div class="loading-indicator">'+o.indicatorText+"</div>";
6209                     }
6210                     if(me.indicatorText) {
6211                         Ext.getDom(o.el).innerHTML = me.indicatorText;                        
6212                     }
6213                     o.success = (Ext.isFunction(o.success) ? o.success : function(){}).createInterceptor(function(response) {
6214                         Ext.getDom(o.el).innerHTML = response.responseText;
6215                     });
6216                 }
6217                 
6218                 var p = o.params,
6219                     url = o.url || me.url,                
6220                     method,
6221                     cb = {success: me.handleResponse,
6222                           failure: me.handleFailure,
6223                           scope: me,
6224                           argument: {options: o},
6225                           timeout : o.timeout || me.timeout
6226                     },
6227                     form,                    
6228                     serForm;                    
6229                   
6230                      
6231                 if (Ext.isFunction(p)) {
6232                     p = p.call(o.scope||WINDOW, o);
6233                 }
6234                                                            
6235                 p = Ext.urlEncode(me.extraParams, Ext.isObject(p) ? Ext.urlEncode(p) : p);    
6236                 
6237                 if (Ext.isFunction(url)) {
6238                     url = url.call(o.scope || WINDOW, o);
6239                 }
6240     
6241                 if((form = Ext.getDom(o.form))){
6242                     url = url || form.action;
6243                      if(o.isUpload || /multipart\/form-data/i.test(form.getAttribute("enctype"))) { 
6244                          return me.doFormUpload.call(me, o, p, url);
6245                      }
6246                     serForm = Ext.lib.Ajax.serializeForm(form);                    
6247                     p = p ? (p + '&' + serForm) : serForm;
6248                 }
6249                 
6250                 method = o.method || me.method || ((p || o.xmlData || o.jsonData) ? POST : GET);
6251                 
6252                 if(method === GET && (me.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
6253                     var dcp = o.disableCachingParam || me.disableCachingParam;
6254                     url = Ext.urlAppend(url, dcp + '=' + (new Date().getTime()));
6255                 }
6256                 
6257                 o.headers = Ext.apply(o.headers || {}, me.defaultHeaders || {});
6258                 
6259                 if(o.autoAbort === true || me.autoAbort) {
6260                     me.abort();
6261                 }
6262                  
6263                 if((method == GET || o.xmlData || o.jsonData) && p){
6264                     url = Ext.urlAppend(url, p);  
6265                     p = '';
6266                 }
6267                 return (me.transId = Ext.lib.Ajax.request(method, url, cb, p, o));
6268             }else{                
6269                 return o.callback ? o.callback.apply(o.scope, [o,UNDEFINED,UNDEFINED]) : null;
6270             }
6271         },
6272     
6273         
6274         isLoading : function(transId){
6275             return transId ? Ext.lib.Ajax.isCallInProgress(transId) : !! this.transId;            
6276         },
6277     
6278         
6279         abort : function(transId){
6280             if(transId || this.isLoading()){
6281                 Ext.lib.Ajax.abort(transId || this.transId);
6282             }
6283         },
6284
6285         
6286         handleResponse : function(response){
6287             this.transId = false;
6288             var options = response.argument.options;
6289             response.argument = options ? options.argument : null;
6290             this.fireEvent(REQUESTCOMPLETE, this, response, options);
6291             if(options.success){
6292                 options.success.call(options.scope, response, options);
6293             }
6294             if(options.callback){
6295                 options.callback.call(options.scope, options, true, response);
6296             }
6297         },
6298
6299         
6300         handleFailure : function(response, e){
6301             this.transId = false;
6302             var options = response.argument.options;
6303             response.argument = options ? options.argument : null;
6304             this.fireEvent(REQUESTEXCEPTION, this, response, options, e);
6305             if(options.failure){
6306                 options.failure.call(options.scope, response, options);
6307             }
6308             if(options.callback){
6309                 options.callback.call(options.scope, options, false, response);
6310             }
6311         },
6312
6313         
6314         doFormUpload : function(o, ps, url){
6315             var id = Ext.id(),
6316                 doc = document,
6317                 frame = doc.createElement('iframe'),
6318                 form = Ext.getDom(o.form),
6319                 hiddens = [],
6320                 hd,
6321                 encoding = 'multipart/form-data',
6322                 buf = {
6323                     target: form.target,
6324                     method: form.method,
6325                     encoding: form.encoding,
6326                     enctype: form.enctype,
6327                     action: form.action
6328                 };
6329
6330             Ext.fly(frame).set({
6331                 id: id,
6332                 name: id,
6333                 cls: 'x-hidden',
6334                 src: Ext.SSL_SECURE_URL 
6335             });
6336             doc.body.appendChild(frame);
6337
6338             
6339             if(Ext.isIE){
6340                document.frames[id].name = id;
6341             }
6342
6343             Ext.fly(form).set({
6344                 target: id,
6345                 method: POST,
6346                 enctype: encoding,
6347                 encoding: encoding,
6348                 action: url || buf.action
6349             });
6350
6351             
6352             Ext.iterate(Ext.urlDecode(ps, false), function(k, v){
6353                 hd = doc.createElement('input');
6354                 Ext.fly(hd).set({
6355                     type: 'hidden',
6356                     value: v,
6357                     name: k
6358                 });
6359                 form.appendChild(hd);
6360                 hiddens.push(hd);
6361             });
6362
6363             function cb(){
6364                 var me = this,
6365                     
6366                     r = {responseText : '',
6367                          responseXML : null,
6368                          argument : o.argument},
6369                     doc,
6370                     firstChild;
6371
6372                 try{
6373                     doc = frame.contentWindow.document || frame.contentDocument || WINDOW.frames[id].document;
6374                     if(doc){
6375                         if(doc.body){
6376                             if(/textarea/i.test((firstChild = doc.body.firstChild || {}).tagName)){ 
6377                                 r.responseText = firstChild.value;
6378                             }else{
6379                                 r.responseText = doc.body.innerHTML;
6380                             }
6381                         }
6382                         
6383                         r.responseXML = doc.XMLDocument || doc;
6384                     }
6385                 }
6386                 catch(e) {}
6387
6388                 Ext.EventManager.removeListener(frame, LOAD, cb, me);
6389
6390                 me.fireEvent(REQUESTCOMPLETE, me, r, o);
6391
6392                 function runCallback(fn, scope, args){
6393                     if(Ext.isFunction(fn)){
6394                         fn.apply(scope, args);
6395                     }
6396                 }
6397
6398                 runCallback(o.success, o.scope, [r, o]);
6399                 runCallback(o.callback, o.scope, [o, true, r]);
6400
6401                 if(!me.debugUploads){
6402                     setTimeout(function(){Ext.removeNode(frame);}, 100);
6403                 }
6404             }
6405
6406             Ext.EventManager.on(frame, LOAD, cb, this);
6407             form.submit();
6408
6409             Ext.fly(form).set(buf);
6410             Ext.each(hiddens, function(h) {
6411                 Ext.removeNode(h);
6412             });
6413         }
6414     });
6415 })();
6416
6417
6418 Ext.Ajax = new Ext.data.Connection({
6419     
6420     
6421     
6422     
6423     
6424     
6425
6426     
6427
6428     
6429     
6430     
6431     
6432     
6433     
6434
6435     
6436     autoAbort : false,
6437
6438     
6439     serializeForm : function(form){
6440         return Ext.lib.Ajax.serializeForm(form);
6441     }
6442 });
6443
6444 Ext.UpdateManager = Ext.Updater = Ext.extend(Ext.util.Observable, 
6445 function() {
6446         var BEFOREUPDATE = "beforeupdate",
6447                 UPDATE = "update",
6448                 FAILURE = "failure";
6449                 
6450         
6451     function processSuccess(response){      
6452             var me = this;
6453         me.transaction = null;
6454         if (response.argument.form && response.argument.reset) {
6455             try { 
6456                 response.argument.form.reset();
6457             } catch(e){}
6458         }
6459         if (me.loadScripts) {
6460             me.renderer.render(me.el, response, me,
6461                updateComplete.createDelegate(me, [response]));
6462         } else {
6463             me.renderer.render(me.el, response, me);
6464             updateComplete.call(me, response);
6465         }
6466     }
6467     
6468     
6469     function updateComplete(response, type, success){
6470         this.fireEvent(type || UPDATE, this.el, response);
6471         if(Ext.isFunction(response.argument.callback)){
6472             response.argument.callback.call(response.argument.scope, this.el, Ext.isEmpty(success) ? true : false, response, response.argument.options);
6473         }
6474     }
6475
6476     
6477     function processFailure(response){              
6478         updateComplete.call(this, response, FAILURE, !!(this.transaction = null));
6479     }
6480             
6481         return {
6482             constructor: function(el, forceNew){
6483                     var me = this;
6484                 el = Ext.get(el);
6485                 if(!forceNew && el.updateManager){
6486                     return el.updateManager;
6487                 }
6488                 
6489                 me.el = el;
6490                 
6491                 me.defaultUrl = null;
6492         
6493                 me.addEvents(
6494                     
6495                     BEFOREUPDATE,
6496                     
6497                     UPDATE,
6498                     
6499                     FAILURE
6500                 );
6501         
6502                 Ext.apply(me, Ext.Updater.defaults);
6503                 
6504                 
6505                 
6506                 
6507                 
6508                 
6509         
6510                 
6511                 me.transaction = null;
6512                 
6513                 me.refreshDelegate = me.refresh.createDelegate(me);
6514                 
6515                 me.updateDelegate = me.update.createDelegate(me);
6516                 
6517                 me.formUpdateDelegate = (me.formUpdate || function(){}).createDelegate(me);     
6518                 
6519                         
6520                 me.renderer = me.renderer || me.getDefaultRenderer();
6521                 
6522                 Ext.Updater.superclass.constructor.call(me);
6523             },
6524         
6525                 
6526             setRenderer : function(renderer){
6527                 this.renderer = renderer;
6528             },  
6529         
6530             
6531             getRenderer : function(){
6532                return this.renderer;
6533             },
6534
6535             
6536             getDefaultRenderer: function() {
6537                 return new Ext.Updater.BasicRenderer();
6538             },
6539                 
6540             
6541             setDefaultUrl : function(defaultUrl){
6542                 this.defaultUrl = defaultUrl;
6543             },
6544         
6545             
6546             getEl : function(){
6547                 return this.el;
6548             },
6549         
6550                 
6551             update : function(url, params, callback, discardUrl){
6552                     var me = this,
6553                         cfg, 
6554                         callerScope;
6555                         
6556                 if(me.fireEvent(BEFOREUPDATE, me.el, url, params) !== false){               
6557                     if(Ext.isObject(url)){ 
6558                         cfg = url;
6559                         url = cfg.url;
6560                         params = params || cfg.params;
6561                         callback = callback || cfg.callback;
6562                         discardUrl = discardUrl || cfg.discardUrl;
6563                         callerScope = cfg.scope;                        
6564                         if(!Ext.isEmpty(cfg.nocache)){me.disableCaching = cfg.nocache;};
6565                         if(!Ext.isEmpty(cfg.text)){me.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
6566                         if(!Ext.isEmpty(cfg.scripts)){me.loadScripts = cfg.scripts;};
6567                         if(!Ext.isEmpty(cfg.timeout)){me.timeout = cfg.timeout;};
6568                     }
6569                     me.showLoading();
6570         
6571                     if(!discardUrl){
6572                         me.defaultUrl = url;
6573                     }
6574                     if(Ext.isFunction(url)){
6575                         url = url.call(me);
6576                     }
6577         
6578                     var o = Ext.apply({}, {
6579                         url : url,
6580                         params: (Ext.isFunction(params) && callerScope) ? params.createDelegate(callerScope) : params,
6581                         success: processSuccess,
6582                         failure: processFailure,
6583                         scope: me,
6584                         callback: undefined,
6585                         timeout: (me.timeout*1000),
6586                         disableCaching: me.disableCaching,
6587                         argument: {
6588                             "options": cfg,
6589                             "url": url,
6590                             "form": null,
6591                             "callback": callback,
6592                             "scope": callerScope || window,
6593                             "params": params
6594                         }
6595                     }, cfg);
6596         
6597                     me.transaction = Ext.Ajax.request(o);
6598                 }
6599             },          
6600
6601                 
6602             formUpdate : function(form, url, reset, callback){
6603                     var me = this;
6604                 if(me.fireEvent(BEFOREUPDATE, me.el, form, url) !== false){
6605                     if(Ext.isFunction(url)){
6606                         url = url.call(me);
6607                     }
6608                     form = Ext.getDom(form)
6609                     me.transaction = Ext.Ajax.request({
6610                         form: form,
6611                         url:url,
6612                         success: processSuccess,
6613                         failure: processFailure,
6614                         scope: me,
6615                         timeout: (me.timeout*1000),
6616                         argument: {
6617                             "url": url,
6618                             "form": form,
6619                             "callback": callback,
6620                             "reset": reset
6621                         }
6622                     });
6623                     me.showLoading.defer(1, me);
6624                 }
6625             },
6626                         
6627             
6628             startAutoRefresh : function(interval, url, params, callback, refreshNow){
6629                     var me = this;
6630                 if(refreshNow){
6631                     me.update(url || me.defaultUrl, params, callback, true);
6632                 }
6633                 if(me.autoRefreshProcId){
6634                     clearInterval(me.autoRefreshProcId);
6635                 }
6636                 me.autoRefreshProcId = setInterval(me.update.createDelegate(me, [url || me.defaultUrl, params, callback, true]), interval * 1000);
6637             },
6638         
6639             
6640             stopAutoRefresh : function(){
6641                 if(this.autoRefreshProcId){
6642                     clearInterval(this.autoRefreshProcId);
6643                     delete this.autoRefreshProcId;
6644                 }
6645             },
6646         
6647             
6648             isAutoRefreshing : function(){
6649                return !!this.autoRefreshProcId;
6650             },
6651         
6652             
6653             showLoading : function(){
6654                 if(this.showLoadIndicator){
6655                 this.el.dom.innerHTML = this.indicatorText;
6656                 }
6657             },
6658         
6659             
6660             abort : function(){
6661                 if(this.transaction){
6662                     Ext.Ajax.abort(this.transaction);
6663                 }
6664             },
6665         
6666             
6667             isUpdating : function(){        
6668                 return this.transaction ? Ext.Ajax.isLoading(this.transaction) : false;        
6669             },
6670             
6671             
6672             refresh : function(callback){
6673                 if(this.defaultUrl){
6674                         this.update(this.defaultUrl, null, callback, true);
6675                 }
6676             }
6677     }
6678 }());
6679
6680
6681 Ext.Updater.defaults = {
6682    
6683     timeout : 30,    
6684     
6685     disableCaching : false,
6686     
6687     showLoadIndicator : true,
6688     
6689     indicatorText : '<div class="loading-indicator">Loading...</div>',
6690      
6691     loadScripts : false,
6692     
6693     sslBlankUrl : Ext.SSL_SECURE_URL      
6694 };
6695
6696
6697
6698 Ext.Updater.updateElement = function(el, url, params, options){
6699     var um = Ext.get(el).getUpdater();
6700     Ext.apply(um, options);
6701     um.update(url, params, options ? options.callback : null);
6702 };
6703
6704
6705 Ext.Updater.BasicRenderer = function(){};
6706
6707 Ext.Updater.BasicRenderer.prototype = {
6708     
6709      render : function(el, response, updateManager, callback){       
6710         el.update(response.responseText, updateManager.loadScripts, callback);
6711     }
6712 };
6713
6714
6715
6716 (function() {
6717
6718
6719 Date.useStrict = false;
6720
6721
6722
6723
6724
6725 function xf(format) {
6726     var args = Array.prototype.slice.call(arguments, 1);
6727     return format.replace(/\{(\d+)\}/g, function(m, i) {
6728         return args[i];
6729     });
6730 }
6731
6732
6733
6734 Date.formatCodeToRegex = function(character, currentGroup) {
6735     
6736     var p = Date.parseCodes[character];
6737
6738     if (p) {
6739       p = typeof p == 'function'? p() : p;
6740       Date.parseCodes[character] = p; 
6741     }
6742
6743     return p? Ext.applyIf({
6744       c: p.c? xf(p.c, currentGroup || "{0}") : p.c
6745     }, p) : {
6746         g:0,
6747         c:null,
6748         s:Ext.escapeRe(character) 
6749     }
6750 }
6751
6752
6753 var $f = Date.formatCodeToRegex;
6754
6755 Ext.apply(Date, {
6756     
6757     parseFunctions: {
6758         "M$": function(input, strict) {
6759             
6760             
6761             var re = new RegExp('\\/Date\\(([-+])?(\\d+)(?:[+-]\\d{4})?\\)\\/');
6762             var r = (input || '').match(re);
6763             return r? new Date(((r[1] || '') + r[2]) * 1) : null;
6764         }
6765     },
6766     parseRegexes: [],
6767
6768     
6769     formatFunctions: {
6770         "M$": function() {
6771             
6772             return '\\/Date(' + this.getTime() + ')\\/';
6773         }
6774     },
6775
6776     y2kYear : 50,
6777
6778     
6779     MILLI : "ms",
6780
6781     
6782     SECOND : "s",
6783
6784     
6785     MINUTE : "mi",
6786
6787     
6788     HOUR : "h",
6789
6790     
6791     DAY : "d",
6792
6793     
6794     MONTH : "mo",
6795
6796     
6797     YEAR : "y",
6798
6799     
6800     defaults: {},
6801
6802     
6803     dayNames : [
6804         "Sunday",
6805         "Monday",
6806         "Tuesday",
6807         "Wednesday",
6808         "Thursday",
6809         "Friday",
6810         "Saturday"
6811     ],
6812
6813     
6814     monthNames : [
6815         "January",
6816         "February",
6817         "March",
6818         "April",
6819         "May",
6820         "June",
6821         "July",
6822         "August",
6823         "September",
6824         "October",
6825         "November",
6826         "December"
6827     ],
6828
6829     
6830     monthNumbers : {
6831         Jan:0,
6832         Feb:1,
6833         Mar:2,
6834         Apr:3,
6835         May:4,
6836         Jun:5,
6837         Jul:6,
6838         Aug:7,
6839         Sep:8,
6840         Oct:9,
6841         Nov:10,
6842         Dec:11
6843     },
6844
6845     
6846     getShortMonthName : function(month) {
6847         return Date.monthNames[month].substring(0, 3);
6848     },
6849
6850     
6851     getShortDayName : function(day) {
6852         return Date.dayNames[day].substring(0, 3);
6853     },
6854
6855     
6856     getMonthNumber : function(name) {
6857         
6858         return Date.monthNumbers[name.substring(0, 1).toUpperCase() + name.substring(1, 3).toLowerCase()];
6859     },
6860
6861     
6862     formatCodes : {
6863         d: "String.leftPad(this.getDate(), 2, '0')",
6864         D: "Date.getShortDayName(this.getDay())", 
6865         j: "this.getDate()",
6866         l: "Date.dayNames[this.getDay()]",
6867         N: "(this.getDay() ? this.getDay() : 7)",
6868         S: "this.getSuffix()",
6869         w: "this.getDay()",
6870         z: "this.getDayOfYear()",
6871         W: "String.leftPad(this.getWeekOfYear(), 2, '0')",
6872         F: "Date.monthNames[this.getMonth()]",
6873         m: "String.leftPad(this.getMonth() + 1, 2, '0')",
6874         M: "Date.getShortMonthName(this.getMonth())", 
6875         n: "(this.getMonth() + 1)",
6876         t: "this.getDaysInMonth()",
6877         L: "(this.isLeapYear() ? 1 : 0)",
6878         o: "(this.getFullYear() + (this.getWeekOfYear() == 1 && this.getMonth() > 0 ? +1 : (this.getWeekOfYear() >= 52 && this.getMonth() < 11 ? -1 : 0)))",
6879         Y: "this.getFullYear()",
6880         y: "('' + this.getFullYear()).substring(2, 4)",
6881         a: "(this.getHours() < 12 ? 'am' : 'pm')",
6882         A: "(this.getHours() < 12 ? 'AM' : 'PM')",
6883         g: "((this.getHours() % 12) ? this.getHours() % 12 : 12)",
6884         G: "this.getHours()",
6885         h: "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0')",
6886         H: "String.leftPad(this.getHours(), 2, '0')",
6887         i: "String.leftPad(this.getMinutes(), 2, '0')",
6888         s: "String.leftPad(this.getSeconds(), 2, '0')",
6889         u: "String.leftPad(this.getMilliseconds(), 3, '0')",
6890         O: "this.getGMTOffset()",
6891         P: "this.getGMTOffset(true)",
6892         T: "this.getTimezone()",
6893         Z: "(this.getTimezoneOffset() * -60)",
6894
6895         c: function() { 
6896             for (var c = "Y-m-dTH:i:sP", code = [], i = 0, l = c.length; i < l; ++i) {
6897                 var e = c.charAt(i);
6898                 code.push(e == "T" ? "'T'" : Date.getFormatCode(e)); 
6899             }
6900             return code.join(" + ");
6901         },
6902         
6903
6904         U: "Math.round(this.getTime() / 1000)"
6905     },
6906
6907     
6908     isValid : function(y, m, d, h, i, s, ms) {
6909         
6910         h = h || 0;
6911         i = i || 0;
6912         s = s || 0;
6913         ms = ms || 0;
6914
6915         var dt = new Date(y, m - 1, d, h, i, s, ms);
6916
6917         return y == dt.getFullYear() &&
6918             m == dt.getMonth() + 1 &&
6919             d == dt.getDate() &&
6920             h == dt.getHours() &&
6921             i == dt.getMinutes() &&
6922             s == dt.getSeconds() &&
6923             ms == dt.getMilliseconds();
6924     },
6925
6926     
6927     parseDate : function(input, format, strict) {
6928         var p = Date.parseFunctions;
6929         if (p[format] == null) {
6930             Date.createParser(format);
6931         }
6932         return p[format](input, Ext.isDefined(strict) ? strict : Date.useStrict);
6933     },
6934
6935     
6936     getFormatCode : function(character) {
6937         var f = Date.formatCodes[character];
6938
6939         if (f) {
6940           f = typeof f == 'function'? f() : f;
6941           Date.formatCodes[character] = f; 
6942         }
6943
6944         
6945         return f || ("'" + String.escape(character) + "'");
6946     },
6947
6948     
6949     createFormat : function(format) {
6950         var code = [],
6951             special = false,
6952             ch = '';
6953
6954         for (var i = 0; i < format.length; ++i) {
6955             ch = format.charAt(i);
6956             if (!special && ch == "\\") {
6957                 special = true;
6958             } else if (special) {
6959                 special = false;
6960                 code.push("'" + String.escape(ch) + "'");
6961             } else {
6962                 code.push(Date.getFormatCode(ch))
6963             }
6964         }
6965         Date.formatFunctions[format] = new Function("return " + code.join('+'));
6966     },
6967
6968     
6969     createParser : function() {
6970         var code = [
6971             "var dt, y, m, d, h, i, s, ms, o, z, zz, u, v,",
6972                 "def = Date.defaults,",
6973                 "results = String(input).match(Date.parseRegexes[{0}]);", 
6974
6975             "if(results){",
6976                 "{1}",
6977
6978                 "if(u != null){", 
6979                     "v = new Date(u * 1000);", 
6980                 "}else{",
6981                     
6982                     
6983                     
6984                     "dt = (new Date()).clearTime();",
6985
6986                     
6987                     "y = y >= 0? y : Ext.num(def.y, dt.getFullYear());",
6988                     "m = m >= 0? m : Ext.num(def.m - 1, dt.getMonth());",
6989                     "d = d >= 0? d : Ext.num(def.d, dt.getDate());",
6990
6991                     
6992                     "h  = h || Ext.num(def.h, dt.getHours());",
6993                     "i  = i || Ext.num(def.i, dt.getMinutes());",
6994                     "s  = s || Ext.num(def.s, dt.getSeconds());",
6995                     "ms = ms || Ext.num(def.ms, dt.getMilliseconds());",
6996
6997                     "if(z >= 0 && y >= 0){",
6998                         
6999                         
7000
7001                         
7002                         "v = new Date(y, 0, 1, h, i, s, ms);",
7003
7004                         
7005                         "v = !strict? v : (strict === true && (z <= 364 || (v.isLeapYear() && z <= 365))? v.add(Date.DAY, z) : null);",
7006                     "}else if(strict === true && !Date.isValid(y, m + 1, d, h, i, s, ms)){", 
7007                         "v = null;", 
7008                     "}else{",
7009                         
7010                         "v = new Date(y, m, d, h, i, s, ms);",
7011                     "}",
7012                 "}",
7013             "}",
7014
7015             "if(v){",
7016                 
7017                 "if(zz != null){",
7018                     
7019                     "v = v.add(Date.SECOND, -v.getTimezoneOffset() * 60 - zz);",
7020                 "}else if(o){",
7021                     
7022                     "v = v.add(Date.MINUTE, -v.getTimezoneOffset() + (sn == '+'? -1 : 1) * (hr * 60 + mn));",
7023                 "}",
7024             "}",
7025
7026             "return v;"
7027         ].join('\n');
7028
7029         return function(format) {
7030             var regexNum = Date.parseRegexes.length,
7031                 currentGroup = 1,
7032                 calc = [],
7033                 regex = [],
7034                 special = false,
7035                 ch = "";
7036
7037             for (var i = 0; i < format.length; ++i) {
7038                 ch = format.charAt(i);
7039                 if (!special && ch == "\\") {
7040                     special = true;
7041                 } else if (special) {
7042                     special = false;
7043                     regex.push(String.escape(ch));
7044                 } else {
7045                     var obj = $f(ch, currentGroup);
7046                     currentGroup += obj.g;
7047                     regex.push(obj.s);
7048                     if (obj.g && obj.c) {
7049                         calc.push(obj.c);
7050                     }
7051                 }
7052             }
7053
7054             Date.parseRegexes[regexNum] = new RegExp("^" + regex.join('') + "$", "i");
7055             Date.parseFunctions[format] = new Function("input", "strict", xf(code, regexNum, calc.join('')));
7056         }
7057     }(),
7058
7059     
7060     parseCodes : {
7061         
7062         d: {
7063             g:1,
7064             c:"d = parseInt(results[{0}], 10);\n",
7065             s:"(\\d{2})" 
7066         },
7067         j: {
7068             g:1,
7069             c:"d = parseInt(results[{0}], 10);\n",
7070             s:"(\\d{1,2})" 
7071         },
7072         D: function() {
7073             for (var a = [], i = 0; i < 7; a.push(Date.getShortDayName(i)), ++i); 
7074             return {
7075                 g:0,
7076                 c:null,
7077                 s:"(?:" + a.join("|") +")"
7078             }
7079         },
7080         l: function() {
7081             return {
7082                 g:0,
7083                 c:null,
7084                 s:"(?:" + Date.dayNames.join("|") + ")"
7085             }
7086         },
7087         N: {
7088             g:0,
7089             c:null,
7090             s:"[1-7]" 
7091         },
7092         S: {
7093             g:0,
7094             c:null,
7095             s:"(?:st|nd|rd|th)"
7096         },
7097         w: {
7098             g:0,
7099             c:null,
7100             s:"[0-6]" 
7101         },
7102         z: {
7103             g:1,
7104             c:"z = parseInt(results[{0}], 10);\n",
7105             s:"(\\d{1,3})" 
7106         },
7107         W: {
7108             g:0,
7109             c:null,
7110             s:"(?:\\d{2})" 
7111         },
7112         F: function() {
7113             return {
7114                 g:1,
7115                 c:"m = parseInt(Date.getMonthNumber(results[{0}]), 10);\n", 
7116                 s:"(" + Date.monthNames.join("|") + ")"
7117             }
7118         },
7119         M: function() {
7120             for (var a = [], i = 0; i < 12; a.push(Date.getShortMonthName(i)), ++i); 
7121             return Ext.applyIf({
7122                 s:"(" + a.join("|") + ")"
7123             }, $f("F"));
7124         },
7125         m: {
7126             g:1,
7127             c:"m = parseInt(results[{0}], 10) - 1;\n",
7128             s:"(\\d{2})" 
7129         },
7130         n: {
7131             g:1,
7132             c:"m = parseInt(results[{0}], 10) - 1;\n",
7133             s:"(\\d{1,2})" 
7134         },
7135         t: {
7136             g:0,
7137             c:null,
7138             s:"(?:\\d{2})" 
7139         },
7140         L: {
7141             g:0,
7142             c:null,
7143             s:"(?:1|0)"
7144         },
7145         o: function() {
7146             return $f("Y");
7147         },
7148         Y: {
7149             g:1,
7150             c:"y = parseInt(results[{0}], 10);\n",
7151             s:"(\\d{4})" 
7152         },
7153         y: {
7154             g:1,
7155             c:"var ty = parseInt(results[{0}], 10);\n"
7156                 + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n", 
7157             s:"(\\d{1,2})"
7158         },
7159         a: {
7160             g:1,
7161             c:"if (results[{0}] == 'am') {\n"
7162                 + "if (!h || h == 12) { h = 0; }\n"
7163                 + "} else { if (!h || h < 12) { h = (h || 0) + 12; }}",
7164             s:"(am|pm)"
7165         },
7166         A: {
7167             g:1,
7168             c:"if (results[{0}] == 'AM') {\n"
7169                 + "if (!h || h == 12) { h = 0; }\n"
7170                 + "} else { if (!h || h < 12) { h = (h || 0) + 12; }}",
7171             s:"(AM|PM)"
7172         },
7173         g: function() {
7174             return $f("G");
7175         },
7176         G: {
7177             g:1,
7178             c:"h = parseInt(results[{0}], 10);\n",
7179             s:"(\\d{1,2})" 
7180         },
7181         h: function() {
7182             return $f("H");
7183         },
7184         H: {
7185             g:1,
7186             c:"h = parseInt(results[{0}], 10);\n",
7187             s:"(\\d{2})" 
7188         },
7189         i: {
7190             g:1,
7191             c:"i = parseInt(results[{0}], 10);\n",
7192             s:"(\\d{2})" 
7193         },
7194         s: {
7195             g:1,
7196             c:"s = parseInt(results[{0}], 10);\n",
7197             s:"(\\d{2})" 
7198         },
7199         u: {
7200             g:1,
7201             c:"ms = results[{0}]; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n",
7202             s:"(\\d+)" 
7203         },
7204         O: {
7205             g:1,
7206             c:[
7207                 "o = results[{0}];",
7208                 "var sn = o.substring(0,1),", 
7209                     "hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60),", 
7210                     "mn = o.substring(3,5) % 60;", 
7211                 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n" 
7212             ].join("\n"),
7213             s: "([+\-]\\d{4})" 
7214         },
7215         P: {
7216             g:1,
7217             c:[
7218                 "o = results[{0}];",
7219                 "var sn = o.substring(0,1),", 
7220                     "hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60),", 
7221                     "mn = o.substring(4,6) % 60;", 
7222                 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n" 
7223             ].join("\n"),
7224             s: "([+\-]\\d{2}:\\d{2})" 
7225         },
7226         T: {
7227             g:0,
7228             c:null,
7229             s:"[A-Z]{1,4}" 
7230         },
7231         Z: {
7232             g:1,
7233             c:"zz = results[{0}] * 1;\n" 
7234                   + "zz = (-43200 <= zz && zz <= 50400)? zz : null;\n",
7235             s:"([+\-]?\\d{1,5})" 
7236         },
7237         c: function() {
7238             var calc = [],
7239                 arr = [
7240                     $f("Y", 1), 
7241                     $f("m", 2), 
7242                     $f("d", 3), 
7243                     $f("h", 4), 
7244                     $f("i", 5), 
7245                     $f("s", 6), 
7246                     {c:"ms = results[7] || '0'; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n"}, 
7247                     {c:[ 
7248                         "if(results[8]) {", 
7249                             "if(results[8] == 'Z'){",
7250                                 "zz = 0;", 
7251                             "}else if (results[8].indexOf(':') > -1){",
7252                                 $f("P", 8).c, 
7253                             "}else{",
7254                                 $f("O", 8).c, 
7255                             "}",
7256                         "}"
7257                     ].join('\n')}
7258                 ];
7259
7260             for (var i = 0, l = arr.length; i < l; ++i) {
7261                 calc.push(arr[i].c);
7262             }
7263
7264             return {
7265                 g:1,
7266                 c:calc.join(""),
7267                 s:[
7268                     arr[0].s, 
7269                     "(?:", "-", arr[1].s, 
7270                         "(?:", "-", arr[2].s, 
7271                             "(?:",
7272                                 "(?:T| )?", 
7273                                 arr[3].s, ":", arr[4].s,  
7274                                 "(?::", arr[5].s, ")?", 
7275                                 "(?:(?:\\.|,)(\\d+))?", 
7276                                 "(Z|(?:[-+]\\d{2}(?::)?\\d{2}))?", 
7277                             ")?",
7278                         ")?",
7279                     ")?"
7280                 ].join("")
7281             }
7282         },
7283         U: {
7284             g:1,
7285             c:"u = parseInt(results[{0}], 10);\n",
7286             s:"(-?\\d+)" 
7287         }
7288     }
7289 });
7290
7291 }());
7292
7293 Ext.apply(Date.prototype, {
7294     
7295     dateFormat : function(format) {
7296         if (Date.formatFunctions[format] == null) {
7297             Date.createFormat(format);
7298         }
7299         return Date.formatFunctions[format].call(this);
7300     },
7301
7302     
7303     getTimezone : function() {
7304         
7305         
7306         
7307         
7308         
7309         
7310         
7311         
7312         
7313         
7314         
7315         
7316         return this.toString().replace(/^.* (?:\((.*)\)|([A-Z]{1,4})(?:[\-+][0-9]{4})?(?: -?\d+)?)$/, "$1$2").replace(/[^A-Z]/g, "");
7317     },
7318
7319     
7320     getGMTOffset : function(colon) {
7321         return (this.getTimezoneOffset() > 0 ? "-" : "+")
7322             + String.leftPad(Math.floor(Math.abs(this.getTimezoneOffset()) / 60), 2, "0")
7323             + (colon ? ":" : "")
7324             + String.leftPad(Math.abs(this.getTimezoneOffset() % 60), 2, "0");
7325     },
7326
7327     
7328     getDayOfYear: function() {
7329         var num = 0,
7330             d = this.clone(),
7331             m = this.getMonth(),
7332             i;
7333
7334         for (i = 0, d.setDate(1), d.setMonth(0); i < m; d.setMonth(++i)) {
7335             num += d.getDaysInMonth();
7336         }
7337         return num + this.getDate() - 1;
7338     },
7339
7340     
7341     getWeekOfYear : function() {
7342         
7343         var ms1d = 864e5, 
7344             ms7d = 7 * ms1d; 
7345
7346         return function() { 
7347             var DC3 = Date.UTC(this.getFullYear(), this.getMonth(), this.getDate() + 3) / ms1d, 
7348                 AWN = Math.floor(DC3 / 7), 
7349                 Wyr = new Date(AWN * ms7d).getUTCFullYear();
7350
7351             return AWN - Math.floor(Date.UTC(Wyr, 0, 7) / ms7d) + 1;
7352         }
7353     }(),
7354
7355     
7356     isLeapYear : function() {
7357         var year = this.getFullYear();
7358         return !!((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
7359     },
7360
7361     
7362     getFirstDayOfMonth : function() {
7363         var day = (this.getDay() - (this.getDate() - 1)) % 7;
7364         return (day < 0) ? (day + 7) : day;
7365     },
7366
7367     
7368     getLastDayOfMonth : function() {
7369         return this.getLastDateOfMonth().getDay();
7370     },
7371
7372
7373     
7374     getFirstDateOfMonth : function() {
7375         return new Date(this.getFullYear(), this.getMonth(), 1);
7376     },
7377
7378     
7379     getLastDateOfMonth : function() {
7380         return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
7381     },
7382
7383     
7384     getDaysInMonth: function() {
7385         var daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
7386
7387         return function() { 
7388             var m = this.getMonth();
7389
7390             return m == 1 && this.isLeapYear() ? 29 : daysInMonth[m];
7391         }
7392     }(),
7393
7394     
7395     getSuffix : function() {
7396         switch (this.getDate()) {
7397             case 1:
7398             case 21:
7399             case 31:
7400                 return "st";
7401             case 2:
7402             case 22:
7403                 return "nd";
7404             case 3:
7405             case 23:
7406                 return "rd";
7407             default:
7408                 return "th";
7409         }
7410     },
7411
7412     
7413     clone : function() {
7414         return new Date(this.getTime());
7415     },
7416
7417     
7418     isDST : function() {
7419         
7420         
7421         return new Date(this.getFullYear(), 0, 1).getTimezoneOffset() != this.getTimezoneOffset();
7422     },
7423
7424     
7425     clearTime : function(clone) {
7426         if (clone) {
7427             return this.clone().clearTime();
7428         }
7429
7430         
7431         var d = this.getDate();
7432
7433         
7434         this.setHours(0);
7435         this.setMinutes(0);
7436         this.setSeconds(0);
7437         this.setMilliseconds(0);
7438
7439         if (this.getDate() != d) { 
7440             
7441             
7442
7443             
7444             for (var hr = 1, c = this.add(Date.HOUR, hr); c.getDate() != d; hr++, c = this.add(Date.HOUR, hr));
7445
7446             this.setDate(d);
7447             this.setHours(c.getHours());
7448         }
7449
7450         return this;
7451     },
7452
7453     
7454     add : function(interval, value) {
7455         var d = this.clone();
7456         if (!interval || value === 0) return d;
7457
7458         switch(interval.toLowerCase()) {
7459             case Date.MILLI:
7460                 d.setMilliseconds(this.getMilliseconds() + value);
7461                 break;
7462             case Date.SECOND:
7463                 d.setSeconds(this.getSeconds() + value);
7464                 break;
7465             case Date.MINUTE:
7466                 d.setMinutes(this.getMinutes() + value);
7467                 break;
7468             case Date.HOUR:
7469                 d.setHours(this.getHours() + value);
7470                 break;
7471             case Date.DAY:
7472                 d.setDate(this.getDate() + value);
7473                 break;
7474             case Date.MONTH:
7475                 var day = this.getDate();
7476                 if (day > 28) {
7477                     day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
7478                 }
7479                 d.setDate(day);
7480                 d.setMonth(this.getMonth() + value);
7481                 break;
7482             case Date.YEAR:
7483                 d.setFullYear(this.getFullYear() + value);
7484                 break;
7485         }
7486         return d;
7487     },
7488
7489     
7490     between : function(start, end) {
7491         var t = this.getTime();
7492         return start.getTime() <= t && t <= end.getTime();
7493     }
7494 });
7495
7496
7497
7498 Date.prototype.format = Date.prototype.dateFormat;
7499
7500
7501
7502 if (Ext.isSafari && (navigator.userAgent.match(/WebKit\/(\d+)/)[1] || NaN) < 420) {
7503     Ext.apply(Date.prototype, {
7504         _xMonth : Date.prototype.setMonth,
7505         _xDate  : Date.prototype.setDate,
7506
7507         
7508         
7509         setMonth : function(num) {
7510             if (num <= -1) {
7511                 var n = Math.ceil(-num),
7512                     back_year = Math.ceil(n / 12),
7513                     month = (n % 12) ? 12 - n % 12 : 0;
7514
7515                 this.setFullYear(this.getFullYear() - back_year);
7516
7517                 return this._xMonth(month);
7518             } else {
7519                 return this._xMonth(num);
7520             }
7521         },
7522
7523         
7524         
7525         
7526         setDate : function(d) {
7527             
7528             
7529             return this.setTime(this.getTime() - (this.getDate() - d) * 864e5);
7530         }
7531     });
7532 }
7533
7534
7535
7536
7537 Ext.util.MixedCollection = function(allowFunctions, keyFn){
7538     this.items = [];
7539     this.map = {};
7540     this.keys = [];
7541     this.length = 0;
7542     this.addEvents(
7543         
7544         'clear',
7545         
7546         'add',
7547         
7548         'replace',
7549         
7550         'remove',
7551         'sort'
7552     );
7553     this.allowFunctions = allowFunctions === true;
7554     if(keyFn){
7555         this.getKey = keyFn;
7556     }
7557     Ext.util.MixedCollection.superclass.constructor.call(this);
7558 };
7559
7560 Ext.extend(Ext.util.MixedCollection, Ext.util.Observable, {
7561
7562     
7563     allowFunctions : false,
7564
7565     
7566     add : function(key, o){
7567         if(arguments.length == 1){
7568             o = arguments[0];
7569             key = this.getKey(o);
7570         }
7571         if(typeof key != 'undefined' && key !== null){
7572             var old = this.map[key];
7573             if(typeof old != 'undefined'){
7574                 return this.replace(key, o);
7575             }
7576             this.map[key] = o;
7577         }
7578         this.length++;
7579         this.items.push(o);
7580         this.keys.push(key);
7581         this.fireEvent('add', this.length-1, o, key);
7582         return o;
7583     },
7584
7585     
7586     getKey : function(o){
7587          return o.id;
7588     },
7589
7590     
7591     replace : function(key, o){
7592         if(arguments.length == 1){
7593             o = arguments[0];
7594             key = this.getKey(o);
7595         }
7596         var old = this.map[key];
7597         if(typeof key == 'undefined' || key === null || typeof old == 'undefined'){
7598              return this.add(key, o);
7599         }
7600         var index = this.indexOfKey(key);
7601         this.items[index] = o;
7602         this.map[key] = o;
7603         this.fireEvent('replace', key, old, o);
7604         return o;
7605     },
7606
7607     
7608     addAll : function(objs){
7609         if(arguments.length > 1 || Ext.isArray(objs)){
7610             var args = arguments.length > 1 ? arguments : objs;
7611             for(var i = 0, len = args.length; i < len; i++){
7612                 this.add(args[i]);
7613             }
7614         }else{
7615             for(var key in objs){
7616                 if(this.allowFunctions || typeof objs[key] != 'function'){
7617                     this.add(key, objs[key]);
7618                 }
7619             }
7620         }
7621     },
7622
7623     
7624     each : function(fn, scope){
7625         var items = [].concat(this.items); 
7626         for(var i = 0, len = items.length; i < len; i++){
7627             if(fn.call(scope || items[i], items[i], i, len) === false){
7628                 break;
7629             }
7630         }
7631     },
7632
7633     
7634     eachKey : function(fn, scope){
7635         for(var i = 0, len = this.keys.length; i < len; i++){
7636             fn.call(scope || window, this.keys[i], this.items[i], i, len);
7637         }
7638     },
7639
7640     
7641     find : function(fn, scope){
7642         for(var i = 0, len = this.items.length; i < len; i++){
7643             if(fn.call(scope || window, this.items[i], this.keys[i])){
7644                 return this.items[i];
7645             }
7646         }
7647         return null;
7648     },
7649
7650     
7651     insert : function(index, key, o){
7652         if(arguments.length == 2){
7653             o = arguments[1];
7654             key = this.getKey(o);
7655         }
7656         if(this.containsKey(key)){
7657             this.suspendEvents();
7658             this.removeKey(key);
7659             this.resumeEvents();
7660         }
7661         if(index >= this.length){
7662             return this.add(key, o);
7663         }
7664         this.length++;
7665         this.items.splice(index, 0, o);
7666         if(typeof key != 'undefined' && key !== null){
7667             this.map[key] = o;
7668         }
7669         this.keys.splice(index, 0, key);
7670         this.fireEvent('add', index, o, key);
7671         return o;
7672     },
7673
7674     
7675     remove : function(o){
7676         return this.removeAt(this.indexOf(o));
7677     },
7678
7679     
7680     removeAt : function(index){
7681         if(index < this.length && index >= 0){
7682             this.length--;
7683             var o = this.items[index];
7684             this.items.splice(index, 1);
7685             var key = this.keys[index];
7686             if(typeof key != 'undefined'){
7687                 delete this.map[key];
7688             }
7689             this.keys.splice(index, 1);
7690             this.fireEvent('remove', o, key);
7691             return o;
7692         }
7693         return false;
7694     },
7695
7696     
7697     removeKey : function(key){
7698         return this.removeAt(this.indexOfKey(key));
7699     },
7700
7701     
7702     getCount : function(){
7703         return this.length;
7704     },
7705
7706     
7707     indexOf : function(o){
7708         return this.items.indexOf(o);
7709     },
7710
7711     
7712     indexOfKey : function(key){
7713         return this.keys.indexOf(key);
7714     },
7715
7716     
7717     item : function(key){
7718         var mk = this.map[key],
7719             item = mk !== undefined ? mk : (typeof key == 'number') ? this.items[key] : undefined;
7720         return !Ext.isFunction(item) || this.allowFunctions ? item : null; 
7721     },
7722
7723     
7724     itemAt : function(index){
7725         return this.items[index];
7726     },
7727
7728     
7729     key : function(key){
7730         return this.map[key];
7731     },
7732
7733     
7734     contains : function(o){
7735         return this.indexOf(o) != -1;
7736     },
7737
7738     
7739     containsKey : function(key){
7740         return typeof this.map[key] != 'undefined';
7741     },
7742
7743     
7744     clear : function(){
7745         this.length = 0;
7746         this.items = [];
7747         this.keys = [];
7748         this.map = {};
7749         this.fireEvent('clear');
7750     },
7751
7752     
7753     first : function(){
7754         return this.items[0];
7755     },
7756
7757     
7758     last : function(){
7759         return this.items[this.length-1];
7760     },
7761
7762     
7763     _sort : function(property, dir, fn){
7764         var i,
7765             len,
7766             dsc = String(dir).toUpperCase() == 'DESC' ? -1 : 1,
7767             c = [], k = this.keys, items = this.items;
7768
7769         fn = fn || function(a, b){
7770             return a-b;
7771         };
7772         for(i = 0, len = items.length; i < len; i++){
7773             c[c.length] = {key: k[i], value: items[i], index: i};
7774         }
7775         c.sort(function(a, b){
7776             var v = fn(a[property], b[property]) * dsc;
7777             if(v === 0){
7778                 v = (a.index < b.index ? -1 : 1);
7779             }
7780             return v;
7781         });
7782         for(i = 0, len = c.length; i < len; i++){
7783             items[i] = c[i].value;
7784             k[i] = c[i].key;
7785         }
7786         this.fireEvent('sort', this);
7787     },
7788
7789     
7790     sort : function(dir, fn){
7791         this._sort('value', dir, fn);
7792     },
7793
7794     
7795     keySort : function(dir, fn){
7796         this._sort('key', dir, fn || function(a, b){
7797             var v1 = String(a).toUpperCase(), v2 = String(b).toUpperCase();
7798             return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
7799         });
7800     },
7801
7802     
7803     getRange : function(start, end){
7804         var items = this.items;
7805         if(items.length < 1){
7806             return [];
7807         }
7808         start = start || 0;
7809         end = Math.min(typeof end == 'undefined' ? this.length-1 : end, this.length-1);
7810         var i, r = [];
7811         if(start <= end){
7812             for(i = start; i <= end; i++) {
7813                 r[r.length] = items[i];
7814             }
7815         }else{
7816             for(i = start; i >= end; i--) {
7817                 r[r.length] = items[i];
7818             }
7819         }
7820         return r;
7821     },
7822
7823     
7824     filter : function(property, value, anyMatch, caseSensitive){
7825         if(Ext.isEmpty(value, false)){
7826             return this.clone();
7827         }
7828         value = this.createValueMatcher(value, anyMatch, caseSensitive);
7829         return this.filterBy(function(o){
7830             return o && value.test(o[property]);
7831         });
7832     },
7833
7834     
7835     filterBy : function(fn, scope){
7836         var r = new Ext.util.MixedCollection();
7837         r.getKey = this.getKey;
7838         var k = this.keys, it = this.items;
7839         for(var i = 0, len = it.length; i < len; i++){
7840             if(fn.call(scope||this, it[i], k[i])){
7841                 r.add(k[i], it[i]);
7842             }
7843         }
7844         return r;
7845     },
7846
7847     
7848     findIndex : function(property, value, start, anyMatch, caseSensitive){
7849         if(Ext.isEmpty(value, false)){
7850             return -1;
7851         }
7852         value = this.createValueMatcher(value, anyMatch, caseSensitive);
7853         return this.findIndexBy(function(o){
7854             return o && value.test(o[property]);
7855         }, null, start);
7856     },
7857
7858     
7859     findIndexBy : function(fn, scope, start){
7860         var k = this.keys, it = this.items;
7861         for(var i = (start||0), len = it.length; i < len; i++){
7862             if(fn.call(scope||this, it[i], k[i])){
7863                 return i;
7864             }
7865         }
7866         return -1;
7867     },
7868
7869     
7870     createValueMatcher : function(value, anyMatch, caseSensitive, exactMatch) {
7871         if (!value.exec) { 
7872             var er = Ext.escapeRe;
7873             value = String(value);
7874             if (anyMatch === true) {
7875                 value = er(value);
7876             } else {
7877                 value = '^' + er(value);
7878                 if (exactMatch === true) {
7879                     value += '$';
7880                 }
7881             }
7882             value = new RegExp(value, caseSensitive ? '' : 'i');
7883          }
7884          return value;
7885     },
7886
7887     
7888     clone : function(){
7889         var r = new Ext.util.MixedCollection();
7890         var k = this.keys, it = this.items;
7891         for(var i = 0, len = it.length; i < len; i++){
7892             r.add(k[i], it[i]);
7893         }
7894         r.getKey = this.getKey;
7895         return r;
7896     }
7897 });
7898
7899 Ext.util.MixedCollection.prototype.get = Ext.util.MixedCollection.prototype.item;
7900 Ext.util.JSON = new (function(){
7901     var useHasOwn = !!{}.hasOwnProperty,
7902         isNative = function() {
7903             var useNative = null;
7904
7905             return function() {
7906                 if (useNative === null) {
7907                     useNative = Ext.USE_NATIVE_JSON && window.JSON && JSON.toString() == '[object JSON]';
7908                 }
7909         
7910                 return useNative;
7911             };
7912         }(),
7913         pad = function(n) {
7914             return n < 10 ? "0" + n : n;
7915         },
7916         doDecode = function(json){
7917             return eval("(" + json + ')');    
7918         },
7919         doEncode = function(o){
7920             if(!Ext.isDefined(o) || o === null){
7921                 return "null";
7922             }else if(Ext.isArray(o)){
7923                 return encodeArray(o);
7924             }else if(Ext.isDate(o)){
7925                 return Ext.util.JSON.encodeDate(o);
7926             }else if(Ext.isString(o)){
7927                 return encodeString(o);
7928             }else if(typeof o == "number"){
7929                 
7930                 return isFinite(o) ? String(o) : "null";
7931             }else if(Ext.isBoolean(o)){
7932                 return String(o);
7933             }else {
7934                 var a = ["{"], b, i, v;
7935                 for (i in o) {
7936                     
7937                     if(!o.getElementsByTagName){
7938                         if(!useHasOwn || o.hasOwnProperty(i)) {
7939                             v = o[i];
7940                             switch (typeof v) {
7941                             case "undefined":
7942                             case "function":
7943                             case "unknown":
7944                                 break;
7945                             default:
7946                                 if(b){
7947                                     a.push(',');
7948                                 }
7949                                 a.push(doEncode(i), ":",
7950                                         v === null ? "null" : doEncode(v));
7951                                 b = true;
7952                             }
7953                         }
7954                     }
7955                 }
7956                 a.push("}");
7957                 return a.join("");
7958             }    
7959         },
7960         m = {
7961             "\b": '\\b',
7962             "\t": '\\t',
7963             "\n": '\\n',
7964             "\f": '\\f',
7965             "\r": '\\r',
7966             '"' : '\\"',
7967             "\\": '\\\\'
7968         },
7969         encodeString = function(s){
7970             if (/["\\\x00-\x1f]/.test(s)) {
7971                 return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
7972                     var c = m[b];
7973                     if(c){
7974                         return c;
7975                     }
7976                     c = b.charCodeAt();
7977                     return "\\u00" +
7978                         Math.floor(c / 16).toString(16) +
7979                         (c % 16).toString(16);
7980                 }) + '"';
7981             }
7982             return '"' + s + '"';
7983         },
7984         encodeArray = function(o){
7985             var a = ["["], b, i, l = o.length, v;
7986                 for (i = 0; i < l; i += 1) {
7987                     v = o[i];
7988                     switch (typeof v) {
7989                         case "undefined":
7990                         case "function":
7991                         case "unknown":
7992                             break;
7993                         default:
7994                             if (b) {
7995                                 a.push(',');
7996                             }
7997                             a.push(v === null ? "null" : Ext.util.JSON.encode(v));
7998                             b = true;
7999                     }
8000                 }
8001                 a.push("]");
8002                 return a.join("");
8003         };
8004
8005     this.encodeDate = function(o){
8006         return '"' + o.getFullYear() + "-" +
8007                 pad(o.getMonth() + 1) + "-" +
8008                 pad(o.getDate()) + "T" +
8009                 pad(o.getHours()) + ":" +
8010                 pad(o.getMinutes()) + ":" +
8011                 pad(o.getSeconds()) + '"';
8012     };
8013
8014     
8015     this.encode = function() {
8016         var ec;
8017         return function(o) {
8018             if (!ec) {
8019                 
8020                 ec = isNative() ? JSON.stringify : doEncode;
8021             }
8022             return ec(o);
8023         };
8024     }();
8025
8026
8027     
8028     this.decode = function() {
8029         var dc;
8030         return function(json) {
8031             if (!dc) {
8032                 
8033                 dc = isNative() ? JSON.parse : doDecode;
8034             }
8035             return dc(json);
8036         };
8037     }();
8038
8039 })();
8040
8041 Ext.encode = Ext.util.JSON.encode;
8042
8043 Ext.decode = Ext.util.JSON.decode;
8044
8045 Ext.util.Format = function(){
8046     var trimRe = /^\s+|\s+$/g,
8047         stripTagsRE = /<\/?[^>]+>/gi,
8048         stripScriptsRe = /(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig,
8049         nl2brRe = /\r?\n/g;
8050         
8051     return {
8052         
8053         ellipsis : function(value, len, word){
8054             if(value && value.length > len){
8055                 if(word){
8056                     var vs = value.substr(0, len - 2),
8057                         index = Math.max(vs.lastIndexOf(' '), vs.lastIndexOf('.'), vs.lastIndexOf('!'), vs.lastIndexOf('?'));
8058                     if(index == -1 || index < (len - 15)){
8059                         return value.substr(0, len - 3) + "...";
8060                     }else{
8061                         return vs.substr(0, index) + "...";
8062                     }
8063                 } else{
8064                     return value.substr(0, len - 3) + "...";
8065                 }
8066             }
8067             return value;
8068         },
8069
8070         
8071         undef : function(value){
8072             return value !== undefined ? value : "";
8073         },
8074
8075         
8076         defaultValue : function(value, defaultValue){
8077             return value !== undefined && value !== '' ? value : defaultValue;
8078         },
8079
8080         
8081         htmlEncode : function(value){
8082             return !value ? value : String(value).replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/</g, "&lt;").replace(/"/g, "&quot;");
8083         },
8084
8085         
8086         htmlDecode : function(value){
8087             return !value ? value : String(value).replace(/&gt;/g, ">").replace(/&lt;/g, "<").replace(/&quot;/g, '"').replace(/&amp;/g, "&");
8088         },
8089
8090         
8091         trim : function(value){
8092             return String(value).replace(trimRe, "");
8093         },
8094
8095         
8096         substr : function(value, start, length){
8097             return String(value).substr(start, length);
8098         },
8099
8100         
8101         lowercase : function(value){
8102             return String(value).toLowerCase();
8103         },
8104
8105         
8106         uppercase : function(value){
8107             return String(value).toUpperCase();
8108         },
8109
8110         
8111         capitalize : function(value){
8112             return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
8113         },
8114
8115         
8116         call : function(value, fn){
8117             if(arguments.length > 2){
8118                 var args = Array.prototype.slice.call(arguments, 2);
8119                 args.unshift(value);
8120                 return eval(fn).apply(window, args);
8121             }else{
8122                 return eval(fn).call(window, value);
8123             }
8124         },
8125
8126         
8127         usMoney : function(v){
8128             v = (Math.round((v-0)*100))/100;
8129             v = (v == Math.floor(v)) ? v + ".00" : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
8130             v = String(v);
8131             var ps = v.split('.'),
8132                 whole = ps[0],
8133                 sub = ps[1] ? '.'+ ps[1] : '.00',
8134                 r = /(\d+)(\d{3})/;
8135             while (r.test(whole)) {
8136                 whole = whole.replace(r, '$1' + ',' + '$2');
8137             }
8138             v = whole + sub;
8139             if(v.charAt(0) == '-'){
8140                 return '-$' + v.substr(1);
8141             }
8142             return "$" +  v;
8143         },
8144
8145         
8146         date : function(v, format){
8147             if(!v){
8148                 return "";
8149             }
8150             if(!Ext.isDate(v)){
8151                 v = new Date(Date.parse(v));
8152             }
8153             return v.dateFormat(format || "m/d/Y");
8154         },
8155
8156         
8157         dateRenderer : function(format){
8158             return function(v){
8159                 return Ext.util.Format.date(v, format);
8160             };
8161         },
8162         
8163         
8164         stripTags : function(v){
8165             return !v ? v : String(v).replace(stripTagsRE, "");
8166         },
8167
8168         
8169         stripScripts : function(v){
8170             return !v ? v : String(v).replace(stripScriptsRe, "");
8171         },
8172
8173         
8174         fileSize : function(size){
8175             if(size < 1024) {
8176                 return size + " bytes";
8177             } else if(size < 1048576) {
8178                 return (Math.round(((size*10) / 1024))/10) + " KB";
8179             } else {
8180                 return (Math.round(((size*10) / 1048576))/10) + " MB";
8181             }
8182         },
8183
8184         
8185         math : function(){
8186             var fns = {};
8187             return function(v, a){
8188                 if(!fns[a]){
8189                     fns[a] = new Function('v', 'return v ' + a + ';');
8190                 }
8191                 return fns[a](v);
8192             }
8193         }(),
8194
8195         
8196         round : function(value, precision) {
8197             var result = Number(value);
8198             if (typeof precision == 'number') {
8199                 precision = Math.pow(10, precision);
8200                 result = Math.round(value * precision) / precision;
8201             }
8202             return result;
8203         },
8204
8205         
8206         number: function(v, format) {
8207             if(!format){
8208                         return v;
8209                     }
8210                     v = Ext.num(v, NaN);
8211             if (isNaN(v)){
8212                 return '';
8213             }
8214                     var comma = ',',
8215                         dec = '.',
8216                         i18n = false,
8217                         neg = v < 0;
8218                 
8219                     v = Math.abs(v);
8220                     if(format.substr(format.length - 2) == '/i'){
8221                         format = format.substr(0, format.length - 2);
8222                         i18n = true;
8223                         comma = '.';
8224                         dec = ',';
8225                     }
8226                 
8227                     var hasComma = format.indexOf(comma) != -1, 
8228                         psplit = (i18n ? format.replace(/[^\d\,]/g, '') : format.replace(/[^\d\.]/g, '')).split(dec);
8229                 
8230                     if(1 < psplit.length){
8231                         v = v.toFixed(psplit[1].length);
8232                     }else if(2 < psplit.length){
8233                         throw ('NumberFormatException: invalid format, formats should have no more than 1 period: ' + format);
8234                     }else{
8235                         v = v.toFixed(0);
8236                     }
8237                 
8238                     var fnum = v.toString();
8239                     if(hasComma){
8240                         psplit = fnum.split('.');
8241                 
8242                         var cnum = psplit[0], parr = [], j = cnum.length, m = Math.floor(j / 3), n = cnum.length % 3 || 3;
8243                 
8244                         for(var i = 0; i < j; i += n){
8245                             if(i != 0){
8246                                 n = 3;
8247                             }
8248                             parr[parr.length] = cnum.substr(i, n);
8249                             m -= 1;
8250                         }
8251                         fnum = parr.join(comma);
8252                         if(psplit[1]){
8253                             fnum += dec + psplit[1];
8254                         }
8255                     }
8256                 
8257                     return (neg ? '-' : '') + format.replace(/[\d,?\.?]+/, fnum);
8258         },
8259
8260         
8261         numberRenderer : function(format){
8262             return function(v){
8263                 return Ext.util.Format.number(v, format);
8264             };
8265         },
8266
8267         
8268         plural : function(v, s, p){
8269             return v +' ' + (v == 1 ? s : (p ? p : s+'s'));
8270         },
8271         
8272         
8273         nl2br : function(v){
8274             return Ext.isEmpty(v) ? '' : v.replace(nl2brRe, '<br/>');
8275         }
8276     }
8277 }();
8278
8279 Ext.XTemplate = function(){
8280     Ext.XTemplate.superclass.constructor.apply(this, arguments);
8281
8282     var me = this,
8283         s = me.html,
8284         re = /<tpl\b[^>]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/,
8285         nameRe = /^<tpl\b[^>]*?for="(.*?)"/,
8286         ifRe = /^<tpl\b[^>]*?if="(.*?)"/,
8287         execRe = /^<tpl\b[^>]*?exec="(.*?)"/,
8288         m,
8289         id = 0,
8290         tpls = [],
8291         VALUES = 'values',
8292         PARENT = 'parent',
8293         XINDEX = 'xindex',
8294         XCOUNT = 'xcount',
8295         RETURN = 'return ',
8296         WITHVALUES = 'with(values){ ';
8297
8298     s = ['<tpl>', s, '</tpl>'].join('');
8299
8300     while((m = s.match(re))){
8301         var m2 = m[0].match(nameRe),
8302                         m3 = m[0].match(ifRe),
8303                 m4 = m[0].match(execRe),
8304                 exp = null,
8305                 fn = null,
8306                 exec = null,
8307                 name = m2 && m2[1] ? m2[1] : '';
8308
8309        if (m3) {
8310            exp = m3 && m3[1] ? m3[1] : null;
8311            if(exp){
8312                fn = new Function(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES + RETURN +(Ext.util.Format.htmlDecode(exp))+'; }');
8313            }
8314        }
8315        if (m4) {
8316            exp = m4 && m4[1] ? m4[1] : null;
8317            if(exp){
8318                exec = new Function(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES +(Ext.util.Format.htmlDecode(exp))+'; }');
8319            }
8320        }
8321        if(name){
8322            switch(name){
8323                case '.': name = new Function(VALUES, PARENT, WITHVALUES + RETURN + VALUES + '; }'); break;
8324                case '..': name = new Function(VALUES, PARENT, WITHVALUES + RETURN + PARENT + '; }'); break;
8325                default: name = new Function(VALUES, PARENT, WITHVALUES + RETURN + name + '; }');
8326            }
8327        }
8328        tpls.push({
8329             id: id,
8330             target: name,
8331             exec: exec,
8332             test: fn,
8333             body: m[1]||''
8334         });
8335        s = s.replace(m[0], '{xtpl'+ id + '}');
8336        ++id;
8337     }
8338         Ext.each(tpls, function(t) {
8339         me.compileTpl(t);
8340     });
8341     me.master = tpls[tpls.length-1];
8342     me.tpls = tpls;
8343 };
8344 Ext.extend(Ext.XTemplate, Ext.Template, {
8345     
8346     re : /\{([\w-\.\#]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?(\s?[\+\-\*\\]\s?[\d\.\+\-\*\\\(\)]+)?\}/g,
8347     
8348     codeRe : /\{\[((?:\\\]|.|\n)*?)\]\}/g,
8349
8350     
8351     applySubTemplate : function(id, values, parent, xindex, xcount){
8352         var me = this,
8353                 len,
8354                 t = me.tpls[id],
8355                 vs,
8356                 buf = [];
8357         if ((t.test && !t.test.call(me, values, parent, xindex, xcount)) ||
8358             (t.exec && t.exec.call(me, values, parent, xindex, xcount))) {
8359             return '';
8360         }
8361         vs = t.target ? t.target.call(me, values, parent) : values;
8362         len = vs.length;
8363         parent = t.target ? values : parent;
8364         if(t.target && Ext.isArray(vs)){
8365                 Ext.each(vs, function(v, i) {
8366                 buf[buf.length] = t.compiled.call(me, v, parent, i+1, len);
8367             });
8368             return buf.join('');
8369         }
8370         return t.compiled.call(me, vs, parent, xindex, xcount);
8371     },
8372
8373     
8374     compileTpl : function(tpl){
8375         var fm = Ext.util.Format,
8376                 useF = this.disableFormats !== true,
8377             sep = Ext.isGecko ? "+" : ",",
8378             body;
8379
8380         function fn(m, name, format, args, math){
8381             if(name.substr(0, 4) == 'xtpl'){
8382                 return "'"+ sep +'this.applySubTemplate('+name.substr(4)+', values, parent, xindex, xcount)'+sep+"'";
8383             }
8384             var v;
8385             if(name === '.'){
8386                 v = 'values';
8387             }else if(name === '#'){
8388                 v = 'xindex';
8389             }else if(name.indexOf('.') != -1){
8390                 v = name;
8391             }else{
8392                 v = "values['" + name + "']";
8393             }
8394             if(math){
8395                 v = '(' + v + math + ')';
8396             }
8397             if (format && useF) {
8398                 args = args ? ',' + args : "";
8399                 if(format.substr(0, 5) != "this."){
8400                     format = "fm." + format + '(';
8401                 }else{
8402                     format = 'this.call("'+ format.substr(5) + '", ';
8403                     args = ", values";
8404                 }
8405             } else {
8406                 args= ''; format = "("+v+" === undefined ? '' : ";
8407             }
8408             return "'"+ sep + format + v + args + ")"+sep+"'";
8409         }
8410
8411         function codeFn(m, code){
8412             
8413             return "'" + sep + '(' + code.replace(/\\'/g, "'") + ')' + sep + "'";
8414         }
8415
8416         
8417         if(Ext.isGecko){
8418             body = "tpl.compiled = function(values, parent, xindex, xcount){ return '" +
8419                    tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn).replace(this.codeRe, codeFn) +
8420                     "';};";
8421         }else{
8422             body = ["tpl.compiled = function(values, parent, xindex, xcount){ return ['"];
8423             body.push(tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn).replace(this.codeRe, codeFn));
8424             body.push("'].join('');};");
8425             body = body.join('');
8426         }
8427         eval(body);
8428         return this;
8429     },
8430
8431     
8432     applyTemplate : function(values){
8433         return this.master.compiled.call(this, values, {}, 1, 1);
8434     },
8435
8436     
8437     compile : function(){return this;}
8438
8439     
8440     
8441     
8442
8443 });
8444
8445 Ext.XTemplate.prototype.apply = Ext.XTemplate.prototype.applyTemplate;
8446
8447
8448 Ext.XTemplate.from = function(el){
8449     el = Ext.getDom(el);
8450     return new Ext.XTemplate(el.value || el.innerHTML);
8451 };
8452 Ext.util.CSS = function(){
8453         var rules = null;
8454         var doc = document;
8455
8456     var camelRe = /(-[a-z])/gi;
8457     var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
8458
8459    return {
8460    
8461    createStyleSheet : function(cssText, id){
8462        var ss;
8463        var head = doc.getElementsByTagName("head")[0];
8464        var rules = doc.createElement("style");
8465        rules.setAttribute("type", "text/css");
8466        if(id){
8467            rules.setAttribute("id", id);
8468        }
8469        if(Ext.isIE){
8470            head.appendChild(rules);
8471            ss = rules.styleSheet;
8472            ss.cssText = cssText;
8473        }else{
8474            try{
8475                 rules.appendChild(doc.createTextNode(cssText));
8476            }catch(e){
8477                rules.cssText = cssText;
8478            }
8479            head.appendChild(rules);
8480            ss = rules.styleSheet ? rules.styleSheet : (rules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
8481        }
8482        this.cacheStyleSheet(ss);
8483        return ss;
8484    },
8485
8486    
8487    removeStyleSheet : function(id){
8488        var existing = doc.getElementById(id);
8489        if(existing){
8490            existing.parentNode.removeChild(existing);
8491        }
8492    },
8493
8494    
8495    swapStyleSheet : function(id, url){
8496        this.removeStyleSheet(id);
8497        var ss = doc.createElement("link");
8498        ss.setAttribute("rel", "stylesheet");
8499        ss.setAttribute("type", "text/css");
8500        ss.setAttribute("id", id);
8501        ss.setAttribute("href", url);
8502        doc.getElementsByTagName("head")[0].appendChild(ss);
8503    },
8504    
8505    
8506    refreshCache : function(){
8507        return this.getRules(true);
8508    },
8509
8510    
8511    cacheStyleSheet : function(ss){
8512        if(!rules){
8513            rules = {};
8514        }
8515        try{
8516            var ssRules = ss.cssRules || ss.rules;
8517            for(var j = ssRules.length-1; j >= 0; --j){
8518                rules[ssRules[j].selectorText.toLowerCase()] = ssRules[j];
8519            }
8520        }catch(e){}
8521    },
8522    
8523    
8524    getRules : function(refreshCache){
8525                 if(rules === null || refreshCache){
8526                         rules = {};
8527                         var ds = doc.styleSheets;
8528                         for(var i =0, len = ds.length; i < len; i++){
8529                             try{
8530                         this.cacheStyleSheet(ds[i]);
8531                     }catch(e){} 
8532                 }
8533                 }
8534                 return rules;
8535         },
8536         
8537         
8538    getRule : function(selector, refreshCache){
8539                 var rs = this.getRules(refreshCache);
8540                 if(!Ext.isArray(selector)){
8541                     return rs[selector.toLowerCase()];
8542                 }
8543                 for(var i = 0; i < selector.length; i++){
8544                         if(rs[selector[i]]){
8545                                 return rs[selector[i].toLowerCase()];
8546                         }
8547                 }
8548                 return null;
8549         },
8550         
8551         
8552         
8553    updateRule : function(selector, property, value){
8554                 if(!Ext.isArray(selector)){
8555                         var rule = this.getRule(selector);
8556                         if(rule){
8557                                 rule.style[property.replace(camelRe, camelFn)] = value;
8558                                 return true;
8559                         }
8560                 }else{
8561                         for(var i = 0; i < selector.length; i++){
8562                                 if(this.updateRule(selector[i], property, value)){
8563                                         return true;
8564                                 }
8565                         }
8566                 }
8567                 return false;
8568         }
8569    };   
8570 }();
8571 Ext.util.ClickRepeater = function(el, config)
8572 {
8573     this.el = Ext.get(el);
8574     this.el.unselectable();
8575
8576     Ext.apply(this, config);
8577
8578     this.addEvents(
8579     
8580         "mousedown",
8581     
8582         "click",
8583     
8584         "mouseup"
8585     );
8586
8587     if(!this.disabled){
8588         this.disabled = true;
8589         this.enable();
8590     }
8591
8592     
8593     if(this.handler){
8594         this.on("click", this.handler,  this.scope || this);
8595     }
8596
8597     Ext.util.ClickRepeater.superclass.constructor.call(this);
8598 };
8599
8600 Ext.extend(Ext.util.ClickRepeater, Ext.util.Observable, {
8601     interval : 20,
8602     delay: 250,
8603     preventDefault : true,
8604     stopDefault : false,
8605     timer : 0,
8606
8607     
8608     enable: function(){
8609         if(this.disabled){
8610             this.el.on('mousedown', this.handleMouseDown, this);
8611             if(this.preventDefault || this.stopDefault){
8612                 this.el.on('click', this.eventOptions, this);
8613             }
8614         }
8615         this.disabled = false;
8616     },
8617     
8618     
8619     disable: function( force){
8620         if(force || !this.disabled){
8621             clearTimeout(this.timer);
8622             if(this.pressClass){
8623                 this.el.removeClass(this.pressClass);
8624             }
8625             Ext.getDoc().un('mouseup', this.handleMouseUp, this);
8626             this.el.removeAllListeners();
8627         }
8628         this.disabled = true;
8629     },
8630     
8631     
8632     setDisabled: function(disabled){
8633         this[disabled ? 'disable' : 'enable']();    
8634     },
8635     
8636     eventOptions: function(e){
8637         if(this.preventDefault){
8638             e.preventDefault();
8639         }
8640         if(this.stopDefault){
8641             e.stopEvent();
8642         }       
8643     },
8644     
8645     
8646     destroy : function() {
8647         this.disable(true);
8648         Ext.destroy(this.el);
8649         this.purgeListeners();
8650     },
8651     
8652     
8653     handleMouseDown : function(){
8654         clearTimeout(this.timer);
8655         this.el.blur();
8656         if(this.pressClass){
8657             this.el.addClass(this.pressClass);
8658         }
8659         this.mousedownTime = new Date();
8660
8661         Ext.getDoc().on("mouseup", this.handleMouseUp, this);
8662         this.el.on("mouseout", this.handleMouseOut, this);
8663
8664         this.fireEvent("mousedown", this);
8665         this.fireEvent("click", this);
8666
8667
8668         if (this.accelerate) {
8669             this.delay = 400;
8670             }
8671         this.timer = this.click.defer(this.delay || this.interval, this);
8672     },
8673
8674     
8675     click : function(){
8676         this.fireEvent("click", this);
8677         this.timer = this.click.defer(this.accelerate ?
8678             this.easeOutExpo(this.mousedownTime.getElapsed(),
8679                 400,
8680                 -390,
8681                 12000) :
8682             this.interval, this);
8683     },
8684
8685     easeOutExpo : function (t, b, c, d) {
8686         return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
8687     },
8688
8689     
8690     handleMouseOut : function(){
8691         clearTimeout(this.timer);
8692         if(this.pressClass){
8693             this.el.removeClass(this.pressClass);
8694         }
8695         this.el.on("mouseover", this.handleMouseReturn, this);
8696     },
8697
8698     
8699     handleMouseReturn : function(){
8700         this.el.un("mouseover", this.handleMouseReturn, this);
8701         if(this.pressClass){
8702             this.el.addClass(this.pressClass);
8703         }
8704         this.click();
8705     },
8706
8707     
8708     handleMouseUp : function(){
8709         clearTimeout(this.timer);
8710         this.el.un("mouseover", this.handleMouseReturn, this);
8711         this.el.un("mouseout", this.handleMouseOut, this);
8712         Ext.getDoc().un("mouseup", this.handleMouseUp, this);
8713         this.el.removeClass(this.pressClass);
8714         this.fireEvent("mouseup", this);
8715     }
8716 });
8717 Ext.KeyNav = function(el, config){
8718     this.el = Ext.get(el);
8719     Ext.apply(this, config);
8720     if(!this.disabled){
8721         this.disabled = true;
8722         this.enable();
8723     }
8724 };
8725
8726 Ext.KeyNav.prototype = {
8727     
8728     disabled : false,
8729     
8730     defaultEventAction: "stopEvent",
8731     
8732     forceKeyDown : false,
8733
8734     
8735     relay : function(e){
8736         var k = e.getKey();
8737         var h = this.keyToHandler[k];
8738         if(h && this[h]){
8739             if(this.doRelay(e, this[h], h) !== true){
8740                 e[this.defaultEventAction]();
8741             }
8742         }
8743     },
8744
8745     
8746     doRelay : function(e, h, hname){
8747         return h.call(this.scope || this, e);
8748     },
8749
8750     
8751     enter : false,
8752     left : false,
8753     right : false,
8754     up : false,
8755     down : false,
8756     tab : false,
8757     esc : false,
8758     pageUp : false,
8759     pageDown : false,
8760     del : false,
8761     home : false,
8762     end : false,
8763
8764     
8765     keyToHandler : {
8766         37 : "left",
8767         39 : "right",
8768         38 : "up",
8769         40 : "down",
8770         33 : "pageUp",
8771         34 : "pageDown",
8772         46 : "del",
8773         36 : "home",
8774         35 : "end",
8775         13 : "enter",
8776         27 : "esc",
8777         9  : "tab"
8778     },
8779     
8780     stopKeyUp: function(e) {
8781         var k = e.getKey();
8782
8783         if (k >= 37 && k <= 40) {
8784             
8785             
8786             e.stopEvent();
8787         }
8788     },
8789     
8790     
8791     destroy: function(){
8792         this.disable();    
8793     },
8794
8795         
8796         enable: function() {
8797         if (this.disabled) {
8798             if (Ext.isSafari2) {
8799                 
8800                 this.el.on('keyup', this.stopKeyUp, this);
8801             }
8802
8803             this.el.on(this.isKeydown()? 'keydown' : 'keypress', this.relay, this);
8804             this.disabled = false;
8805         }
8806     },
8807
8808         
8809         disable: function() {
8810         if (!this.disabled) {
8811             if (Ext.isSafari2) {
8812                 
8813                 this.el.un('keyup', this.stopKeyUp, this);
8814             }
8815
8816             this.el.un(this.isKeydown()? 'keydown' : 'keypress', this.relay, this);
8817             this.disabled = true;
8818         }
8819     },
8820     
8821     
8822     setDisabled : function(disabled){
8823         this[disabled ? "disable" : "enable"]();
8824     },
8825     
8826     
8827     isKeydown: function(){
8828         return this.forceKeyDown || Ext.EventManager.useKeydown;
8829     }
8830 };
8831
8832 Ext.KeyMap = function(el, config, eventName){
8833     this.el  = Ext.get(el);
8834     this.eventName = eventName || "keydown";
8835     this.bindings = [];
8836     if(config){
8837         this.addBinding(config);
8838     }
8839     this.enable();
8840 };
8841
8842 Ext.KeyMap.prototype = {
8843     
8844     stopEvent : false,
8845
8846     
8847         addBinding : function(config){
8848         if(Ext.isArray(config)){
8849             Ext.each(config, function(c){
8850                 this.addBinding(c);
8851             }, this);
8852             return;
8853         }
8854         var keyCode = config.key,
8855             fn = config.fn || config.handler,
8856             scope = config.scope;
8857
8858         if (config.stopEvent) {
8859             this.stopEvent = config.stopEvent;    
8860         }       
8861
8862         if(typeof keyCode == "string"){
8863             var ks = [];
8864             var keyString = keyCode.toUpperCase();
8865             for(var j = 0, len = keyString.length; j < len; j++){
8866                 ks.push(keyString.charCodeAt(j));
8867             }
8868             keyCode = ks;
8869         }
8870         var keyArray = Ext.isArray(keyCode);
8871         
8872         var handler = function(e){
8873             if(this.checkModifiers(config, e)){
8874                 var k = e.getKey();
8875                 if(keyArray){
8876                     for(var i = 0, len = keyCode.length; i < len; i++){
8877                         if(keyCode[i] == k){
8878                           if(this.stopEvent){
8879                               e.stopEvent();
8880                           }
8881                           fn.call(scope || window, k, e);
8882                           return;
8883                         }
8884                     }
8885                 }else{
8886                     if(k == keyCode){
8887                         if(this.stopEvent){
8888                            e.stopEvent();
8889                         }
8890                         fn.call(scope || window, k, e);
8891                     }
8892                 }
8893             }
8894         };
8895         this.bindings.push(handler);
8896         },
8897     
8898     
8899     checkModifiers: function(config, e){
8900         var val, key, keys = ['shift', 'ctrl', 'alt'];
8901         for (var i = 0, len = keys.length; i < len; ++i){
8902             key = keys[i];
8903             val = config[key];
8904             if(!(val === undefined || (val === e[key + 'Key']))){
8905                 return false;
8906             }
8907         }
8908         return true;
8909     },
8910
8911     
8912     on : function(key, fn, scope){
8913         var keyCode, shift, ctrl, alt;
8914         if(typeof key == "object" && !Ext.isArray(key)){
8915             keyCode = key.key;
8916             shift = key.shift;
8917             ctrl = key.ctrl;
8918             alt = key.alt;
8919         }else{
8920             keyCode = key;
8921         }
8922         this.addBinding({
8923             key: keyCode,
8924             shift: shift,
8925             ctrl: ctrl,
8926             alt: alt,
8927             fn: fn,
8928             scope: scope
8929         });
8930     },
8931
8932     
8933     handleKeyDown : function(e){
8934             if(this.enabled){ 
8935             var b = this.bindings;
8936             for(var i = 0, len = b.length; i < len; i++){
8937                 b[i].call(this, e);
8938             }
8939             }
8940         },
8941
8942         
8943         isEnabled : function(){
8944             return this.enabled;
8945         },
8946
8947         
8948         enable: function(){
8949                 if(!this.enabled){
8950                     this.el.on(this.eventName, this.handleKeyDown, this);
8951                     this.enabled = true;
8952                 }
8953         },
8954
8955         
8956         disable: function(){
8957                 if(this.enabled){
8958                     this.el.removeListener(this.eventName, this.handleKeyDown, this);
8959                     this.enabled = false;
8960                 }
8961         },
8962     
8963     
8964     setDisabled : function(disabled){
8965         this[disabled ? "disable" : "enable"]();
8966     }
8967 };
8968 Ext.util.TextMetrics = function(){
8969     var shared;
8970     return {
8971         
8972         measure : function(el, text, fixedWidth){
8973             if(!shared){
8974                 shared = Ext.util.TextMetrics.Instance(el, fixedWidth);
8975             }
8976             shared.bind(el);
8977             shared.setFixedWidth(fixedWidth || 'auto');
8978             return shared.getSize(text);
8979         },
8980
8981         
8982         createInstance : function(el, fixedWidth){
8983             return Ext.util.TextMetrics.Instance(el, fixedWidth);
8984         }
8985     };
8986 }();
8987
8988 Ext.util.TextMetrics.Instance = function(bindTo, fixedWidth){
8989     var ml = new Ext.Element(document.createElement('div'));
8990     document.body.appendChild(ml.dom);
8991     ml.position('absolute');
8992     ml.setLeftTop(-1000, -1000);
8993     ml.hide();
8994
8995     if(fixedWidth){
8996         ml.setWidth(fixedWidth);
8997     }
8998
8999     var instance = {
9000         
9001         getSize : function(text){
9002             ml.update(text);
9003             var s = ml.getSize();
9004             ml.update('');
9005             return s;
9006         },
9007
9008         
9009         bind : function(el){
9010             ml.setStyle(
9011                 Ext.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height', 'text-transform', 'letter-spacing')
9012             );
9013         },
9014
9015         
9016         setFixedWidth : function(width){
9017             ml.setWidth(width);
9018         },
9019
9020         
9021         getWidth : function(text){
9022             ml.dom.style.width = 'auto';
9023             return this.getSize(text).width;
9024         },
9025
9026         
9027         getHeight : function(text){
9028             return this.getSize(text).height;
9029         }
9030     };
9031
9032     instance.bind(bindTo);
9033
9034     return instance;
9035 };
9036
9037 Ext.Element.addMethods({
9038     
9039     getTextWidth : function(text, min, max){
9040         return (Ext.util.TextMetrics.measure(this.dom, Ext.value(text, this.dom.innerHTML, true)).width).constrain(min || 0, max || 1000000);
9041     }
9042 });
9043
9044 Ext.util.Cookies = {
9045     
9046     set : function(name, value){
9047         var argv = arguments;
9048         var argc = arguments.length;
9049         var expires = (argc > 2) ? argv[2] : null;
9050         var path = (argc > 3) ? argv[3] : '/';
9051         var domain = (argc > 4) ? argv[4] : null;
9052         var secure = (argc > 5) ? argv[5] : false;
9053         document.cookie = name + "=" + escape(value) + ((expires === null) ? "" : ("; expires=" + expires.toGMTString())) + ((path === null) ? "" : ("; path=" + path)) + ((domain === null) ? "" : ("; domain=" + domain)) + ((secure === true) ? "; secure" : "");
9054     },
9055
9056     
9057     get : function(name){
9058         var arg = name + "=";
9059         var alen = arg.length;
9060         var clen = document.cookie.length;
9061         var i = 0;
9062         var j = 0;
9063         while(i < clen){
9064             j = i + alen;
9065             if(document.cookie.substring(i, j) == arg){
9066                 return Ext.util.Cookies.getCookieVal(j);
9067             }
9068             i = document.cookie.indexOf(" ", i) + 1;
9069             if(i === 0){
9070                 break;
9071             }
9072         }
9073         return null;
9074     },
9075
9076     
9077     clear : function(name){
9078         if(Ext.util.Cookies.get(name)){
9079             document.cookie = name + "=" + "; expires=Thu, 01-Jan-70 00:00:01 GMT";
9080         }
9081     },
9082     
9083     getCookieVal : function(offset){
9084         var endstr = document.cookie.indexOf(";", offset);
9085         if(endstr == -1){
9086             endstr = document.cookie.length;
9087         }
9088         return unescape(document.cookie.substring(offset, endstr));
9089     }
9090 };
9091 Ext.handleError = function(e) {
9092     throw e;
9093 };
9094
9095
9096 Ext.Error = function(message) {
9097     
9098     this.message = (this.lang[message]) ? this.lang[message] : message;
9099 }
9100 Ext.Error.prototype = new Error();
9101 Ext.apply(Ext.Error.prototype, {
9102     
9103     lang: {},
9104
9105     name: 'Ext.Error',
9106     
9107     getName : function() {
9108         return this.name;
9109     },
9110     
9111     getMessage : function() {
9112         return this.message;
9113     },
9114     
9115     toJson : function() {
9116         return Ext.encode(this);
9117     }
9118 });
9119
9120
9121 Ext.ComponentMgr = function(){
9122     var all = new Ext.util.MixedCollection();
9123     var types = {};
9124     var ptypes = {};
9125
9126     return {
9127         
9128         register : function(c){
9129             all.add(c);
9130         },
9131
9132         
9133         unregister : function(c){
9134             all.remove(c);
9135         },
9136
9137         
9138         get : function(id){
9139             return all.get(id);
9140         },
9141
9142         
9143         onAvailable : function(id, fn, scope){
9144             all.on("add", function(index, o){
9145                 if(o.id == id){
9146                     fn.call(scope || o, o);
9147                     all.un("add", fn, scope);
9148                 }
9149             });
9150         },
9151
9152         
9153         all : all,
9154         
9155         
9156         isRegistered : function(xtype){
9157             return types[xtype] !== undefined;    
9158         },
9159
9160         
9161         registerType : function(xtype, cls){
9162             types[xtype] = cls;
9163             cls.xtype = xtype;
9164         },
9165
9166         
9167         create : function(config, defaultType){
9168             return config.render ? config : new types[config.xtype || defaultType](config);
9169         },
9170
9171         
9172         registerPlugin : function(ptype, cls){
9173             ptypes[ptype] = cls;
9174             cls.ptype = ptype;
9175         },
9176
9177         
9178         createPlugin : function(config, defaultType){
9179             var PluginCls = ptypes[config.ptype || defaultType];
9180             if (PluginCls.init) {
9181                 return PluginCls;                
9182             } else {
9183                 return new PluginCls(config);
9184             }            
9185         }
9186     };
9187 }();
9188
9189
9190 Ext.reg = Ext.ComponentMgr.registerType; 
9191
9192 Ext.preg = Ext.ComponentMgr.registerPlugin;
9193
9194 Ext.create = Ext.ComponentMgr.create;
9195 Ext.Component = function(config){
9196     config = config || {};
9197     if(config.initialConfig){
9198         if(config.isAction){           
9199             this.baseAction = config;
9200         }
9201         config = config.initialConfig; 
9202     }else if(config.tagName || config.dom || Ext.isString(config)){ 
9203         config = {applyTo: config, id: config.id || config};
9204     }
9205
9206     
9207     this.initialConfig = config;
9208
9209     Ext.apply(this, config);
9210     this.addEvents(
9211         
9212         'added',
9213         
9214         'disable',
9215         
9216         'enable',
9217         
9218         'beforeshow',
9219         
9220         'show',
9221         
9222         'beforehide',
9223         
9224         'hide',
9225         
9226         'removed',
9227         
9228         'beforerender',
9229         
9230         'render',
9231         
9232         'afterrender',
9233         
9234         'beforedestroy',
9235         
9236         'destroy',
9237         
9238         'beforestaterestore',
9239         
9240         'staterestore',
9241         
9242         'beforestatesave',
9243         
9244         'statesave'
9245     );
9246     this.getId();
9247     Ext.ComponentMgr.register(this);
9248     Ext.Component.superclass.constructor.call(this);
9249
9250     if(this.baseAction){
9251         this.baseAction.addComponent(this);
9252     }
9253
9254     this.initComponent();
9255
9256     if(this.plugins){
9257         if(Ext.isArray(this.plugins)){
9258             for(var i = 0, len = this.plugins.length; i < len; i++){
9259                 this.plugins[i] = this.initPlugin(this.plugins[i]);
9260             }
9261         }else{
9262             this.plugins = this.initPlugin(this.plugins);
9263         }
9264     }
9265
9266     if(this.stateful !== false){
9267         this.initState();
9268     }
9269
9270     if(this.applyTo){
9271         this.applyToMarkup(this.applyTo);
9272         delete this.applyTo;
9273     }else if(this.renderTo){
9274         this.render(this.renderTo);
9275         delete this.renderTo;
9276     }
9277 };
9278
9279
9280 Ext.Component.AUTO_ID = 1000;
9281
9282 Ext.extend(Ext.Component, Ext.util.Observable, {
9283     
9284     
9285     
9286     
9287     
9288     
9289     
9290
9291     
9292     
9293
9294     
9295     
9296     
9297     
9298     
9299     
9300     
9301     
9302     
9303     disabled : false,
9304     
9305     hidden : false,
9306     
9307     
9308     
9309     
9310     
9311     
9312     
9313     autoEl : 'div',
9314
9315     
9316     disabledClass : 'x-item-disabled',
9317     
9318     allowDomMove : true,
9319     
9320     autoShow : false,
9321     
9322     hideMode : 'display',
9323     
9324     hideParent : false,
9325     
9326     
9327     
9328     
9329     
9330     rendered : false,
9331
9332     
9333     
9334
9335     
9336
9337     
9338     tplWriteMode : 'overwrite',
9339
9340     
9341
9342
9343     
9344     ctype : 'Ext.Component',
9345
9346     
9347     actionMode : 'el',
9348
9349     
9350     getActionEl : function(){
9351         return this[this.actionMode];
9352     },
9353
9354     initPlugin : function(p){
9355         if(p.ptype && !Ext.isFunction(p.init)){
9356             p = Ext.ComponentMgr.createPlugin(p);
9357         }else if(Ext.isString(p)){
9358             p = Ext.ComponentMgr.createPlugin({
9359                 ptype: p
9360             });
9361         }
9362         p.init(this);
9363         return p;
9364     },
9365
9366     
9367     initComponent : Ext.emptyFn,
9368
9369     
9370     render : function(container, position){
9371         if(!this.rendered && this.fireEvent('beforerender', this) !== false){
9372             if(!container && this.el){
9373                 this.el = Ext.get(this.el);
9374                 container = this.el.dom.parentNode;
9375                 this.allowDomMove = false;
9376             }
9377             this.container = Ext.get(container);
9378             if(this.ctCls){
9379                 this.container.addClass(this.ctCls);
9380             }
9381             this.rendered = true;
9382             if(position !== undefined){
9383                 if(Ext.isNumber(position)){
9384                     position = this.container.dom.childNodes[position];
9385                 }else{
9386                     position = Ext.getDom(position);
9387                 }
9388             }
9389             this.onRender(this.container, position || null);
9390             if(this.autoShow){
9391                 this.el.removeClass(['x-hidden','x-hide-' + this.hideMode]);
9392             }
9393             if(this.cls){
9394                 this.el.addClass(this.cls);
9395                 delete this.cls;
9396             }
9397             if(this.style){
9398                 this.el.applyStyles(this.style);
9399                 delete this.style;
9400             }
9401             if(this.overCls){
9402                 this.el.addClassOnOver(this.overCls);
9403             }
9404             this.fireEvent('render', this);
9405
9406
9407             
9408             
9409             var contentTarget = this.getContentTarget();
9410             if (this.html){
9411                 contentTarget.update(Ext.DomHelper.markup(this.html));
9412                 delete this.html;
9413             }
9414             if (this.contentEl){
9415                 var ce = Ext.getDom(this.contentEl);
9416                 Ext.fly(ce).removeClass(['x-hidden', 'x-hide-display']);
9417                 contentTarget.appendChild(ce);
9418             }
9419             if (this.tpl) {
9420                 if (!this.tpl.compile) {
9421                     this.tpl = new Ext.XTemplate(this.tpl);
9422                 }
9423                 if (this.data) {
9424                     this.tpl[this.tplWriteMode](contentTarget, this.data);
9425                     delete this.data;
9426                 }
9427             }
9428             this.afterRender(this.container);
9429
9430
9431             if(this.hidden){
9432                 
9433                 this.doHide();
9434             }
9435             if(this.disabled){
9436                 
9437                 this.disable(true);
9438             }
9439
9440             if(this.stateful !== false){
9441                 this.initStateEvents();
9442             }
9443             this.fireEvent('afterrender', this);
9444         }
9445         return this;
9446     },
9447
9448
9449     
9450     update: function(htmlOrData, loadScripts, cb) {
9451         var contentTarget = this.getContentTarget();
9452         if (this.tpl && typeof htmlOrData !== "string") {
9453             this.tpl[this.tplWriteMode](contentTarget, htmlOrData || {});
9454         } else {
9455             var html = Ext.isObject(htmlOrData) ? Ext.DomHelper.markup(htmlOrData) : htmlOrData;
9456             contentTarget.update(html, loadScripts, cb);
9457         }
9458     },
9459
9460
9461     
9462     onAdded : function(container, pos) {
9463         this.ownerCt = container;
9464         this.initRef();
9465         this.fireEvent('added', this, container, pos);
9466     },
9467
9468     
9469     onRemoved : function() {
9470         this.removeRef();
9471         this.fireEvent('removed', this, this.ownerCt);
9472         delete this.ownerCt;
9473     },
9474
9475     
9476     initRef : function() {
9477         
9478         if(this.ref && !this.refOwner){
9479             var levels = this.ref.split('/'),
9480                 last = levels.length, 
9481                 i = 0,
9482                 t = this;
9483                 
9484             while(t && i < last){
9485                 t = t.ownerCt;
9486                 ++i;
9487             }
9488             if(t){
9489                 t[this.refName = levels[--i]] = this;
9490                 
9491                 this.refOwner = t;
9492             }
9493         }
9494     },
9495
9496     removeRef : function() {
9497         if (this.refOwner && this.refName) {
9498             delete this.refOwner[this.refName];
9499             delete this.refOwner;
9500         }
9501     },
9502
9503     
9504     initState : function(){
9505         if(Ext.state.Manager){
9506             var id = this.getStateId();
9507             if(id){
9508                 var state = Ext.state.Manager.get(id);
9509                 if(state){
9510                     if(this.fireEvent('beforestaterestore', this, state) !== false){
9511                         this.applyState(Ext.apply({}, state));
9512                         this.fireEvent('staterestore', this, state);
9513                     }
9514                 }
9515             }
9516         }
9517     },
9518
9519     
9520     getStateId : function(){
9521         return this.stateId || ((this.id.indexOf('ext-comp-') == 0 || this.id.indexOf('ext-gen') == 0) ? null : this.id);
9522     },
9523
9524     
9525     initStateEvents : function(){
9526         if(this.stateEvents){
9527             for(var i = 0, e; e = this.stateEvents[i]; i++){
9528                 this.on(e, this.saveState, this, {delay:100});
9529             }
9530         }
9531     },
9532
9533     
9534     applyState : function(state){
9535         if(state){
9536             Ext.apply(this, state);
9537         }
9538     },
9539
9540     
9541     getState : function(){
9542         return null;
9543     },
9544
9545     
9546     saveState : function(){
9547         if(Ext.state.Manager && this.stateful !== false){
9548             var id = this.getStateId();
9549             if(id){
9550                 var state = this.getState();
9551                 if(this.fireEvent('beforestatesave', this, state) !== false){
9552                     Ext.state.Manager.set(id, state);
9553                     this.fireEvent('statesave', this, state);
9554                 }
9555             }
9556         }
9557     },
9558
9559     
9560     applyToMarkup : function(el){
9561         this.allowDomMove = false;
9562         this.el = Ext.get(el);
9563         this.render(this.el.dom.parentNode);
9564     },
9565
9566     
9567     addClass : function(cls){
9568         if(this.el){
9569             this.el.addClass(cls);
9570         }else{
9571             this.cls = this.cls ? this.cls + ' ' + cls : cls;
9572         }
9573         return this;
9574     },
9575
9576     
9577     removeClass : function(cls){
9578         if(this.el){
9579             this.el.removeClass(cls);
9580         }else if(this.cls){
9581             this.cls = this.cls.split(' ').remove(cls).join(' ');
9582         }
9583         return this;
9584     },
9585
9586     
9587     
9588     onRender : function(ct, position){
9589         if(!this.el && this.autoEl){
9590             if(Ext.isString(this.autoEl)){
9591                 this.el = document.createElement(this.autoEl);
9592             }else{
9593                 var div = document.createElement('div');
9594                 Ext.DomHelper.overwrite(div, this.autoEl);
9595                 this.el = div.firstChild;
9596             }
9597             if (!this.el.id) {
9598                 this.el.id = this.getId();
9599             }
9600         }
9601         if(this.el){
9602             this.el = Ext.get(this.el);
9603             if(this.allowDomMove !== false){
9604                 ct.dom.insertBefore(this.el.dom, position);
9605                 if (div) {
9606                     Ext.removeNode(div);
9607                     div = null;
9608                 }
9609             }
9610         }
9611     },
9612
9613     
9614     getAutoCreate : function(){
9615         var cfg = Ext.isObject(this.autoCreate) ?
9616                       this.autoCreate : Ext.apply({}, this.defaultAutoCreate);
9617         if(this.id && !cfg.id){
9618             cfg.id = this.id;
9619         }
9620         return cfg;
9621     },
9622
9623     
9624     afterRender : Ext.emptyFn,
9625
9626     
9627     destroy : function(){
9628         if(!this.isDestroyed){
9629             if(this.fireEvent('beforedestroy', this) !== false){
9630                 this.destroying = true;
9631                 this.beforeDestroy();
9632                 if(this.ownerCt && this.ownerCt.remove){
9633                     this.ownerCt.remove(this, false);
9634                 }
9635                 if(this.rendered){
9636                     this.el.remove();
9637                     if(this.actionMode == 'container' || this.removeMode == 'container'){
9638                         this.container.remove();
9639                     }
9640                 }
9641                 this.onDestroy();
9642                 Ext.ComponentMgr.unregister(this);
9643                 this.fireEvent('destroy', this);
9644                 this.purgeListeners();
9645                 this.destroying = false;
9646                 this.isDestroyed = true;
9647             }
9648         }
9649     },
9650
9651     deleteMembers : function(){
9652         var args = arguments;
9653         for(var i = 0, len = args.length; i < len; ++i){
9654             delete this[args[i]];
9655         }
9656     },
9657
9658     
9659     beforeDestroy : Ext.emptyFn,
9660
9661     
9662     onDestroy  : Ext.emptyFn,
9663
9664     
9665     getEl : function(){
9666         return this.el;
9667     },
9668
9669     
9670     getContentTarget : function(){
9671         return this.el;
9672     },
9673
9674     
9675     getId : function(){
9676         return this.id || (this.id = 'ext-comp-' + (++Ext.Component.AUTO_ID));
9677     },
9678
9679     
9680     getItemId : function(){
9681         return this.itemId || this.getId();
9682     },
9683
9684     
9685     focus : function(selectText, delay){
9686         if(delay){
9687             this.focus.defer(Ext.isNumber(delay) ? delay : 10, this, [selectText, false]);
9688             return;
9689         }
9690         if(this.rendered){
9691             this.el.focus();
9692             if(selectText === true){
9693                 this.el.dom.select();
9694             }
9695         }
9696         return this;
9697     },
9698
9699     
9700     blur : function(){
9701         if(this.rendered){
9702             this.el.blur();
9703         }
9704         return this;
9705     },
9706
9707     
9708     disable : function( silent){
9709         if(this.rendered){
9710             this.onDisable();
9711         }
9712         this.disabled = true;
9713         if(silent !== true){
9714             this.fireEvent('disable', this);
9715         }
9716         return this;
9717     },
9718
9719     
9720     onDisable : function(){
9721         this.getActionEl().addClass(this.disabledClass);
9722         this.el.dom.disabled = true;
9723     },
9724
9725     
9726     enable : function(){
9727         if(this.rendered){
9728             this.onEnable();
9729         }
9730         this.disabled = false;
9731         this.fireEvent('enable', this);
9732         return this;
9733     },
9734
9735     
9736     onEnable : function(){
9737         this.getActionEl().removeClass(this.disabledClass);
9738         this.el.dom.disabled = false;
9739     },
9740
9741     
9742     setDisabled : function(disabled){
9743         return this[disabled ? 'disable' : 'enable']();
9744     },
9745
9746     
9747     show : function(){
9748         if(this.fireEvent('beforeshow', this) !== false){
9749             this.hidden = false;
9750             if(this.autoRender){
9751                 this.render(Ext.isBoolean(this.autoRender) ? Ext.getBody() : this.autoRender);
9752             }
9753             if(this.rendered){
9754                 this.onShow();
9755             }
9756             this.fireEvent('show', this);
9757         }
9758         return this;
9759     },
9760
9761     
9762     onShow : function(){
9763         this.getVisibilityEl().removeClass('x-hide-' + this.hideMode);
9764     },
9765
9766     
9767     hide : function(){
9768         if(this.fireEvent('beforehide', this) !== false){
9769             this.doHide();
9770             this.fireEvent('hide', this);
9771         }
9772         return this;
9773     },
9774
9775     
9776     doHide: function(){
9777         this.hidden = true;
9778         if(this.rendered){
9779             this.onHide();
9780         }
9781     },
9782
9783     
9784     onHide : function(){
9785         this.getVisibilityEl().addClass('x-hide-' + this.hideMode);
9786     },
9787
9788     
9789     getVisibilityEl : function(){
9790         return this.hideParent ? this.container : this.getActionEl();
9791     },
9792
9793     
9794     setVisible : function(visible){
9795         return this[visible ? 'show' : 'hide']();
9796     },
9797
9798     
9799     isVisible : function(){
9800         return this.rendered && this.getVisibilityEl().isVisible();
9801     },
9802
9803     
9804     cloneConfig : function(overrides){
9805         overrides = overrides || {};
9806         var id = overrides.id || Ext.id();
9807         var cfg = Ext.applyIf(overrides, this.initialConfig);
9808         cfg.id = id; 
9809         return new this.constructor(cfg);
9810     },
9811
9812     
9813     getXType : function(){
9814         return this.constructor.xtype;
9815     },
9816
9817     
9818     isXType : function(xtype, shallow){
9819         
9820         if (Ext.isFunction(xtype)){
9821             xtype = xtype.xtype; 
9822         }else if (Ext.isObject(xtype)){
9823             xtype = xtype.constructor.xtype; 
9824         }
9825
9826         return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1 : this.constructor.xtype == xtype;
9827     },
9828
9829     
9830     getXTypes : function(){
9831         var tc = this.constructor;
9832         if(!tc.xtypes){
9833             var c = [], sc = this;
9834             while(sc && sc.constructor.xtype){
9835                 c.unshift(sc.constructor.xtype);
9836                 sc = sc.constructor.superclass;
9837             }
9838             tc.xtypeChain = c;
9839             tc.xtypes = c.join('/');
9840         }
9841         return tc.xtypes;
9842     },
9843
9844     
9845     findParentBy : function(fn) {
9846         for (var p = this.ownerCt; (p != null) && !fn(p, this); p = p.ownerCt);
9847         return p || null;
9848     },
9849
9850     
9851     findParentByType : function(xtype) {
9852         return Ext.isFunction(xtype) ?
9853             this.findParentBy(function(p){
9854                 return p.constructor === xtype;
9855             }) :
9856             this.findParentBy(function(p){
9857                 return p.constructor.xtype === xtype;
9858             });
9859     },
9860
9861     
9862     getPositionEl : function(){
9863         return this.positionEl || this.el;
9864     },
9865
9866     
9867     purgeListeners : function(){
9868         Ext.Component.superclass.purgeListeners.call(this);
9869         if(this.mons){
9870             this.on('beforedestroy', this.clearMons, this, {single: true});
9871         }
9872     },
9873
9874     
9875     clearMons : function(){
9876         Ext.each(this.mons, function(m){
9877             m.item.un(m.ename, m.fn, m.scope);
9878         }, this);
9879         this.mons = [];
9880     },
9881
9882     
9883     createMons: function(){
9884         if(!this.mons){
9885             this.mons = [];
9886             this.on('beforedestroy', this.clearMons, this, {single: true});
9887         }
9888     },
9889
9890     
9891     mon : function(item, ename, fn, scope, opt){
9892         this.createMons();
9893         if(Ext.isObject(ename)){
9894             var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
9895
9896             var o = ename;
9897             for(var e in o){
9898                 if(propRe.test(e)){
9899                     continue;
9900                 }
9901                 if(Ext.isFunction(o[e])){
9902                     
9903                     this.mons.push({
9904                         item: item, ename: e, fn: o[e], scope: o.scope
9905                     });
9906                     item.on(e, o[e], o.scope, o);
9907                 }else{
9908                     
9909                     this.mons.push({
9910                         item: item, ename: e, fn: o[e], scope: o.scope
9911                     });
9912                     item.on(e, o[e]);
9913                 }
9914             }
9915             return;
9916         }
9917
9918         this.mons.push({
9919             item: item, ename: ename, fn: fn, scope: scope
9920         });
9921         item.on(ename, fn, scope, opt);
9922     },
9923
9924     
9925     mun : function(item, ename, fn, scope){
9926         var found, mon;
9927         this.createMons();
9928         for(var i = 0, len = this.mons.length; i < len; ++i){
9929             mon = this.mons[i];
9930             if(item === mon.item && ename == mon.ename && fn === mon.fn && scope === mon.scope){
9931                 this.mons.splice(i, 1);
9932                 item.un(ename, fn, scope);
9933                 found = true;
9934                 break;
9935             }
9936         }
9937         return found;
9938     },
9939
9940     
9941     nextSibling : function(){
9942         if(this.ownerCt){
9943             var index = this.ownerCt.items.indexOf(this);
9944             if(index != -1 && index+1 < this.ownerCt.items.getCount()){
9945                 return this.ownerCt.items.itemAt(index+1);
9946             }
9947         }
9948         return null;
9949     },
9950
9951     
9952     previousSibling : function(){
9953         if(this.ownerCt){
9954             var index = this.ownerCt.items.indexOf(this);
9955             if(index > 0){
9956                 return this.ownerCt.items.itemAt(index-1);
9957             }
9958         }
9959         return null;
9960     },
9961
9962     
9963     getBubbleTarget : function(){
9964         return this.ownerCt;
9965     }
9966 });
9967
9968 Ext.reg('component', Ext.Component);
9969 Ext.Action = Ext.extend(Object, {
9970     
9971     
9972     
9973     
9974     
9975     
9976     
9977
9978     constructor : function(config){
9979         this.initialConfig = config;
9980         this.itemId = config.itemId = (config.itemId || config.id || Ext.id());
9981         this.items = [];
9982     },
9983     
9984     
9985     isAction : true,
9986
9987     
9988     setText : function(text){
9989         this.initialConfig.text = text;
9990         this.callEach('setText', [text]);
9991     },
9992
9993     
9994     getText : function(){
9995         return this.initialConfig.text;
9996     },
9997
9998     
9999     setIconClass : function(cls){
10000         this.initialConfig.iconCls = cls;
10001         this.callEach('setIconClass', [cls]);
10002     },
10003
10004     
10005     getIconClass : function(){
10006         return this.initialConfig.iconCls;
10007     },
10008
10009     
10010     setDisabled : function(v){
10011         this.initialConfig.disabled = v;
10012         this.callEach('setDisabled', [v]);
10013     },
10014
10015     
10016     enable : function(){
10017         this.setDisabled(false);
10018     },
10019
10020     
10021     disable : function(){
10022         this.setDisabled(true);
10023     },
10024
10025     
10026     isDisabled : function(){
10027         return this.initialConfig.disabled;
10028     },
10029
10030     
10031     setHidden : function(v){
10032         this.initialConfig.hidden = v;
10033         this.callEach('setVisible', [!v]);
10034     },
10035
10036     
10037     show : function(){
10038         this.setHidden(false);
10039     },
10040
10041     
10042     hide : function(){
10043         this.setHidden(true);
10044     },
10045
10046     
10047     isHidden : function(){
10048         return this.initialConfig.hidden;
10049     },
10050
10051     
10052     setHandler : function(fn, scope){
10053         this.initialConfig.handler = fn;
10054         this.initialConfig.scope = scope;
10055         this.callEach('setHandler', [fn, scope]);
10056     },
10057
10058     
10059     each : function(fn, scope){
10060         Ext.each(this.items, fn, scope);
10061     },
10062
10063     
10064     callEach : function(fnName, args){
10065         var cs = this.items;
10066         for(var i = 0, len = cs.length; i < len; i++){
10067             cs[i][fnName].apply(cs[i], args);
10068         }
10069     },
10070
10071     
10072     addComponent : function(comp){
10073         this.items.push(comp);
10074         comp.on('destroy', this.removeComponent, this);
10075     },
10076
10077     
10078     removeComponent : function(comp){
10079         this.items.remove(comp);
10080     },
10081
10082     
10083     execute : function(){
10084         this.initialConfig.handler.apply(this.initialConfig.scope || window, arguments);
10085     }
10086 });
10087
10088 (function(){
10089 Ext.Layer = function(config, existingEl){
10090     config = config || {};
10091     var dh = Ext.DomHelper;
10092     var cp = config.parentEl, pel = cp ? Ext.getDom(cp) : document.body;
10093     if(existingEl){
10094         this.dom = Ext.getDom(existingEl);
10095     }
10096     if(!this.dom){
10097         var o = config.dh || {tag: 'div', cls: 'x-layer'};
10098         this.dom = dh.append(pel, o);
10099     }
10100     if(config.cls){
10101         this.addClass(config.cls);
10102     }
10103     this.constrain = config.constrain !== false;
10104     this.setVisibilityMode(Ext.Element.VISIBILITY);
10105     if(config.id){
10106         this.id = this.dom.id = config.id;
10107     }else{
10108         this.id = Ext.id(this.dom);
10109     }
10110     this.zindex = config.zindex || this.getZIndex();
10111     this.position('absolute', this.zindex);
10112     if(config.shadow){
10113         this.shadowOffset = config.shadowOffset || 4;
10114         this.shadow = new Ext.Shadow({
10115             offset : this.shadowOffset,
10116             mode : config.shadow
10117         });
10118     }else{
10119         this.shadowOffset = 0;
10120     }
10121     this.useShim = config.shim !== false && Ext.useShims;
10122     this.useDisplay = config.useDisplay;
10123     this.hide();
10124 };
10125
10126 var supr = Ext.Element.prototype;
10127
10128
10129 var shims = [];
10130
10131 Ext.extend(Ext.Layer, Ext.Element, {
10132
10133     getZIndex : function(){
10134         return this.zindex || parseInt((this.getShim() || this).getStyle('z-index'), 10) || 11000;
10135     },
10136
10137     getShim : function(){
10138         if(!this.useShim){
10139             return null;
10140         }
10141         if(this.shim){
10142             return this.shim;
10143         }
10144         var shim = shims.shift();
10145         if(!shim){
10146             shim = this.createShim();
10147             shim.enableDisplayMode('block');
10148             shim.dom.style.display = 'none';
10149             shim.dom.style.visibility = 'visible';
10150         }
10151         var pn = this.dom.parentNode;
10152         if(shim.dom.parentNode != pn){
10153             pn.insertBefore(shim.dom, this.dom);
10154         }
10155         shim.setStyle('z-index', this.getZIndex()-2);
10156         this.shim = shim;
10157         return shim;
10158     },
10159
10160     hideShim : function(){
10161         if(this.shim){
10162             this.shim.setDisplayed(false);
10163             shims.push(this.shim);
10164             delete this.shim;
10165         }
10166     },
10167
10168     disableShadow : function(){
10169         if(this.shadow){
10170             this.shadowDisabled = true;
10171             this.shadow.hide();
10172             this.lastShadowOffset = this.shadowOffset;
10173             this.shadowOffset = 0;
10174         }
10175     },
10176
10177     enableShadow : function(show){
10178         if(this.shadow){
10179             this.shadowDisabled = false;
10180             this.shadowOffset = this.lastShadowOffset;
10181             delete this.lastShadowOffset;
10182             if(show){
10183                 this.sync(true);
10184             }
10185         }
10186     },
10187
10188     
10189     
10190     
10191     sync : function(doShow){
10192         var sw = this.shadow;
10193         if(!this.updating && this.isVisible() && (sw || this.useShim)){
10194             var sh = this.getShim();
10195
10196             var w = this.getWidth(),
10197                 h = this.getHeight();
10198
10199             var l = this.getLeft(true),
10200                 t = this.getTop(true);
10201
10202             if(sw && !this.shadowDisabled){
10203                 if(doShow && !sw.isVisible()){
10204                     sw.show(this);
10205                 }else{
10206                     sw.realign(l, t, w, h);
10207                 }
10208                 if(sh){
10209                     if(doShow){
10210                        sh.show();
10211                     }
10212                     
10213                     var a = sw.adjusts, s = sh.dom.style;
10214                     s.left = (Math.min(l, l+a.l))+'px';
10215                     s.top = (Math.min(t, t+a.t))+'px';
10216                     s.width = (w+a.w)+'px';
10217                     s.height = (h+a.h)+'px';
10218                 }
10219             }else if(sh){
10220                 if(doShow){
10221                    sh.show();
10222                 }
10223                 sh.setSize(w, h);
10224                 sh.setLeftTop(l, t);
10225             }
10226
10227         }
10228     },
10229
10230     
10231     destroy : function(){
10232         this.hideShim();
10233         if(this.shadow){
10234             this.shadow.hide();
10235         }
10236         this.removeAllListeners();
10237         Ext.removeNode(this.dom);
10238         delete this.dom;
10239     },
10240
10241     remove : function(){
10242         this.destroy();
10243     },
10244
10245     
10246     beginUpdate : function(){
10247         this.updating = true;
10248     },
10249
10250     
10251     endUpdate : function(){
10252         this.updating = false;
10253         this.sync(true);
10254     },
10255
10256     
10257     hideUnders : function(negOffset){
10258         if(this.shadow){
10259             this.shadow.hide();
10260         }
10261         this.hideShim();
10262     },
10263
10264     
10265     constrainXY : function(){
10266         if(this.constrain){
10267             var vw = Ext.lib.Dom.getViewWidth(),
10268                 vh = Ext.lib.Dom.getViewHeight();
10269             var s = Ext.getDoc().getScroll();
10270
10271             var xy = this.getXY();
10272             var x = xy[0], y = xy[1];
10273             var so = this.shadowOffset;
10274             var w = this.dom.offsetWidth+so, h = this.dom.offsetHeight+so;
10275             
10276             var moved = false;
10277             
10278             if((x + w) > vw+s.left){
10279                 x = vw - w - so;
10280                 moved = true;
10281             }
10282             if((y + h) > vh+s.top){
10283                 y = vh - h - so;
10284                 moved = true;
10285             }
10286             
10287             if(x < s.left){
10288                 x = s.left;
10289                 moved = true;
10290             }
10291             if(y < s.top){
10292                 y = s.top;
10293                 moved = true;
10294             }
10295             if(moved){
10296                 if(this.avoidY){
10297                     var ay = this.avoidY;
10298                     if(y <= ay && (y+h) >= ay){
10299                         y = ay-h-5;
10300                     }
10301                 }
10302                 xy = [x, y];
10303                 this.storeXY(xy);
10304                 supr.setXY.call(this, xy);
10305                 this.sync();
10306             }
10307         }
10308         return this;
10309     },
10310
10311     isVisible : function(){
10312         return this.visible;
10313     },
10314
10315     
10316     showAction : function(){
10317         this.visible = true; 
10318         if(this.useDisplay === true){
10319             this.setDisplayed('');
10320         }else if(this.lastXY){
10321             supr.setXY.call(this, this.lastXY);
10322         }else if(this.lastLT){
10323             supr.setLeftTop.call(this, this.lastLT[0], this.lastLT[1]);
10324         }
10325     },
10326
10327     
10328     hideAction : function(){
10329         this.visible = false;
10330         if(this.useDisplay === true){
10331             this.setDisplayed(false);
10332         }else{
10333             this.setLeftTop(-10000,-10000);
10334         }
10335     },
10336
10337     
10338     setVisible : function(v, a, d, c, e){
10339         if(v){
10340             this.showAction();
10341         }
10342         if(a && v){
10343             var cb = function(){
10344                 this.sync(true);
10345                 if(c){
10346                     c();
10347                 }
10348             }.createDelegate(this);
10349             supr.setVisible.call(this, true, true, d, cb, e);
10350         }else{
10351             if(!v){
10352                 this.hideUnders(true);
10353             }
10354             var cb = c;
10355             if(a){
10356                 cb = function(){
10357                     this.hideAction();
10358                     if(c){
10359                         c();
10360                     }
10361                 }.createDelegate(this);
10362             }
10363             supr.setVisible.call(this, v, a, d, cb, e);
10364             if(v){
10365                 this.sync(true);
10366             }else if(!a){
10367                 this.hideAction();
10368             }
10369         }
10370         return this;
10371     },
10372
10373     storeXY : function(xy){
10374         delete this.lastLT;
10375         this.lastXY = xy;
10376     },
10377
10378     storeLeftTop : function(left, top){
10379         delete this.lastXY;
10380         this.lastLT = [left, top];
10381     },
10382
10383     
10384     beforeFx : function(){
10385         this.beforeAction();
10386         return Ext.Layer.superclass.beforeFx.apply(this, arguments);
10387     },
10388
10389     
10390     afterFx : function(){
10391         Ext.Layer.superclass.afterFx.apply(this, arguments);
10392         this.sync(this.isVisible());
10393     },
10394
10395     
10396     beforeAction : function(){
10397         if(!this.updating && this.shadow){
10398             this.shadow.hide();
10399         }
10400     },
10401
10402     
10403     setLeft : function(left){
10404         this.storeLeftTop(left, this.getTop(true));
10405         supr.setLeft.apply(this, arguments);
10406         this.sync();
10407         return this;
10408     },
10409
10410     setTop : function(top){
10411         this.storeLeftTop(this.getLeft(true), top);
10412         supr.setTop.apply(this, arguments);
10413         this.sync();
10414         return this;
10415     },
10416
10417     setLeftTop : function(left, top){
10418         this.storeLeftTop(left, top);
10419         supr.setLeftTop.apply(this, arguments);
10420         this.sync();
10421         return this;
10422     },
10423
10424     setXY : function(xy, a, d, c, e){
10425         this.fixDisplay();
10426         this.beforeAction();
10427         this.storeXY(xy);
10428         var cb = this.createCB(c);
10429         supr.setXY.call(this, xy, a, d, cb, e);
10430         if(!a){
10431             cb();
10432         }
10433         return this;
10434     },
10435
10436     
10437     createCB : function(c){
10438         var el = this;
10439         return function(){
10440             el.constrainXY();
10441             el.sync(true);
10442             if(c){
10443                 c();
10444             }
10445         };
10446     },
10447
10448     
10449     setX : function(x, a, d, c, e){
10450         this.setXY([x, this.getY()], a, d, c, e);
10451         return this;
10452     },
10453
10454     
10455     setY : function(y, a, d, c, e){
10456         this.setXY([this.getX(), y], a, d, c, e);
10457         return this;
10458     },
10459
10460     
10461     setSize : function(w, h, a, d, c, e){
10462         this.beforeAction();
10463         var cb = this.createCB(c);
10464         supr.setSize.call(this, w, h, a, d, cb, e);
10465         if(!a){
10466             cb();
10467         }
10468         return this;
10469     },
10470
10471     
10472     setWidth : function(w, a, d, c, e){
10473         this.beforeAction();
10474         var cb = this.createCB(c);
10475         supr.setWidth.call(this, w, a, d, cb, e);
10476         if(!a){
10477             cb();
10478         }
10479         return this;
10480     },
10481
10482     
10483     setHeight : function(h, a, d, c, e){
10484         this.beforeAction();
10485         var cb = this.createCB(c);
10486         supr.setHeight.call(this, h, a, d, cb, e);
10487         if(!a){
10488             cb();
10489         }
10490         return this;
10491     },
10492
10493     
10494     setBounds : function(x, y, w, h, a, d, c, e){
10495         this.beforeAction();
10496         var cb = this.createCB(c);
10497         if(!a){
10498             this.storeXY([x, y]);
10499             supr.setXY.call(this, [x, y]);
10500             supr.setSize.call(this, w, h, a, d, cb, e);
10501             cb();
10502         }else{
10503             supr.setBounds.call(this, x, y, w, h, a, d, cb, e);
10504         }
10505         return this;
10506     },
10507
10508     
10509     setZIndex : function(zindex){
10510         this.zindex = zindex;
10511         this.setStyle('z-index', zindex + 2);
10512         if(this.shadow){
10513             this.shadow.setZIndex(zindex + 1);
10514         }
10515         if(this.shim){
10516             this.shim.setStyle('z-index', zindex);
10517         }
10518         return this;
10519     }
10520 });
10521 })();
10522
10523 Ext.Shadow = function(config){
10524     Ext.apply(this, config);
10525     if(typeof this.mode != "string"){
10526         this.mode = this.defaultMode;
10527     }
10528     var o = this.offset, a = {h: 0};
10529     var rad = Math.floor(this.offset/2);
10530     switch(this.mode.toLowerCase()){ 
10531         case "drop":
10532             a.w = 0;
10533             a.l = a.t = o;
10534             a.t -= 1;
10535             if(Ext.isIE){
10536                 a.l -= this.offset + rad;
10537                 a.t -= this.offset + rad;
10538                 a.w -= rad;
10539                 a.h -= rad;
10540                 a.t += 1;
10541             }
10542         break;
10543         case "sides":
10544             a.w = (o*2);
10545             a.l = -o;
10546             a.t = o-1;
10547             if(Ext.isIE){
10548                 a.l -= (this.offset - rad);
10549                 a.t -= this.offset + rad;
10550                 a.l += 1;
10551                 a.w -= (this.offset - rad)*2;
10552                 a.w -= rad + 1;
10553                 a.h -= 1;
10554             }
10555         break;
10556         case "frame":
10557             a.w = a.h = (o*2);
10558             a.l = a.t = -o;
10559             a.t += 1;
10560             a.h -= 2;
10561             if(Ext.isIE){
10562                 a.l -= (this.offset - rad);
10563                 a.t -= (this.offset - rad);
10564                 a.l += 1;
10565                 a.w -= (this.offset + rad + 1);
10566                 a.h -= (this.offset + rad);
10567                 a.h += 1;
10568             }
10569         break;
10570     };
10571
10572     this.adjusts = a;
10573 };
10574
10575 Ext.Shadow.prototype = {
10576     
10577     
10578     offset: 4,
10579
10580     
10581     defaultMode: "drop",
10582
10583     
10584     show : function(target){
10585         target = Ext.get(target);
10586         if(!this.el){
10587             this.el = Ext.Shadow.Pool.pull();
10588             if(this.el.dom.nextSibling != target.dom){
10589                 this.el.insertBefore(target);
10590             }
10591         }
10592         this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10)-1);
10593         if(Ext.isIE){
10594             this.el.dom.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius="+(this.offset)+")";
10595         }
10596         this.realign(
10597             target.getLeft(true),
10598             target.getTop(true),
10599             target.getWidth(),
10600             target.getHeight()
10601         );
10602         this.el.dom.style.display = "block";
10603     },
10604
10605     
10606     isVisible : function(){
10607         return this.el ? true : false;  
10608     },
10609
10610     
10611     realign : function(l, t, w, h){
10612         if(!this.el){
10613             return;
10614         }
10615         var a = this.adjusts, d = this.el.dom, s = d.style;
10616         var iea = 0;
10617         s.left = (l+a.l)+"px";
10618         s.top = (t+a.t)+"px";
10619         var sw = (w+a.w), sh = (h+a.h), sws = sw +"px", shs = sh + "px";
10620         if(s.width != sws || s.height != shs){
10621             s.width = sws;
10622             s.height = shs;
10623             if(!Ext.isIE){
10624                 var cn = d.childNodes;
10625                 var sww = Math.max(0, (sw-12))+"px";
10626                 cn[0].childNodes[1].style.width = sww;
10627                 cn[1].childNodes[1].style.width = sww;
10628                 cn[2].childNodes[1].style.width = sww;
10629                 cn[1].style.height = Math.max(0, (sh-12))+"px";
10630             }
10631         }
10632     },
10633
10634     
10635     hide : function(){
10636         if(this.el){
10637             this.el.dom.style.display = "none";
10638             Ext.Shadow.Pool.push(this.el);
10639             delete this.el;
10640         }
10641     },
10642
10643     
10644     setZIndex : function(z){
10645         this.zIndex = z;
10646         if(this.el){
10647             this.el.setStyle("z-index", z);
10648         }
10649     }
10650 };
10651
10652
10653 Ext.Shadow.Pool = function(){
10654     var p = [];
10655     var markup = Ext.isIE ?
10656                  '<div class="x-ie-shadow"></div>' :
10657                  '<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>';
10658     return {
10659         pull : function(){
10660             var sh = p.shift();
10661             if(!sh){
10662                 sh = Ext.get(Ext.DomHelper.insertHtml("beforeBegin", document.body.firstChild, markup));
10663                 sh.autoBoxAdjust = false;
10664             }
10665             return sh;
10666         },
10667
10668         push : function(sh){
10669             p.push(sh);
10670         }
10671     };
10672 }();
10673 Ext.BoxComponent = Ext.extend(Ext.Component, {
10674
10675     
10676     
10677     
10678     
10679     
10680     
10681     
10682     
10683     
10684     
10685     
10686     
10687     
10688     
10689     
10690     
10691     
10692     
10693     
10694
10695     
10696
10697     
10698     initComponent : function(){
10699         Ext.BoxComponent.superclass.initComponent.call(this);
10700         this.addEvents(
10701             
10702             'resize',
10703             
10704             'move'
10705         );
10706     },
10707
10708     
10709     boxReady : false,
10710     
10711     deferHeight: false,
10712
10713     
10714     setSize : function(w, h){
10715
10716         
10717         if(typeof w == 'object'){
10718             h = w.height, w = w.width;
10719         }
10720         if (Ext.isDefined(w) && Ext.isDefined(this.boxMinWidth) && (w < this.boxMinWidth)) {
10721             w = this.boxMinWidth;
10722         }
10723         if (Ext.isDefined(h) && Ext.isDefined(this.boxMinHeight) && (h < this.boxMinHeight)) {
10724             h = this.boxMinHeight;
10725         }
10726         if (Ext.isDefined(w) && Ext.isDefined(this.boxMaxWidth) && (w > this.boxMaxWidth)) {
10727             w = this.boxMaxWidth;
10728         }
10729         if (Ext.isDefined(h) && Ext.isDefined(this.boxMaxHeight) && (h > this.boxMaxHeight)) {
10730             h = this.boxMaxHeight;
10731         }
10732         
10733         if(!this.boxReady){
10734             this.width = w, this.height = h;
10735             return this;
10736         }
10737
10738         
10739         if(this.cacheSizes !== false && this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
10740             return this;
10741         }
10742         this.lastSize = {width: w, height: h};
10743         var adj = this.adjustSize(w, h),
10744             aw = adj.width,
10745             ah = adj.height,
10746             rz;
10747         if(aw !== undefined || ah !== undefined){ 
10748             rz = this.getResizeEl();
10749             if(!this.deferHeight && aw !== undefined && ah !== undefined){
10750                 rz.setSize(aw, ah);
10751             }else if(!this.deferHeight && ah !== undefined){
10752                 rz.setHeight(ah);
10753             }else if(aw !== undefined){
10754                 rz.setWidth(aw);
10755             }
10756             this.onResize(aw, ah, w, h);
10757         }
10758         return this;
10759     },
10760
10761     
10762     setWidth : function(width){
10763         return this.setSize(width);
10764     },
10765
10766     
10767     setHeight : function(height){
10768         return this.setSize(undefined, height);
10769     },
10770
10771     
10772     getSize : function(){
10773         return this.getResizeEl().getSize();
10774     },
10775
10776     
10777     getWidth : function(){
10778         return this.getResizeEl().getWidth();
10779     },
10780
10781     
10782     getHeight : function(){
10783         return this.getResizeEl().getHeight();
10784     },
10785
10786     
10787     getOuterSize : function(){
10788         var el = this.getResizeEl();
10789         return {width: el.getWidth() + el.getMargins('lr'),
10790                 height: el.getHeight() + el.getMargins('tb')};
10791     },
10792
10793     
10794     getPosition : function(local){
10795         var el = this.getPositionEl();
10796         if(local === true){
10797             return [el.getLeft(true), el.getTop(true)];
10798         }
10799         return this.xy || el.getXY();
10800     },
10801
10802     
10803     getBox : function(local){
10804         var pos = this.getPosition(local);
10805         var s = this.getSize();
10806         s.x = pos[0];
10807         s.y = pos[1];
10808         return s;
10809     },
10810
10811     
10812     updateBox : function(box){
10813         this.setSize(box.width, box.height);
10814         this.setPagePosition(box.x, box.y);
10815         return this;
10816     },
10817
10818     
10819     getResizeEl : function(){
10820         return this.resizeEl || this.el;
10821     },
10822
10823     
10824     setAutoScroll : function(scroll){
10825         if(this.rendered){
10826             this.getContentTarget().setOverflow(scroll ? 'auto' : '');
10827         }
10828         this.autoScroll = scroll;
10829         return this;
10830     },
10831
10832     
10833     setPosition : function(x, y){
10834         if(x && typeof x[1] == 'number'){
10835             y = x[1];
10836             x = x[0];
10837         }
10838         this.x = x;
10839         this.y = y;
10840         if(!this.boxReady){
10841             return this;
10842         }
10843         var adj = this.adjustPosition(x, y);
10844         var ax = adj.x, ay = adj.y;
10845
10846         var el = this.getPositionEl();
10847         if(ax !== undefined || ay !== undefined){
10848             if(ax !== undefined && ay !== undefined){
10849                 el.setLeftTop(ax, ay);
10850             }else if(ax !== undefined){
10851                 el.setLeft(ax);
10852             }else if(ay !== undefined){
10853                 el.setTop(ay);
10854             }
10855             this.onPosition(ax, ay);
10856             this.fireEvent('move', this, ax, ay);
10857         }
10858         return this;
10859     },
10860
10861     
10862     setPagePosition : function(x, y){
10863         if(x && typeof x[1] == 'number'){
10864             y = x[1];
10865             x = x[0];
10866         }
10867         this.pageX = x;
10868         this.pageY = y;
10869         if(!this.boxReady){
10870             return;
10871         }
10872         if(x === undefined || y === undefined){ 
10873             return;
10874         }
10875         var p = this.getPositionEl().translatePoints(x, y);
10876         this.setPosition(p.left, p.top);
10877         return this;
10878     },
10879
10880     
10881     afterRender : function(){
10882         Ext.BoxComponent.superclass.afterRender.call(this);
10883         if(this.resizeEl){
10884             this.resizeEl = Ext.get(this.resizeEl);
10885         }
10886         if(this.positionEl){
10887             this.positionEl = Ext.get(this.positionEl);
10888         }
10889         this.boxReady = true;
10890         this.setAutoScroll(this.autoScroll);
10891         this.setSize(this.width, this.height);
10892         if(this.x || this.y){
10893             this.setPosition(this.x, this.y);
10894         }else if(this.pageX || this.pageY){
10895             this.setPagePosition(this.pageX, this.pageY);
10896         }
10897     },
10898
10899     
10900     syncSize : function(){
10901         delete this.lastSize;
10902         this.setSize(this.autoWidth ? undefined : this.getResizeEl().getWidth(), this.autoHeight ? undefined : this.getResizeEl().getHeight());
10903         return this;
10904     },
10905
10906     
10907     onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
10908         this.fireEvent('resize', this, adjWidth, adjHeight, rawWidth, rawHeight);
10909     },
10910
10911     
10912     onPosition : function(x, y){
10913
10914     },
10915
10916     
10917     adjustSize : function(w, h){
10918         if(this.autoWidth){
10919             w = 'auto';
10920         }
10921         if(this.autoHeight){
10922             h = 'auto';
10923         }
10924         return {width : w, height: h};
10925     },
10926
10927     
10928     adjustPosition : function(x, y){
10929         return {x : x, y: y};
10930     }
10931 });
10932 Ext.reg('box', Ext.BoxComponent);
10933
10934
10935
10936 Ext.Spacer = Ext.extend(Ext.BoxComponent, {
10937     autoEl:'div'
10938 });
10939 Ext.reg('spacer', Ext.Spacer);
10940 Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy){
10941
10942     
10943     this.el = Ext.get(dragElement, true);
10944     this.el.dom.unselectable = "on";
10945     
10946     this.resizingEl = Ext.get(resizingElement, true);
10947
10948     
10949     this.orientation = orientation || Ext.SplitBar.HORIZONTAL;
10950
10951     
10952     
10953     this.minSize = 0;
10954
10955     
10956     this.maxSize = 2000;
10957
10958     
10959     this.animate = false;
10960
10961     
10962     this.useShim = false;
10963
10964     
10965     this.shim = null;
10966
10967     if(!existingProxy){
10968         
10969         this.proxy = Ext.SplitBar.createProxy(this.orientation);
10970     }else{
10971         this.proxy = Ext.get(existingProxy).dom;
10972     }
10973     
10974     this.dd = new Ext.dd.DDProxy(this.el.dom.id, "XSplitBars", {dragElId : this.proxy.id});
10975
10976     
10977     this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);
10978
10979     
10980     this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);
10981
10982     
10983     this.dragSpecs = {};
10984
10985     
10986     this.adapter = new Ext.SplitBar.BasicLayoutAdapter();
10987     this.adapter.init(this);
10988
10989     if(this.orientation == Ext.SplitBar.HORIZONTAL){
10990         
10991         this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? Ext.SplitBar.LEFT : Ext.SplitBar.RIGHT);
10992         this.el.addClass("x-splitbar-h");
10993     }else{
10994         
10995         this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? Ext.SplitBar.TOP : Ext.SplitBar.BOTTOM);
10996         this.el.addClass("x-splitbar-v");
10997     }
10998
10999     this.addEvents(
11000         
11001         "resize",
11002         
11003         "moved",
11004         
11005         "beforeresize",
11006
11007         "beforeapply"
11008     );
11009
11010     Ext.SplitBar.superclass.constructor.call(this);
11011 };
11012
11013 Ext.extend(Ext.SplitBar, Ext.util.Observable, {
11014     onStartProxyDrag : function(x, y){
11015         this.fireEvent("beforeresize", this);
11016         this.overlay =  Ext.DomHelper.append(document.body,  {cls: "x-drag-overlay", html: "&#160;"}, true);
11017         this.overlay.unselectable();
11018         this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
11019         this.overlay.show();
11020         Ext.get(this.proxy).setDisplayed("block");
11021         var size = this.adapter.getElementSize(this);
11022         this.activeMinSize = this.getMinimumSize();
11023         this.activeMaxSize = this.getMaximumSize();
11024         var c1 = size - this.activeMinSize;
11025         var c2 = Math.max(this.activeMaxSize - size, 0);
11026         if(this.orientation == Ext.SplitBar.HORIZONTAL){
11027             this.dd.resetConstraints();
11028             this.dd.setXConstraint(
11029                 this.placement == Ext.SplitBar.LEFT ? c1 : c2,
11030                 this.placement == Ext.SplitBar.LEFT ? c2 : c1,
11031                 this.tickSize
11032             );
11033             this.dd.setYConstraint(0, 0);
11034         }else{
11035             this.dd.resetConstraints();
11036             this.dd.setXConstraint(0, 0);
11037             this.dd.setYConstraint(
11038                 this.placement == Ext.SplitBar.TOP ? c1 : c2,
11039                 this.placement == Ext.SplitBar.TOP ? c2 : c1,
11040                 this.tickSize
11041             );
11042          }
11043         this.dragSpecs.startSize = size;
11044         this.dragSpecs.startPoint = [x, y];
11045         Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);
11046     },
11047
11048     
11049     onEndProxyDrag : function(e){
11050         Ext.get(this.proxy).setDisplayed(false);
11051         var endPoint = Ext.lib.Event.getXY(e);
11052         if(this.overlay){
11053             Ext.destroy(this.overlay);
11054             delete this.overlay;
11055         }
11056         var newSize;
11057         if(this.orientation == Ext.SplitBar.HORIZONTAL){
11058             newSize = this.dragSpecs.startSize +
11059                 (this.placement == Ext.SplitBar.LEFT ?
11060                     endPoint[0] - this.dragSpecs.startPoint[0] :
11061                     this.dragSpecs.startPoint[0] - endPoint[0]
11062                 );
11063         }else{
11064             newSize = this.dragSpecs.startSize +
11065                 (this.placement == Ext.SplitBar.TOP ?
11066                     endPoint[1] - this.dragSpecs.startPoint[1] :
11067                     this.dragSpecs.startPoint[1] - endPoint[1]
11068                 );
11069         }
11070         newSize = Math.min(Math.max(newSize, this.activeMinSize), this.activeMaxSize);
11071         if(newSize != this.dragSpecs.startSize){
11072             if(this.fireEvent('beforeapply', this, newSize) !== false){
11073                 this.adapter.setElementSize(this, newSize);
11074                 this.fireEvent("moved", this, newSize);
11075                 this.fireEvent("resize", this, newSize);
11076             }
11077         }
11078     },
11079
11080     
11081     getAdapter : function(){
11082         return this.adapter;
11083     },
11084
11085     
11086     setAdapter : function(adapter){
11087         this.adapter = adapter;
11088         this.adapter.init(this);
11089     },
11090
11091     
11092     getMinimumSize : function(){
11093         return this.minSize;
11094     },
11095
11096     
11097     setMinimumSize : function(minSize){
11098         this.minSize = minSize;
11099     },
11100
11101     
11102     getMaximumSize : function(){
11103         return this.maxSize;
11104     },
11105
11106     
11107     setMaximumSize : function(maxSize){
11108         this.maxSize = maxSize;
11109     },
11110
11111     
11112     setCurrentSize : function(size){
11113         var oldAnimate = this.animate;
11114         this.animate = false;
11115         this.adapter.setElementSize(this, size);
11116         this.animate = oldAnimate;
11117     },
11118
11119     
11120     destroy : function(removeEl){
11121         Ext.destroy(this.shim, Ext.get(this.proxy));
11122         this.dd.unreg();
11123         if(removeEl){
11124             this.el.remove();
11125         }
11126         this.purgeListeners();
11127     }
11128 });
11129
11130
11131 Ext.SplitBar.createProxy = function(dir){
11132     var proxy = new Ext.Element(document.createElement("div"));
11133     document.body.appendChild(proxy.dom);
11134     proxy.unselectable();
11135     var cls = 'x-splitbar-proxy';
11136     proxy.addClass(cls + ' ' + (dir == Ext.SplitBar.HORIZONTAL ? cls +'-h' : cls + '-v'));
11137     return proxy.dom;
11138 };
11139
11140
11141 Ext.SplitBar.BasicLayoutAdapter = function(){
11142 };
11143
11144 Ext.SplitBar.BasicLayoutAdapter.prototype = {
11145     
11146     init : function(s){
11147
11148     },
11149     
11150      getElementSize : function(s){
11151         if(s.orientation == Ext.SplitBar.HORIZONTAL){
11152             return s.resizingEl.getWidth();
11153         }else{
11154             return s.resizingEl.getHeight();
11155         }
11156     },
11157
11158     
11159     setElementSize : function(s, newSize, onComplete){
11160         if(s.orientation == Ext.SplitBar.HORIZONTAL){
11161             if(!s.animate){
11162                 s.resizingEl.setWidth(newSize);
11163                 if(onComplete){
11164                     onComplete(s, newSize);
11165                 }
11166             }else{
11167                 s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');
11168             }
11169         }else{
11170
11171             if(!s.animate){
11172                 s.resizingEl.setHeight(newSize);
11173                 if(onComplete){
11174                     onComplete(s, newSize);
11175                 }
11176             }else{
11177                 s.resizingEl.setHeight(newSize, true, .1, onComplete, 'easeOut');
11178             }
11179         }
11180     }
11181 };
11182
11183
11184 Ext.SplitBar.AbsoluteLayoutAdapter = function(container){
11185     this.basic = new Ext.SplitBar.BasicLayoutAdapter();
11186     this.container = Ext.get(container);
11187 };
11188
11189 Ext.SplitBar.AbsoluteLayoutAdapter.prototype = {
11190     init : function(s){
11191         this.basic.init(s);
11192     },
11193
11194     getElementSize : function(s){
11195         return this.basic.getElementSize(s);
11196     },
11197
11198     setElementSize : function(s, newSize, onComplete){
11199         this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));
11200     },
11201
11202     moveSplitter : function(s){
11203         var yes = Ext.SplitBar;
11204         switch(s.placement){
11205             case yes.LEFT:
11206                 s.el.setX(s.resizingEl.getRight());
11207                 break;
11208             case yes.RIGHT:
11209                 s.el.setStyle("right", (this.container.getWidth() - s.resizingEl.getLeft()) + "px");
11210                 break;
11211             case yes.TOP:
11212                 s.el.setY(s.resizingEl.getBottom());
11213                 break;
11214             case yes.BOTTOM:
11215                 s.el.setY(s.resizingEl.getTop() - s.el.getHeight());
11216                 break;
11217         }
11218     }
11219 };
11220
11221
11222 Ext.SplitBar.VERTICAL = 1;
11223
11224
11225 Ext.SplitBar.HORIZONTAL = 2;
11226
11227
11228 Ext.SplitBar.LEFT = 1;
11229
11230
11231 Ext.SplitBar.RIGHT = 2;
11232
11233
11234 Ext.SplitBar.TOP = 3;
11235
11236
11237 Ext.SplitBar.BOTTOM = 4;
11238
11239 Ext.Container = Ext.extend(Ext.BoxComponent, {
11240     
11241     
11242     
11243     
11244     bufferResize: 50,
11245
11246     
11247     
11248     
11249
11250
11251     
11252     autoDestroy : true,
11253
11254     
11255     forceLayout: false,
11256
11257     
11258     
11259     defaultType : 'panel',
11260
11261     
11262     resizeEvent: 'resize',
11263
11264     
11265     bubbleEvents: ['add', 'remove'],
11266
11267     
11268     initComponent : function(){
11269         Ext.Container.superclass.initComponent.call(this);
11270
11271         this.addEvents(
11272             
11273             'afterlayout',
11274             
11275             'beforeadd',
11276             
11277             'beforeremove',
11278             
11279             'add',
11280             
11281             'remove'
11282         );
11283
11284         this.enableBubble(this.bubbleEvents);
11285
11286         
11287         var items = this.items;
11288         if(items){
11289             delete this.items;
11290             this.add(items);
11291         }
11292     },
11293
11294     
11295     initItems : function(){
11296         if(!this.items){
11297             this.items = new Ext.util.MixedCollection(false, this.getComponentId);
11298             this.getLayout(); 
11299         }
11300     },
11301
11302     
11303     setLayout : function(layout){
11304         if(this.layout && this.layout != layout){
11305             this.layout.setContainer(null);
11306         }
11307         this.initItems();
11308         this.layout = layout;
11309         layout.setContainer(this);
11310     },
11311
11312     afterRender: function(){
11313         this.layoutDone = false;
11314         if(!this.layout){
11315             this.layout = 'auto';
11316         }
11317         if(Ext.isObject(this.layout) && !this.layout.layout){
11318             this.layoutConfig = this.layout;
11319             this.layout = this.layoutConfig.type;
11320         }
11321         if(Ext.isString(this.layout)){
11322             this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig);
11323         }
11324         this.setLayout(this.layout);
11325
11326         
11327         
11328         Ext.Container.superclass.afterRender.call(this);
11329
11330         if(Ext.isDefined(this.activeItem)){
11331             var item = this.activeItem;
11332             delete this.activeItem;
11333             this.layout.setActiveItem(item);
11334         }
11335
11336         
11337         if(!this.ownerCt && !this.layoutDone){
11338             this.doLayout(false, true);
11339         }
11340
11341         if(this.monitorResize === true){
11342             Ext.EventManager.onWindowResize(this.doLayout, this, [false]);
11343         }
11344     },
11345
11346     
11347     getLayoutTarget : function(){
11348         return this.el;
11349     },
11350
11351     
11352     getComponentId : function(comp){
11353         return comp.getItemId();
11354     },
11355
11356     
11357     add : function(comp){
11358         this.initItems();
11359         var args = arguments.length > 1;
11360         if(args || Ext.isArray(comp)){
11361             var result = [];
11362             Ext.each(args ? arguments : comp, function(c){
11363                 result.push(this.add(c));
11364             }, this);
11365             return result;
11366         }
11367         var c = this.lookupComponent(this.applyDefaults(comp));
11368         var index = this.items.length;
11369         if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
11370             this.items.add(c);
11371             
11372             c.onAdded(this, index);
11373             this.onAdd(c);
11374             this.fireEvent('add', this, c, index);
11375         }
11376         return c;
11377     },
11378
11379     onAdd : function(c){
11380         
11381     },
11382     
11383     
11384     onAdded : function(container, pos) {
11385         
11386         this.ownerCt = container;
11387         this.initRef();
11388         
11389         this.cascade(function(c){
11390             c.initRef();
11391         });
11392         this.fireEvent('added', this, container, pos);
11393     },
11394
11395     
11396     insert : function(index, comp){
11397         this.initItems();
11398         var a = arguments, len = a.length;
11399         if(len > 2){
11400             var result = [];
11401             for(var i = len-1; i >= 1; --i) {
11402                 result.push(this.insert(index, a[i]));
11403             }
11404             return result;
11405         }
11406         var c = this.lookupComponent(this.applyDefaults(comp));
11407         index = Math.min(index, this.items.length);
11408         if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
11409             if(c.ownerCt == this){
11410                 this.items.remove(c);
11411             }
11412             this.items.insert(index, c);
11413             c.onAdded(this, index);
11414             this.onAdd(c);
11415             this.fireEvent('add', this, c, index);
11416         }
11417         return c;
11418     },
11419
11420     
11421     applyDefaults : function(c){
11422         var d = this.defaults;
11423         if(d){
11424             if(Ext.isFunction(d)){
11425                 d = d.call(this, c);
11426             }
11427             if(Ext.isString(c)){
11428                 c = Ext.ComponentMgr.get(c);
11429                 Ext.apply(c, d);
11430             }else if(!c.events){
11431                 Ext.applyIf(c, d);
11432             }else{
11433                 Ext.apply(c, d);
11434             }
11435         }
11436         return c;
11437     },
11438
11439     
11440     onBeforeAdd : function(item){
11441         if(item.ownerCt){
11442             item.ownerCt.remove(item, false);
11443         }
11444         if(this.hideBorders === true){
11445             item.border = (item.border === true);
11446         }
11447     },
11448
11449     
11450     remove : function(comp, autoDestroy){
11451         this.initItems();
11452         var c = this.getComponent(comp);
11453         if(c && this.fireEvent('beforeremove', this, c) !== false){
11454             this.doRemove(c, autoDestroy);
11455             this.fireEvent('remove', this, c);
11456         }
11457         return c;
11458     },
11459
11460     onRemove: function(c){
11461         
11462     },
11463
11464     
11465     doRemove: function(c, autoDestroy){
11466         if(this.layout && this.rendered){
11467             this.layout.onRemove(c);
11468         }
11469         this.items.remove(c);
11470         c.onRemoved();
11471         this.onRemove(c);
11472         if(autoDestroy === true || (autoDestroy !== false && this.autoDestroy)){
11473             c.destroy();
11474         }
11475     },
11476
11477     
11478     removeAll: function(autoDestroy){
11479         this.initItems();
11480         var item, rem = [], items = [];
11481         this.items.each(function(i){
11482             rem.push(i);
11483         });
11484         for (var i = 0, len = rem.length; i < len; ++i){
11485             item = rem[i];
11486             this.remove(item, autoDestroy);
11487             if(item.ownerCt !== this){
11488                 items.push(item);
11489             }
11490         }
11491         return items;
11492     },
11493
11494     
11495     getComponent : function(comp){
11496         if(Ext.isObject(comp)){
11497             comp = comp.getItemId();
11498         }
11499         return this.items.get(comp);
11500     },
11501
11502     
11503     lookupComponent : function(comp){
11504         if(Ext.isString(comp)){
11505             return Ext.ComponentMgr.get(comp);
11506         }else if(!comp.events){
11507             return this.createComponent(comp);
11508         }
11509         return comp;
11510     },
11511
11512     
11513     createComponent : function(config, defaultType){
11514         
11515         
11516         var c = config.render ? config : Ext.create(Ext.apply({
11517             ownerCt: this
11518         }, config), defaultType || this.defaultType);
11519         delete c.ownerCt;
11520         return c;
11521     },
11522
11523     
11524     canLayout: function() {
11525         var el = this.getLayoutTarget(), vs;
11526         return !!(el && (vs = el.dom.offsetWidth || el.dom.offsetHeight));
11527     },
11528
11529     
11530     doLayout: function(shallow, force){
11531         var rendered = this.rendered,
11532             forceLayout = force || this.forceLayout,
11533             cs, i, len, c;
11534
11535         this.layoutDone = true;
11536         if(!this.canLayout() || this.collapsed){
11537             this.deferLayout = this.deferLayout || !shallow;
11538             if(!forceLayout){
11539                 return;
11540             }
11541             shallow = shallow && !this.deferLayout;
11542         } else {
11543             delete this.deferLayout;
11544         }
11545
11546         cs = (shallow !== true && this.items) ? this.items.items : [];
11547
11548
11549         for(i = 0, len = cs.length; i < len; i++){
11550             if ((c = cs[i]).layout) {
11551                 c.suspendLayoutResize = true;
11552             }
11553         }
11554
11555
11556
11557         if(rendered && this.layout){
11558             this.layout.layout();
11559         }
11560
11561
11562         for(i = 0; i < len; i++){
11563             if((c = cs[i]).doLayout){
11564                 c.doLayout(false, forceLayout);
11565             }
11566         }
11567         if(rendered){
11568             this.onLayout(shallow, forceLayout);
11569         }
11570         
11571         this.hasLayout = true;
11572         delete this.forceLayout;
11573
11574
11575         for(i = 0; i < len; i++){
11576             if ((c = cs[i]).layout) {
11577                 delete c.suspendLayoutResize;
11578             }
11579         }
11580     },
11581
11582     
11583     onLayout : Ext.emptyFn,
11584
11585     onResize: function(adjWidth, adjHeight, rawWidth, rawHeight){
11586         Ext.Container.superclass.onResize.apply(this, arguments);
11587         if ((this.rendered && this.layout && this.layout.monitorResize) && !this.suspendLayoutResize) {
11588             this.layout.onResize();
11589         }
11590     },
11591
11592     
11593     hasLayoutPending: function(){
11594         
11595         var pending = this.layoutPending;
11596         this.ownerCt.bubble(function(c){
11597             return !(pending = c.layoutPending);
11598         });
11599         return pending;
11600
11601     },
11602
11603     onShow : function(){
11604         Ext.Container.superclass.onShow.call(this);
11605         if(Ext.isDefined(this.deferLayout)){
11606             this.doLayout(true);
11607         }
11608     },
11609
11610     
11611     getLayout : function(){
11612         if(!this.layout){
11613             var layout = new Ext.layout.ContainerLayout(this.layoutConfig);
11614             this.setLayout(layout);
11615         }
11616         return this.layout;
11617     },
11618
11619     
11620     beforeDestroy : function(){
11621         var c;
11622         if(this.items){
11623             while(c = this.items.first()){
11624                 this.doRemove(c, true);
11625             }
11626         }
11627         if(this.monitorResize){
11628             Ext.EventManager.removeResizeListener(this.doLayout, this);
11629         }
11630         Ext.destroy(this.layout);
11631         Ext.Container.superclass.beforeDestroy.call(this);
11632     },
11633
11634     
11635     bubble : function(fn, scope, args){
11636         var p = this;
11637         while(p){
11638             if(fn.apply(scope || p, args || [p]) === false){
11639                 break;
11640             }
11641             p = p.ownerCt;
11642         }
11643         return this;
11644     },
11645
11646     
11647     cascade : function(fn, scope, args){
11648         if(fn.apply(scope || this, args || [this]) !== false){
11649             if(this.items){
11650                 var cs = this.items.items;
11651                 for(var i = 0, len = cs.length; i < len; i++){
11652                     if(cs[i].cascade){
11653                         cs[i].cascade(fn, scope, args);
11654                     }else{
11655                         fn.apply(scope || cs[i], args || [cs[i]]);
11656                     }
11657                 }
11658             }
11659         }
11660         return this;
11661     },
11662
11663     
11664     findById : function(id){
11665         var m, ct = this;
11666         this.cascade(function(c){
11667             if(ct != c && c.id === id){
11668                 m = c;
11669                 return false;
11670             }
11671         });
11672         return m || null;
11673     },
11674
11675     
11676     findByType : function(xtype, shallow){
11677         return this.findBy(function(c){
11678             return c.isXType(xtype, shallow);
11679         });
11680     },
11681
11682     
11683     find : function(prop, value){
11684         return this.findBy(function(c){
11685             return c[prop] === value;
11686         });
11687     },
11688
11689     
11690     findBy : function(fn, scope){
11691         var m = [], ct = this;
11692         this.cascade(function(c){
11693             if(ct != c && fn.call(scope || c, c, ct) === true){
11694                 m.push(c);
11695             }
11696         });
11697         return m;
11698     },
11699
11700     
11701     get : function(key){
11702         return this.items.get(key);
11703     }
11704 });
11705
11706 Ext.Container.LAYOUTS = {};
11707 Ext.reg('container', Ext.Container);
11708
11709 Ext.layout.ContainerLayout = Ext.extend(Object, {
11710     
11711     
11712
11713     
11714
11715     
11716     monitorResize:false,
11717     
11718     activeItem : null,
11719
11720     constructor : function(config){
11721         Ext.apply(this, config);
11722     },
11723
11724     
11725     layout : function(){
11726         var target = this.container.getLayoutTarget();
11727         if(!(this.hasLayout || Ext.isEmpty(this.targetCls))){
11728             target.addClass(this.targetCls)
11729         }
11730         this.onLayout(this.container, target);
11731         this.container.fireEvent('afterlayout', this.container, this);
11732         this.hasLayout = true;
11733     },
11734
11735     
11736     onLayout : function(ct, target){
11737         this.renderAll(ct, target);
11738     },
11739
11740     
11741     isValidParent : function(c, target){
11742         return target && c.getPositionEl().dom.parentNode == (target.dom || target);
11743     },
11744
11745     
11746     renderAll : function(ct, target){
11747         var items = ct.items.items;
11748         for(var i = 0, len = items.length; i < len; i++) {
11749             var c = items[i];
11750             if(c && (!c.rendered || !this.isValidParent(c, target))){
11751                 this.renderItem(c, i, target);
11752             }
11753         }
11754     },
11755
11756     
11757     renderItem : function(c, position, target){
11758         if(c && !c.rendered){
11759             c.render(target, position);
11760             this.configureItem(c, position);
11761         }else if(c && !this.isValidParent(c, target)){
11762             if(Ext.isNumber(position)){
11763                 position = target.dom.childNodes[position];
11764             }
11765             target.dom.insertBefore(c.getPositionEl().dom, position || null);
11766             c.container = target;
11767             this.configureItem(c, position);
11768         }
11769     },
11770
11771     
11772     configureItem: function(c, position){
11773         if(this.extraCls){
11774             var t = c.getPositionEl ? c.getPositionEl() : c;
11775             t.addClass(this.extraCls);
11776         }
11777         
11778         if(c.doLayout && this.forceLayout){
11779             c.doLayout(false, true);
11780         }
11781         if (this.renderHidden && c != this.activeItem) {
11782             c.hide();
11783         }
11784     },
11785
11786     onRemove: function(c){
11787          if(this.activeItem == c){
11788             delete this.activeItem;
11789          }
11790          if(c.rendered && this.extraCls){
11791             var t = c.getPositionEl ? c.getPositionEl() : c;
11792             t.removeClass(this.extraCls);
11793         }
11794     },
11795
11796     
11797     onResize: function(){
11798         var ct = this.container,
11799             b = ct.bufferResize;
11800
11801         if (ct.collapsed){
11802             return;
11803         }
11804
11805         
11806         
11807         if (b && ct.ownerCt) {
11808             
11809             
11810             
11811             if (!ct.hasLayoutPending()){
11812                 if(!this.resizeTask){
11813                     this.resizeTask = new Ext.util.DelayedTask(this.runLayout, this);
11814                     this.resizeBuffer = Ext.isNumber(b) ? b : 50;
11815                 }
11816                 ct.layoutPending = true;
11817                 this.resizeTask.delay(this.resizeBuffer);
11818             }
11819         }else{
11820             ct.doLayout(false, this.forceLayout);
11821         }
11822     },
11823
11824     
11825     runLayout: function(){
11826         var ct = this.container;
11827         ct.doLayout();
11828         delete ct.layoutPending;
11829     },
11830
11831     
11832     setContainer : function(ct){
11833         
11834         
11835         this.container = ct;
11836     },
11837
11838     
11839     parseMargins : function(v){
11840         if(Ext.isNumber(v)){
11841             v = v.toString();
11842         }
11843         var ms = v.split(' ');
11844         var len = ms.length;
11845         if(len == 1){
11846             ms[1] = ms[0];
11847             ms[2] = ms[0];
11848             ms[3] = ms[0];
11849         }
11850         if(len == 2){
11851             ms[2] = ms[0];
11852             ms[3] = ms[1];
11853         }
11854         if(len == 3){
11855             ms[3] = ms[1];
11856         }
11857         return {
11858             top:parseInt(ms[0], 10) || 0,
11859             right:parseInt(ms[1], 10) || 0,
11860             bottom:parseInt(ms[2], 10) || 0,
11861             left:parseInt(ms[3], 10) || 0
11862         };
11863     },
11864
11865     
11866     fieldTpl: (function() {
11867         var t = new Ext.Template(
11868             '<div class="x-form-item {itemCls}" tabIndex="-1">',
11869                 '<label for="{id}" style="{labelStyle}" class="x-form-item-label">{label}{labelSeparator}</label>',
11870                 '<div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">',
11871                 '</div><div class="{clearCls}"></div>',
11872             '</div>'
11873         );
11874         t.disableFormats = true;
11875         return t.compile();
11876     })(),
11877
11878     
11879     destroy : function(){
11880         if(!Ext.isEmpty(this.targetCls)){
11881             var target = this.container.getLayoutTarget();
11882             if(target){
11883                 target.removeClass(this.targetCls);
11884             }
11885         }
11886     }
11887 });
11888 Ext.Container.LAYOUTS['auto'] = Ext.layout.ContainerLayout;
11889
11890 Ext.layout.FitLayout = Ext.extend(Ext.layout.ContainerLayout, {
11891     
11892     monitorResize:true,
11893
11894     
11895     onLayout : function(ct, target){
11896         Ext.layout.FitLayout.superclass.onLayout.call(this, ct, target);
11897         if(!this.container.collapsed){
11898             this.setItemSize(this.activeItem || ct.items.itemAt(0), target.getViewSize(true));
11899         }
11900     },
11901
11902     
11903     setItemSize : function(item, size){
11904         if(item && size.height > 0){ 
11905             item.setSize(size);
11906         }
11907     }
11908 });
11909 Ext.Container.LAYOUTS['fit'] = Ext.layout.FitLayout;
11910 Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {
11911     
11912     deferredRender : false,
11913     
11914     
11915     layoutOnCardChange : false,
11916
11917     
11918     
11919     renderHidden : true,
11920     
11921     constructor: function(config){
11922         Ext.layout.CardLayout.superclass.constructor.call(this, config);
11923       
11924     },
11925
11926     
11927     setActiveItem : function(item){
11928         var ai = this.activeItem;
11929         item = this.container.getComponent(item);
11930         if(ai != item){
11931             if(ai){
11932                 ai.hide();
11933                 ai.fireEvent('deactivate', ai);
11934             }
11935             var layout = item.doLayout && (this.layoutOnCardChange || !item.rendered);
11936             this.activeItem = item;
11937             if(item){
11938                 item.show();
11939             }
11940             this.layout();
11941             if(item && layout){
11942                 item.doLayout();
11943             }
11944             item.fireEvent('activate', item);
11945         }
11946     },
11947
11948     
11949     renderAll : function(ct, target){
11950         if(this.deferredRender){
11951             this.renderItem(this.activeItem, undefined, target);
11952         }else{
11953             Ext.layout.CardLayout.superclass.renderAll.call(this, ct, target);
11954         }
11955     }
11956 });
11957 Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;
11958 Ext.layout.AnchorLayout = Ext.extend(Ext.layout.ContainerLayout, {
11959     
11960
11961     
11962     monitorResize:true,
11963
11964     
11965     
11966     getAnchorViewSize : function(ct, target){
11967         return target.dom == document.body ?
11968                    target.getViewSize(true) : target.getStyleSize();
11969     },
11970
11971     
11972     onLayout : function(ct, target){
11973         Ext.layout.AnchorLayout.superclass.onLayout.call(this, ct, target);
11974
11975         var size = target.getViewSize(true);
11976
11977         var w = size.width, h = size.height;
11978
11979         if(w < 20 && h < 20){
11980             return;
11981         }
11982
11983         
11984         var aw, ah;
11985         if(ct.anchorSize){
11986             if(typeof ct.anchorSize == 'number'){
11987                 aw = ct.anchorSize;
11988             }else{
11989                 aw = ct.anchorSize.width;
11990                 ah = ct.anchorSize.height;
11991             }
11992         }else{
11993             aw = ct.initialConfig.width;
11994             ah = ct.initialConfig.height;
11995         }
11996
11997         var cs = ct.items.items, len = cs.length, i, c, a, cw, ch, el, vs;
11998         for(i = 0; i < len; i++){
11999             c = cs[i];
12000             el = c.getPositionEl();
12001             if(c.anchor){
12002                 a = c.anchorSpec;
12003                 if(!a){ 
12004                     vs = c.anchor.split(' ');
12005                     c.anchorSpec = a = {
12006                         right: this.parseAnchor(vs[0], c.initialConfig.width, aw),
12007                         bottom: this.parseAnchor(vs[1], c.initialConfig.height, ah)
12008                     };
12009                 }
12010                 cw = a.right ? this.adjustWidthAnchor(a.right(w) - el.getMargins('lr'), c) : undefined;
12011                 ch = a.bottom ? this.adjustHeightAnchor(a.bottom(h) - el.getMargins('tb'), c) : undefined;
12012
12013                 if(cw || ch){
12014                     c.setSize(cw || undefined, ch || undefined);
12015                 }
12016             }
12017         }
12018     },
12019
12020     
12021     parseAnchor : function(a, start, cstart){
12022         if(a && a != 'none'){
12023             var last;
12024             if(/^(r|right|b|bottom)$/i.test(a)){   
12025                 var diff = cstart - start;
12026                 return function(v){
12027                     if(v !== last){
12028                         last = v;
12029                         return v - diff;
12030                     }
12031                 }
12032             }else if(a.indexOf('%') != -1){
12033                 var ratio = parseFloat(a.replace('%', ''))*.01;   
12034                 return function(v){
12035                     if(v !== last){
12036                         last = v;
12037                         return Math.floor(v*ratio);
12038                     }
12039                 }
12040             }else{
12041                 a = parseInt(a, 10);
12042                 if(!isNaN(a)){                            
12043                     return function(v){
12044                         if(v !== last){
12045                             last = v;
12046                             return v + a;
12047                         }
12048                     }
12049                 }
12050             }
12051         }
12052         return false;
12053     },
12054
12055     
12056     adjustWidthAnchor : function(value, comp){
12057         return value;
12058     },
12059
12060     
12061     adjustHeightAnchor : function(value, comp){
12062         return value;
12063     }
12064
12065     
12066 });
12067 Ext.Container.LAYOUTS['anchor'] = Ext.layout.AnchorLayout;
12068
12069 Ext.layout.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {
12070     
12071     monitorResize:true,
12072
12073     extraCls: 'x-column',
12074
12075     scrollOffset : 0,
12076
12077     
12078
12079     targetCls: 'x-column-layout-ct',
12080
12081     isValidParent : function(c, target){
12082         return c.getPositionEl().dom.parentNode == this.innerCt.dom;
12083     },
12084
12085     
12086     onLayout : function(ct, target){
12087         var cs = ct.items.items, len = cs.length, c, i;
12088
12089         if(!this.innerCt){
12090             
12091             
12092             this.innerCt = target.createChild({cls:'x-column-inner'});
12093             this.innerCt.createChild({cls:'x-clear'});
12094         }
12095         this.renderAll(ct, this.innerCt);
12096
12097         var size = target.getViewSize(true);
12098
12099         if(size.width < 1 && size.height < 1){ 
12100             return;
12101         }
12102
12103         var w = size.width - this.scrollOffset,
12104             h = size.height,
12105             pw = w;
12106
12107         this.innerCt.setWidth(w);
12108
12109         
12110         
12111
12112         for(i = 0; i < len; i++){
12113             c = cs[i];
12114             if(!c.columnWidth){
12115                 pw -= (c.getSize().width + c.getPositionEl().getMargins('lr'));
12116             }
12117         }
12118
12119         pw = pw < 0 ? 0 : pw;
12120
12121         for(i = 0; i < len; i++){
12122             c = cs[i];
12123             if(c.columnWidth){
12124                 c.setSize(Math.floor(c.columnWidth * pw) - c.getPositionEl().getMargins('lr'));
12125             }
12126         }
12127     }
12128
12129     
12130 });
12131
12132 Ext.Container.LAYOUTS['column'] = Ext.layout.ColumnLayout;
12133 Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {
12134     
12135     monitorResize:true,
12136     
12137     rendered : false,
12138
12139     targetCls: 'x-border-layout-ct',
12140
12141     
12142     onLayout : function(ct, target){
12143         var collapsed;
12144         if(!this.rendered){
12145             var items = ct.items.items;
12146             collapsed = [];
12147             for(var i = 0, len = items.length; i < len; i++) {
12148                 var c = items[i];
12149                 var pos = c.region;
12150                 if(c.collapsed){
12151                     collapsed.push(c);
12152                 }
12153                 c.collapsed = false;
12154                 if(!c.rendered){
12155                     c.render(target, i);
12156                     c.getPositionEl().addClass('x-border-panel');
12157                 }
12158                 this[pos] = pos != 'center' && c.split ?
12159                     new Ext.layout.BorderLayout.SplitRegion(this, c.initialConfig, pos) :
12160                     new Ext.layout.BorderLayout.Region(this, c.initialConfig, pos);
12161                 this[pos].render(target, c);
12162             }
12163             this.rendered = true;
12164         }
12165
12166         var size = target.getViewSize(false);
12167         if(size.width < 20 || size.height < 20){ 
12168             if(collapsed){
12169                 this.restoreCollapsed = collapsed;
12170             }
12171             return;
12172         }else if(this.restoreCollapsed){
12173             collapsed = this.restoreCollapsed;
12174             delete this.restoreCollapsed;
12175         }
12176
12177         var w = size.width, h = size.height;
12178         var centerW = w, centerH = h, centerY = 0, centerX = 0;
12179
12180         var n = this.north, s = this.south, west = this.west, e = this.east, c = this.center;
12181         if(!c && Ext.layout.BorderLayout.WARN !== false){
12182             throw 'No center region defined in BorderLayout ' + ct.id;
12183         }
12184
12185         if(n && n.isVisible()){
12186             var b = n.getSize();
12187             var m = n.getMargins();
12188             b.width = w - (m.left+m.right);
12189             b.x = m.left;
12190             b.y = m.top;
12191             centerY = b.height + b.y + m.bottom;
12192             centerH -= centerY;
12193             n.applyLayout(b);
12194         }
12195         if(s && s.isVisible()){
12196             var b = s.getSize();
12197             var m = s.getMargins();
12198             b.width = w - (m.left+m.right);
12199             b.x = m.left;
12200             var totalHeight = (b.height + m.top + m.bottom);
12201             b.y = h - totalHeight + m.top;
12202             centerH -= totalHeight;
12203             s.applyLayout(b);
12204         }
12205         if(west && west.isVisible()){
12206             var b = west.getSize();
12207             var m = west.getMargins();
12208             b.height = centerH - (m.top+m.bottom);
12209             b.x = m.left;
12210             b.y = centerY + m.top;
12211             var totalWidth = (b.width + m.left + m.right);
12212             centerX += totalWidth;
12213             centerW -= totalWidth;
12214             west.applyLayout(b);
12215         }
12216         if(e && e.isVisible()){
12217             var b = e.getSize();
12218             var m = e.getMargins();
12219             b.height = centerH - (m.top+m.bottom);
12220             var totalWidth = (b.width + m.left + m.right);
12221             b.x = w - totalWidth + m.left;
12222             b.y = centerY + m.top;
12223             centerW -= totalWidth;
12224             e.applyLayout(b);
12225         }
12226         if(c){
12227             var m = c.getMargins();
12228             var centerBox = {
12229                 x: centerX + m.left,
12230                 y: centerY + m.top,
12231                 width: centerW - (m.left+m.right),
12232                 height: centerH - (m.top+m.bottom)
12233             };
12234             c.applyLayout(centerBox);
12235         }
12236         if(collapsed){
12237             for(var i = 0, len = collapsed.length; i < len; i++){
12238                 collapsed[i].collapse(false);
12239             }
12240         }
12241         if(Ext.isIE && Ext.isStrict){ 
12242             target.repaint();
12243         }
12244     },
12245
12246     destroy: function() {
12247         var r = ['north', 'south', 'east', 'west'];
12248         for (var i = 0; i < r.length; i++) {
12249             var region = this[r[i]];
12250             if(region){
12251                 if(region.destroy){
12252                     region.destroy();
12253                 }else if (region.split){
12254                     region.split.destroy(true);
12255                 }
12256             }
12257         }
12258         Ext.layout.BorderLayout.superclass.destroy.call(this);
12259     }
12260
12261     
12262 });
12263
12264
12265 Ext.layout.BorderLayout.Region = function(layout, config, pos){
12266     Ext.apply(this, config);
12267     this.layout = layout;
12268     this.position = pos;
12269     this.state = {};
12270     if(typeof this.margins == 'string'){
12271         this.margins = this.layout.parseMargins(this.margins);
12272     }
12273     this.margins = Ext.applyIf(this.margins || {}, this.defaultMargins);
12274     if(this.collapsible){
12275         if(typeof this.cmargins == 'string'){
12276             this.cmargins = this.layout.parseMargins(this.cmargins);
12277         }
12278         if(this.collapseMode == 'mini' && !this.cmargins){
12279             this.cmargins = {left:0,top:0,right:0,bottom:0};
12280         }else{
12281             this.cmargins = Ext.applyIf(this.cmargins || {},
12282                 pos == 'north' || pos == 'south' ? this.defaultNSCMargins : this.defaultEWCMargins);
12283         }
12284     }
12285 };
12286
12287 Ext.layout.BorderLayout.Region.prototype = {
12288     
12289     
12290     
12291     
12292     
12293     
12294     collapsible : false,
12295     
12296     split:false,
12297     
12298     floatable: true,
12299     
12300     minWidth:50,
12301     
12302     minHeight:50,
12303
12304     
12305     defaultMargins : {left:0,top:0,right:0,bottom:0},
12306     
12307     defaultNSCMargins : {left:5,top:5,right:5,bottom:5},
12308     
12309     defaultEWCMargins : {left:5,top:0,right:5,bottom:0},
12310     floatingZIndex: 100,
12311
12312     
12313     isCollapsed : false,
12314
12315     
12316     
12317     
12318
12319     
12320     render : function(ct, p){
12321         this.panel = p;
12322         p.el.enableDisplayMode();
12323         this.targetEl = ct;
12324         this.el = p.el;
12325
12326         var gs = p.getState, ps = this.position;
12327         p.getState = function(){
12328             return Ext.apply(gs.call(p) || {}, this.state);
12329         }.createDelegate(this);
12330
12331         if(ps != 'center'){
12332             p.allowQueuedExpand = false;
12333             p.on({
12334                 beforecollapse: this.beforeCollapse,
12335                 collapse: this.onCollapse,
12336                 beforeexpand: this.beforeExpand,
12337                 expand: this.onExpand,
12338                 hide: this.onHide,
12339                 show: this.onShow,
12340                 scope: this
12341             });
12342             if(this.collapsible || this.floatable){
12343                 p.collapseEl = 'el';
12344                 p.slideAnchor = this.getSlideAnchor();
12345             }
12346             if(p.tools && p.tools.toggle){
12347                 p.tools.toggle.addClass('x-tool-collapse-'+ps);
12348                 p.tools.toggle.addClassOnOver('x-tool-collapse-'+ps+'-over');
12349             }
12350         }
12351     },
12352
12353     
12354     getCollapsedEl : function(){
12355         if(!this.collapsedEl){
12356             if(!this.toolTemplate){
12357                 var tt = new Ext.Template(
12358                      '<div class="x-tool x-tool-{id}">&#160;</div>'
12359                 );
12360                 tt.disableFormats = true;
12361                 tt.compile();
12362                 Ext.layout.BorderLayout.Region.prototype.toolTemplate = tt;
12363             }
12364             this.collapsedEl = this.targetEl.createChild({
12365                 cls: "x-layout-collapsed x-layout-collapsed-"+this.position,
12366                 id: this.panel.id + '-xcollapsed'
12367             });
12368             this.collapsedEl.enableDisplayMode('block');
12369
12370             if(this.collapseMode == 'mini'){
12371                 this.collapsedEl.addClass('x-layout-cmini-'+this.position);
12372                 this.miniCollapsedEl = this.collapsedEl.createChild({
12373                     cls: "x-layout-mini x-layout-mini-"+this.position, html: "&#160;"
12374                 });
12375                 this.miniCollapsedEl.addClassOnOver('x-layout-mini-over');
12376                 this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
12377                 this.collapsedEl.on('click', this.onExpandClick, this, {stopEvent:true});
12378             }else {
12379                 if(this.collapsible !== false && !this.hideCollapseTool) {
12380                     var t = this.toolTemplate.append(
12381                             this.collapsedEl.dom,
12382                             {id:'expand-'+this.position}, true);
12383                     t.addClassOnOver('x-tool-expand-'+this.position+'-over');
12384                     t.on('click', this.onExpandClick, this, {stopEvent:true});
12385                 }
12386                 if(this.floatable !== false || this.titleCollapse){
12387                    this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
12388                    this.collapsedEl.on("click", this[this.floatable ? 'collapseClick' : 'onExpandClick'], this);
12389                 }
12390             }
12391         }
12392         return this.collapsedEl;
12393     },
12394
12395     
12396     onExpandClick : function(e){
12397         if(this.isSlid){
12398             this.panel.expand(false);
12399         }else{
12400             this.panel.expand();
12401         }
12402     },
12403
12404     
12405     onCollapseClick : function(e){
12406         this.panel.collapse();
12407     },
12408
12409     
12410     beforeCollapse : function(p, animate){
12411         this.lastAnim = animate;
12412         if(this.splitEl){
12413             this.splitEl.hide();
12414         }
12415         this.getCollapsedEl().show();
12416         var el = this.panel.getEl();
12417         this.originalZIndex = el.getStyle('z-index');
12418         el.setStyle('z-index', 100);
12419         this.isCollapsed = true;
12420         this.layout.layout();
12421     },
12422
12423     
12424     onCollapse : function(animate){
12425         this.panel.el.setStyle('z-index', 1);
12426         if(this.lastAnim === false || this.panel.animCollapse === false){
12427             this.getCollapsedEl().dom.style.visibility = 'visible';
12428         }else{
12429             this.getCollapsedEl().slideIn(this.panel.slideAnchor, {duration:.2});
12430         }
12431         this.state.collapsed = true;
12432         this.panel.saveState();
12433     },
12434
12435     
12436     beforeExpand : function(animate){
12437         if(this.isSlid){
12438             this.afterSlideIn();
12439         }
12440         var c = this.getCollapsedEl();
12441         this.el.show();
12442         if(this.position == 'east' || this.position == 'west'){
12443             this.panel.setSize(undefined, c.getHeight());
12444         }else{
12445             this.panel.setSize(c.getWidth(), undefined);
12446         }
12447         c.hide();
12448         c.dom.style.visibility = 'hidden';
12449         this.panel.el.setStyle('z-index', this.floatingZIndex);
12450     },
12451
12452     
12453     onExpand : function(){
12454         this.isCollapsed = false;
12455         if(this.splitEl){
12456             this.splitEl.show();
12457         }
12458         this.layout.layout();
12459         this.panel.el.setStyle('z-index', this.originalZIndex);
12460         this.state.collapsed = false;
12461         this.panel.saveState();
12462     },
12463
12464     
12465     collapseClick : function(e){
12466         if(this.isSlid){
12467            e.stopPropagation();
12468            this.slideIn();
12469         }else{
12470            e.stopPropagation();
12471            this.slideOut();
12472         }
12473     },
12474
12475     
12476     onHide : function(){
12477         if(this.isCollapsed){
12478             this.getCollapsedEl().hide();
12479         }else if(this.splitEl){
12480             this.splitEl.hide();
12481         }
12482     },
12483
12484     
12485     onShow : function(){
12486         if(this.isCollapsed){
12487             this.getCollapsedEl().show();
12488         }else if(this.splitEl){
12489             this.splitEl.show();
12490         }
12491     },
12492
12493     
12494     isVisible : function(){
12495         return !this.panel.hidden;
12496     },
12497
12498     
12499     getMargins : function(){
12500         return this.isCollapsed && this.cmargins ? this.cmargins : this.margins;
12501     },
12502
12503     
12504     getSize : function(){
12505         return this.isCollapsed ? this.getCollapsedEl().getSize() : this.panel.getSize();
12506     },
12507
12508     
12509     setPanel : function(panel){
12510         this.panel = panel;
12511     },
12512
12513     
12514     getMinWidth: function(){
12515         return this.minWidth;
12516     },
12517
12518     
12519     getMinHeight: function(){
12520         return this.minHeight;
12521     },
12522
12523     
12524     applyLayoutCollapsed : function(box){
12525         var ce = this.getCollapsedEl();
12526         ce.setLeftTop(box.x, box.y);
12527         ce.setSize(box.width, box.height);
12528     },
12529
12530     
12531     applyLayout : function(box){
12532         if(this.isCollapsed){
12533             this.applyLayoutCollapsed(box);
12534         }else{
12535             this.panel.setPosition(box.x, box.y);
12536             this.panel.setSize(box.width, box.height);
12537         }
12538     },
12539
12540     
12541     beforeSlide: function(){
12542         this.panel.beforeEffect();
12543     },
12544
12545     
12546     afterSlide : function(){
12547         this.panel.afterEffect();
12548     },
12549
12550     
12551     initAutoHide : function(){
12552         if(this.autoHide !== false){
12553             if(!this.autoHideHd){
12554                 var st = new Ext.util.DelayedTask(this.slideIn, this);
12555                 this.autoHideHd = {
12556                     "mouseout": function(e){
12557                         if(!e.within(this.el, true)){
12558                             st.delay(500);
12559                         }
12560                     },
12561                     "mouseover" : function(e){
12562                         st.cancel();
12563                     },
12564                     scope : this
12565                 };
12566             }
12567             this.el.on(this.autoHideHd);
12568             this.collapsedEl.on(this.autoHideHd);
12569         }
12570     },
12571
12572     
12573     clearAutoHide : function(){
12574         if(this.autoHide !== false){
12575             this.el.un("mouseout", this.autoHideHd.mouseout);
12576             this.el.un("mouseover", this.autoHideHd.mouseover);
12577             this.collapsedEl.un("mouseout", this.autoHideHd.mouseout);
12578             this.collapsedEl.un("mouseover", this.autoHideHd.mouseover);
12579         }
12580     },
12581
12582     
12583     clearMonitor : function(){
12584         Ext.getDoc().un("click", this.slideInIf, this);
12585     },
12586
12587     
12588     slideOut : function(){
12589         if(this.isSlid || this.el.hasActiveFx()){
12590             return;
12591         }
12592         this.isSlid = true;
12593         var ts = this.panel.tools;
12594         if(ts && ts.toggle){
12595             ts.toggle.hide();
12596         }
12597         this.el.show();
12598         if(this.position == 'east' || this.position == 'west'){
12599             this.panel.setSize(undefined, this.collapsedEl.getHeight());
12600         }else{
12601             this.panel.setSize(this.collapsedEl.getWidth(), undefined);
12602         }
12603         this.restoreLT = [this.el.dom.style.left, this.el.dom.style.top];
12604         this.el.alignTo(this.collapsedEl, this.getCollapseAnchor());
12605         this.el.setStyle("z-index", this.floatingZIndex+2);
12606         this.panel.el.replaceClass('x-panel-collapsed', 'x-panel-floating');
12607         if(this.animFloat !== false){
12608             this.beforeSlide();
12609             this.el.slideIn(this.getSlideAnchor(), {
12610                 callback: function(){
12611                     this.afterSlide();
12612                     this.initAutoHide();
12613                     Ext.getDoc().on("click", this.slideInIf, this);
12614                 },
12615                 scope: this,
12616                 block: true
12617             });
12618         }else{
12619             this.initAutoHide();
12620              Ext.getDoc().on("click", this.slideInIf, this);
12621         }
12622     },
12623
12624     
12625     afterSlideIn : function(){
12626         this.clearAutoHide();
12627         this.isSlid = false;
12628         this.clearMonitor();
12629         this.el.setStyle("z-index", "");
12630         this.panel.el.replaceClass('x-panel-floating', 'x-panel-collapsed');
12631         this.el.dom.style.left = this.restoreLT[0];
12632         this.el.dom.style.top = this.restoreLT[1];
12633
12634         var ts = this.panel.tools;
12635         if(ts && ts.toggle){
12636             ts.toggle.show();
12637         }
12638     },
12639
12640     
12641     slideIn : function(cb){
12642         if(!this.isSlid || this.el.hasActiveFx()){
12643             Ext.callback(cb);
12644             return;
12645         }
12646         this.isSlid = false;
12647         if(this.animFloat !== false){
12648             this.beforeSlide();
12649             this.el.slideOut(this.getSlideAnchor(), {
12650                 callback: function(){
12651                     this.el.hide();
12652                     this.afterSlide();
12653                     this.afterSlideIn();
12654                     Ext.callback(cb);
12655                 },
12656                 scope: this,
12657                 block: true
12658             });
12659         }else{
12660             this.el.hide();
12661             this.afterSlideIn();
12662         }
12663     },
12664
12665     
12666     slideInIf : function(e){
12667         if(!e.within(this.el)){
12668             this.slideIn();
12669         }
12670     },
12671
12672     
12673     anchors : {
12674         "west" : "left",
12675         "east" : "right",
12676         "north" : "top",
12677         "south" : "bottom"
12678     },
12679
12680     
12681     sanchors : {
12682         "west" : "l",
12683         "east" : "r",
12684         "north" : "t",
12685         "south" : "b"
12686     },
12687
12688     
12689     canchors : {
12690         "west" : "tl-tr",
12691         "east" : "tr-tl",
12692         "north" : "tl-bl",
12693         "south" : "bl-tl"
12694     },
12695
12696     
12697     getAnchor : function(){
12698         return this.anchors[this.position];
12699     },
12700
12701     
12702     getCollapseAnchor : function(){
12703         return this.canchors[this.position];
12704     },
12705
12706     
12707     getSlideAnchor : function(){
12708         return this.sanchors[this.position];
12709     },
12710
12711     
12712     getAlignAdj : function(){
12713         var cm = this.cmargins;
12714         switch(this.position){
12715             case "west":
12716                 return [0, 0];
12717             break;
12718             case "east":
12719                 return [0, 0];
12720             break;
12721             case "north":
12722                 return [0, 0];
12723             break;
12724             case "south":
12725                 return [0, 0];
12726             break;
12727         }
12728     },
12729
12730     
12731     getExpandAdj : function(){
12732         var c = this.collapsedEl, cm = this.cmargins;
12733         switch(this.position){
12734             case "west":
12735                 return [-(cm.right+c.getWidth()+cm.left), 0];
12736             break;
12737             case "east":
12738                 return [cm.right+c.getWidth()+cm.left, 0];
12739             break;
12740             case "north":
12741                 return [0, -(cm.top+cm.bottom+c.getHeight())];
12742             break;
12743             case "south":
12744                 return [0, cm.top+cm.bottom+c.getHeight()];
12745             break;
12746         }
12747     },
12748
12749     destroy : function(){
12750         Ext.destroy(this.miniCollapsedEl, this.collapsedEl);
12751     }
12752 };
12753
12754
12755 Ext.layout.BorderLayout.SplitRegion = function(layout, config, pos){
12756     Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this, layout, config, pos);
12757     
12758     this.applyLayout = this.applyFns[pos];
12759 };
12760
12761 Ext.extend(Ext.layout.BorderLayout.SplitRegion, Ext.layout.BorderLayout.Region, {
12762     
12763     
12764     splitTip : "Drag to resize.",
12765     
12766     collapsibleSplitTip : "Drag to resize. Double click to hide.",
12767     
12768     useSplitTips : false,
12769
12770     
12771     splitSettings : {
12772         north : {
12773             orientation: Ext.SplitBar.VERTICAL,
12774             placement: Ext.SplitBar.TOP,
12775             maxFn : 'getVMaxSize',
12776             minProp: 'minHeight',
12777             maxProp: 'maxHeight'
12778         },
12779         south : {
12780             orientation: Ext.SplitBar.VERTICAL,
12781             placement: Ext.SplitBar.BOTTOM,
12782             maxFn : 'getVMaxSize',
12783             minProp: 'minHeight',
12784             maxProp: 'maxHeight'
12785         },
12786         east : {
12787             orientation: Ext.SplitBar.HORIZONTAL,
12788             placement: Ext.SplitBar.RIGHT,
12789             maxFn : 'getHMaxSize',
12790             minProp: 'minWidth',
12791             maxProp: 'maxWidth'
12792         },
12793         west : {
12794             orientation: Ext.SplitBar.HORIZONTAL,
12795             placement: Ext.SplitBar.LEFT,
12796             maxFn : 'getHMaxSize',
12797             minProp: 'minWidth',
12798             maxProp: 'maxWidth'
12799         }
12800     },
12801
12802     
12803     applyFns : {
12804         west : function(box){
12805             if(this.isCollapsed){
12806                 return this.applyLayoutCollapsed(box);
12807             }
12808             var sd = this.splitEl.dom, s = sd.style;
12809             this.panel.setPosition(box.x, box.y);
12810             var sw = sd.offsetWidth;
12811             s.left = (box.x+box.width-sw)+'px';
12812             s.top = (box.y)+'px';
12813             s.height = Math.max(0, box.height)+'px';
12814             this.panel.setSize(box.width-sw, box.height);
12815         },
12816         east : function(box){
12817             if(this.isCollapsed){
12818                 return this.applyLayoutCollapsed(box);
12819             }
12820             var sd = this.splitEl.dom, s = sd.style;
12821             var sw = sd.offsetWidth;
12822             this.panel.setPosition(box.x+sw, box.y);
12823             s.left = (box.x)+'px';
12824             s.top = (box.y)+'px';
12825             s.height = Math.max(0, box.height)+'px';
12826             this.panel.setSize(box.width-sw, box.height);
12827         },
12828         north : function(box){
12829             if(this.isCollapsed){
12830                 return this.applyLayoutCollapsed(box);
12831             }
12832             var sd = this.splitEl.dom, s = sd.style;
12833             var sh = sd.offsetHeight;
12834             this.panel.setPosition(box.x, box.y);
12835             s.left = (box.x)+'px';
12836             s.top = (box.y+box.height-sh)+'px';
12837             s.width = Math.max(0, box.width)+'px';
12838             this.panel.setSize(box.width, box.height-sh);
12839         },
12840         south : function(box){
12841             if(this.isCollapsed){
12842                 return this.applyLayoutCollapsed(box);
12843             }
12844             var sd = this.splitEl.dom, s = sd.style;
12845             var sh = sd.offsetHeight;
12846             this.panel.setPosition(box.x, box.y+sh);
12847             s.left = (box.x)+'px';
12848             s.top = (box.y)+'px';
12849             s.width = Math.max(0, box.width)+'px';
12850             this.panel.setSize(box.width, box.height-sh);
12851         }
12852     },
12853
12854     
12855     render : function(ct, p){
12856         Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this, ct, p);
12857
12858         var ps = this.position;
12859
12860         this.splitEl = ct.createChild({
12861             cls: "x-layout-split x-layout-split-"+ps, html: "&#160;",
12862             id: this.panel.id + '-xsplit'
12863         });
12864
12865         if(this.collapseMode == 'mini'){
12866             this.miniSplitEl = this.splitEl.createChild({
12867                 cls: "x-layout-mini x-layout-mini-"+ps, html: "&#160;"
12868             });
12869             this.miniSplitEl.addClassOnOver('x-layout-mini-over');
12870             this.miniSplitEl.on('click', this.onCollapseClick, this, {stopEvent:true});
12871         }
12872
12873         var s = this.splitSettings[ps];
12874
12875         this.split = new Ext.SplitBar(this.splitEl.dom, p.el, s.orientation);
12876         this.split.tickSize = this.tickSize;
12877         this.split.placement = s.placement;
12878         this.split.getMaximumSize = this[s.maxFn].createDelegate(this);
12879         this.split.minSize = this.minSize || this[s.minProp];
12880         this.split.on("beforeapply", this.onSplitMove, this);
12881         this.split.useShim = this.useShim === true;
12882         this.maxSize = this.maxSize || this[s.maxProp];
12883
12884         if(p.hidden){
12885             this.splitEl.hide();
12886         }
12887
12888         if(this.useSplitTips){
12889             this.splitEl.dom.title = this.collapsible ? this.collapsibleSplitTip : this.splitTip;
12890         }
12891         if(this.collapsible){
12892             this.splitEl.on("dblclick", this.onCollapseClick,  this);
12893         }
12894     },
12895
12896     
12897     getSize : function(){
12898         if(this.isCollapsed){
12899             return this.collapsedEl.getSize();
12900         }
12901         var s = this.panel.getSize();
12902         if(this.position == 'north' || this.position == 'south'){
12903             s.height += this.splitEl.dom.offsetHeight;
12904         }else{
12905             s.width += this.splitEl.dom.offsetWidth;
12906         }
12907         return s;
12908     },
12909
12910     
12911     getHMaxSize : function(){
12912          var cmax = this.maxSize || 10000;
12913          var center = this.layout.center;
12914          return Math.min(cmax, (this.el.getWidth()+center.el.getWidth())-center.getMinWidth());
12915     },
12916
12917     
12918     getVMaxSize : function(){
12919         var cmax = this.maxSize || 10000;
12920         var center = this.layout.center;
12921         return Math.min(cmax, (this.el.getHeight()+center.el.getHeight())-center.getMinHeight());
12922     },
12923
12924     
12925     onSplitMove : function(split, newSize){
12926         var s = this.panel.getSize();
12927         this.lastSplitSize = newSize;
12928         if(this.position == 'north' || this.position == 'south'){
12929             this.panel.setSize(s.width, newSize);
12930             this.state.height = newSize;
12931         }else{
12932             this.panel.setSize(newSize, s.height);
12933             this.state.width = newSize;
12934         }
12935         this.layout.layout();
12936         this.panel.saveState();
12937         return false;
12938     },
12939
12940     
12941     getSplitBar : function(){
12942         return this.split;
12943     },
12944
12945     
12946     destroy : function() {
12947         Ext.destroy(this.miniSplitEl, this.split, this.splitEl);
12948         Ext.layout.BorderLayout.SplitRegion.superclass.destroy.call(this);
12949     }
12950 });
12951
12952 Ext.Container.LAYOUTS['border'] = Ext.layout.BorderLayout;
12953 Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {
12954
12955     
12956     labelSeparator : ':',
12957
12958     
12959
12960     
12961     trackLabels: false,
12962
12963
12964     onRemove: function(c){
12965         Ext.layout.FormLayout.superclass.onRemove.call(this, c);
12966         if(this.trackLabels){
12967             c.un('show', this.onFieldShow, this);
12968             c.un('hide', this.onFieldHide, this);
12969         }
12970         
12971         var el = c.getPositionEl(),
12972                 ct = c.getItemCt && c.getItemCt();
12973         if(c.rendered && ct){
12974             if (el && el.dom) {
12975                 el.insertAfter(ct);
12976             }
12977             Ext.destroy(ct);
12978             Ext.destroyMembers(c, 'label', 'itemCt');
12979             if(c.customItemCt){
12980                 Ext.destroyMembers(c, 'getItemCt', 'customItemCt');
12981             }
12982         }
12983     },
12984
12985     
12986     setContainer : function(ct){
12987         Ext.layout.FormLayout.superclass.setContainer.call(this, ct);
12988         if(ct.labelAlign){
12989             ct.addClass('x-form-label-'+ct.labelAlign);
12990         }
12991
12992         if(ct.hideLabels){
12993             Ext.apply(this, {
12994                 labelStyle: 'display:none',
12995                 elementStyle: 'padding-left:0;',
12996                 labelAdjust: 0
12997             });
12998         }else{
12999             this.labelSeparator = ct.labelSeparator || this.labelSeparator;
13000             ct.labelWidth = ct.labelWidth || 100;
13001             if(Ext.isNumber(ct.labelWidth)){
13002                 var pad = Ext.isNumber(ct.labelPad) ? ct.labelPad : 5;
13003                 Ext.apply(this, {
13004                     labelAdjust: ct.labelWidth + pad,
13005                     labelStyle: 'width:' + ct.labelWidth + 'px;',
13006                     elementStyle: 'padding-left:' + (ct.labelWidth + pad) + 'px'
13007                 });
13008             }
13009             if(ct.labelAlign == 'top'){
13010                 Ext.apply(this, {
13011                     labelStyle: 'width:auto;',
13012                     labelAdjust: 0,
13013                     elementStyle: 'padding-left:0;'
13014                 });
13015             }
13016         }
13017     },
13018
13019     
13020     isHide: function(c){
13021         return c.hideLabel || this.container.hideLabels;
13022     },
13023
13024     onFieldShow: function(c){
13025         c.getItemCt().removeClass('x-hide-' + c.hideMode);
13026     },
13027
13028     onFieldHide: function(c){
13029         c.getItemCt().addClass('x-hide-' + c.hideMode);
13030     },
13031
13032     
13033     getLabelStyle: function(s){
13034         var ls = '', items = [this.labelStyle, s];
13035         for (var i = 0, len = items.length; i < len; ++i){
13036             if (items[i]){
13037                 ls += items[i];
13038                 if (ls.substr(-1, 1) != ';'){
13039                     ls += ';'
13040                 }
13041             }
13042         }
13043         return ls;
13044     },
13045
13046     
13047
13048     
13049     renderItem : function(c, position, target){
13050         if(c && (c.isFormField || c.fieldLabel) && c.inputType != 'hidden'){
13051             var args = this.getTemplateArgs(c);
13052             if(Ext.isNumber(position)){
13053                 position = target.dom.childNodes[position] || null;
13054             }
13055             if(position){
13056                 c.itemCt = this.fieldTpl.insertBefore(position, args, true);
13057             }else{
13058                 c.itemCt = this.fieldTpl.append(target, args, true);
13059             }
13060             if(!c.getItemCt){
13061                 
13062                 
13063                 Ext.apply(c, {
13064                     getItemCt: function(){
13065                         return c.itemCt;
13066                     },
13067                     customItemCt: true
13068                 });
13069             }
13070             c.label = c.getItemCt().child('label.x-form-item-label');
13071             if(!c.rendered){
13072                 c.render('x-form-el-' + c.id);
13073             }else if(!this.isValidParent(c, target)){
13074                 Ext.fly('x-form-el-' + c.id).appendChild(c.getPositionEl());
13075             }
13076             if(this.trackLabels){
13077                 if(c.hidden){
13078                     this.onFieldHide(c);
13079                 }
13080                 c.on({
13081                     scope: this,
13082                     show: this.onFieldShow,
13083                     hide: this.onFieldHide
13084                 });
13085             }
13086             this.configureItem(c);
13087         }else {
13088             Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments);
13089         }
13090     },
13091
13092     
13093     getTemplateArgs: function(field) {
13094         var noLabelSep = !field.fieldLabel || field.hideLabel;
13095         return {
13096             id: field.id,
13097             label: field.fieldLabel,
13098             labelStyle: this.getLabelStyle(field.labelStyle),
13099             elementStyle: this.elementStyle||'',
13100             labelSeparator: noLabelSep ? '' : (Ext.isDefined(field.labelSeparator) ? field.labelSeparator : this.labelSeparator),
13101             itemCls: (field.itemCls||this.container.itemCls||'') + (field.hideLabel ? ' x-hide-label' : ''),
13102             clearCls: field.clearCls || 'x-form-clear-left'
13103         };
13104     },
13105
13106     
13107     adjustWidthAnchor: function(value, c){
13108         if(c.label && !this.isHide(c) && (this.container.labelAlign != 'top')){
13109             var adjust = Ext.isIE6 || (Ext.isIE && !Ext.isStrict);
13110             return value - this.labelAdjust + (adjust ? -3 : 0);
13111         }
13112         return value;
13113     },
13114
13115     adjustHeightAnchor : function(value, c){
13116         if(c.label && !this.isHide(c) && (this.container.labelAlign == 'top')){
13117             return value - c.label.getHeight();
13118         }
13119         return value;
13120     },
13121
13122     
13123     isValidParent : function(c, target){
13124         return target && this.container.getEl().contains(c.getPositionEl());
13125     }
13126
13127     
13128 });
13129
13130 Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout;
13131
13132 Ext.layout.AccordionLayout = Ext.extend(Ext.layout.FitLayout, {
13133     
13134     fill : true,
13135     
13136     autoWidth : true,
13137     
13138     titleCollapse : true,
13139     
13140     hideCollapseTool : false,
13141     
13142     collapseFirst : false,
13143     
13144     animate : false,
13145     
13146     sequence : false,
13147     
13148     activeOnTop : false,
13149
13150     renderItem : function(c){
13151         if(this.animate === false){
13152             c.animCollapse = false;
13153         }
13154         c.collapsible = true;
13155         if(this.autoWidth){
13156             c.autoWidth = true;
13157         }
13158         if(this.titleCollapse){
13159             c.titleCollapse = true;
13160         }
13161         if(this.hideCollapseTool){
13162             c.hideCollapseTool = true;
13163         }
13164         if(this.collapseFirst !== undefined){
13165             c.collapseFirst = this.collapseFirst;
13166         }
13167         if(!this.activeItem && !c.collapsed){
13168             this.setActiveItem(c, true);
13169         }else if(this.activeItem && this.activeItem != c){
13170             c.collapsed = true;
13171         }
13172         Ext.layout.AccordionLayout.superclass.renderItem.apply(this, arguments);
13173         c.header.addClass('x-accordion-hd');
13174         c.on('beforeexpand', this.beforeExpand, this);
13175     },
13176     
13177     onRemove: function(c){
13178         Ext.layout.AccordionLayout.superclass.onRemove.call(this, c);
13179         if(c.rendered){
13180             c.header.removeClass('x-accordion-hd');
13181         }
13182         c.un('beforeexpand', this.beforeExpand, this);
13183     },
13184
13185     
13186     beforeExpand : function(p, anim){
13187         var ai = this.activeItem;
13188         if(ai){
13189             if(this.sequence){
13190                 delete this.activeItem;
13191                 if (!ai.collapsed){
13192                     ai.collapse({callback:function(){
13193                         p.expand(anim || true);
13194                     }, scope: this});
13195                     return false;
13196                 }
13197             }else{
13198                 ai.collapse(this.animate);
13199             }
13200         }
13201         this.setActive(p);
13202         if(this.activeOnTop){
13203             p.el.dom.parentNode.insertBefore(p.el.dom, p.el.dom.parentNode.firstChild);
13204         }
13205         this.layout();
13206     },
13207
13208     
13209     setItemSize : function(item, size){
13210         if(this.fill && item){
13211             var hh = 0;
13212             this.container.items.each(function(p){
13213                 if(p != item){
13214                     hh += p.header.getHeight();
13215                 }    
13216             });
13217             size.height -= hh;
13218             item.setSize(size);
13219         }
13220     },
13221
13222     
13223     setActiveItem : function(item){
13224         this.setActive(item, true);
13225     },
13226     
13227     
13228     setActive : function(item, expand){
13229         var ai = this.activeItem;
13230         item = this.container.getComponent(item);
13231         if(ai != item){
13232             if(item.rendered && item.collapsed && expand){
13233                 item.expand();
13234             }else{
13235                 if(ai){
13236                    ai.fireEvent('deactivate', ai);
13237                 }
13238                 this.activeItem = item;
13239                 item.fireEvent('activate', item);
13240             }
13241         }
13242     }
13243 });
13244 Ext.Container.LAYOUTS.accordion = Ext.layout.AccordionLayout;
13245
13246
13247 Ext.layout.Accordion = Ext.layout.AccordionLayout;
13248 Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {
13249     
13250
13251     
13252     monitorResize:false,
13253     
13254     targetCls: 'x-table-layout-ct',
13255
13256     
13257     tableAttrs:null,
13258     
13259     
13260     setContainer : function(ct){
13261         Ext.layout.TableLayout.superclass.setContainer.call(this, ct);
13262
13263         this.currentRow = 0;
13264         this.currentColumn = 0;
13265         this.cells = [];
13266     },
13267
13268     
13269     onLayout : function(ct, target){
13270         var cs = ct.items.items, len = cs.length, c, i;
13271
13272         if(!this.table){
13273             this.table = target.createChild(
13274                 Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);
13275         }
13276         this.renderAll(ct, target);
13277     },
13278
13279     
13280     getRow : function(index){
13281         var row = this.table.tBodies[0].childNodes[index];
13282         if(!row){
13283             row = document.createElement('tr');
13284             this.table.tBodies[0].appendChild(row);
13285         }
13286         return row;
13287     },
13288
13289     
13290     getNextCell : function(c){
13291         var cell = this.getNextNonSpan(this.currentColumn, this.currentRow);
13292         var curCol = this.currentColumn = cell[0], curRow = this.currentRow = cell[1];
13293         for(var rowIndex = curRow; rowIndex < curRow + (c.rowspan || 1); rowIndex++){
13294             if(!this.cells[rowIndex]){
13295                 this.cells[rowIndex] = [];
13296             }
13297             for(var colIndex = curCol; colIndex < curCol + (c.colspan || 1); colIndex++){
13298                 this.cells[rowIndex][colIndex] = true;
13299             }
13300         }
13301         var td = document.createElement('td');
13302         if(c.cellId){
13303             td.id = c.cellId;
13304         }
13305         var cls = 'x-table-layout-cell';
13306         if(c.cellCls){
13307             cls += ' ' + c.cellCls;
13308         }
13309         td.className = cls;
13310         if(c.colspan){
13311             td.colSpan = c.colspan;
13312         }
13313         if(c.rowspan){
13314             td.rowSpan = c.rowspan;
13315         }
13316         this.getRow(curRow).appendChild(td);
13317         return td;
13318     },
13319     
13320     
13321     getNextNonSpan: function(colIndex, rowIndex){
13322         var cols = this.columns;
13323         while((cols && colIndex >= cols) || (this.cells[rowIndex] && this.cells[rowIndex][colIndex])) {
13324             if(cols && colIndex >= cols){
13325                 rowIndex++;
13326                 colIndex = 0;
13327             }else{
13328                 colIndex++;
13329             }
13330         }
13331         return [colIndex, rowIndex];
13332     },
13333
13334     
13335     renderItem : function(c, position, target){
13336         if(c && !c.rendered){
13337             c.render(this.getNextCell(c));
13338             this.configureItem(c, position);
13339         }else if(c && !this.isValidParent(c, target)){
13340             var container = this.getNextCell(c);
13341             container.insertBefore(c.getPositionEl().dom, null);
13342             c.container = Ext.get(container);
13343             this.configureItem(c, position);
13344         }
13345     },
13346
13347     
13348     isValidParent : function(c, target){
13349         return c.getPositionEl().up('table', 5).dom.parentNode === (target.dom || target);
13350     }
13351
13352     
13353 });
13354
13355 Ext.Container.LAYOUTS['table'] = Ext.layout.TableLayout;
13356 Ext.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {
13357
13358     extraCls: 'x-abs-layout-item',
13359
13360     onLayout : function(ct, target){
13361         target.position();
13362         this.paddingLeft = target.getPadding('l');
13363         this.paddingTop = target.getPadding('t');
13364
13365         Ext.layout.AbsoluteLayout.superclass.onLayout.call(this, ct, target);
13366     },
13367
13368     
13369     adjustWidthAnchor : function(value, comp){
13370         return value ? value - comp.getPosition(true)[0] + this.paddingLeft : value;
13371     },
13372
13373     
13374     adjustHeightAnchor : function(value, comp){
13375         return  value ? value - comp.getPosition(true)[1] + this.paddingTop : value;
13376     }
13377     
13378 });
13379 Ext.Container.LAYOUTS['absolute'] = Ext.layout.AbsoluteLayout;
13380
13381 Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
13382     
13383     defaultMargins : {left:0,top:0,right:0,bottom:0},
13384     
13385     padding : '0',
13386     
13387     pack : 'start',
13388
13389     
13390     monitorResize : true,
13391     scrollOffset : 0,
13392     extraCls : 'x-box-item',
13393     targetCls : 'x-box-layout-ct',
13394     innerCls : 'x-box-inner',
13395
13396     constructor : function(config){
13397         Ext.layout.BoxLayout.superclass.constructor.call(this, config);
13398         if(Ext.isString(this.defaultMargins)){
13399             this.defaultMargins = this.parseMargins(this.defaultMargins);
13400         }
13401     },
13402
13403     
13404     isValidParent : function(c, target){
13405         return c.getPositionEl().dom.parentNode == this.innerCt.dom;
13406     },
13407
13408     
13409     onLayout : function(ct, target){
13410         var cs = ct.items.items, len = cs.length, c, i, last = len-1, cm;
13411
13412         if(!this.innerCt){
13413             
13414             
13415             this.innerCt = target.createChild({cls:this.innerCls});
13416             this.padding = this.parseMargins(this.padding);
13417         }
13418         this.renderAll(ct, this.innerCt);
13419     },
13420
13421     
13422     renderItem : function(c){
13423         if(Ext.isString(c.margins)){
13424             c.margins = this.parseMargins(c.margins);
13425         }else if(!c.margins){
13426             c.margins = this.defaultMargins;
13427         }
13428         Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments);
13429     },
13430
13431     
13432     getTargetSize : function(target){
13433         return (Ext.isIE6 && Ext.isStrict && target.dom == document.body) ? target.getStyleSize() : target.getViewSize(true);
13434     },
13435
13436     getItems: function(ct){
13437         var items = [];
13438         ct.items.each(function(c){
13439             if(c.isVisible()){
13440                 items.push(c);
13441             }
13442         });
13443         return items;
13444     }
13445 });
13446
13447
13448 Ext.layout.VBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
13449     
13450     align : 'left', 
13451     
13452     
13453
13454     
13455     onLayout : function(ct, target){
13456         Ext.layout.VBoxLayout.superclass.onLayout.call(this, ct, target);
13457
13458         var cs = this.getItems(ct), cm, ch, margin, cl, diff, aw,
13459             size = target.getViewSize(true),
13460             w = size.width,
13461             h = size.height - this.scrollOffset,
13462             l = this.padding.left, t = this.padding.top,
13463             isStart = this.pack == 'start',
13464             stretchWidth = w - (this.padding.left + this.padding.right),
13465             extraHeight = 0,
13466             maxWidth = 0,
13467             totalFlex = 0,
13468             flexHeight = 0,
13469             usedHeight = 0,
13470             idx = 0,
13471             heights = [],
13472             restore = [],
13473             c,
13474             csLen = cs.length;
13475
13476         
13477         for (i = 0 ; i < csLen; i++) {
13478             c = cs[i];
13479             cm = c.margins;
13480             margin = cm.top + cm.bottom;
13481             maxWidth = Math.max(maxWidth, c.getWidth() + cm.left + cm.right);
13482         }
13483
13484         var innerCtWidth = maxWidth + this.padding.left + this.padding.right;
13485         switch(this.align){
13486             case 'stretch':
13487                 this.innerCt.setSize(w, h);
13488                 break;
13489             case 'stretchmax':
13490             case 'left':
13491                 this.innerCt.setSize(innerCtWidth, h);
13492                 break;
13493             case 'center':
13494                 this.innerCt.setSize(w = Math.max(w, innerCtWidth), h);
13495                 break;
13496         }
13497
13498         var availableWidth = Math.max(0, w - this.padding.left - this.padding.right);
13499         
13500         for (i = 0 ; i < csLen; i++) {
13501             c = cs[i];
13502             cm = c.margins;
13503             if(this.align == 'stretch'){
13504                 c.setWidth((stretchWidth - (cm.left + cm.right)).constrain(
13505                     c.minWidth || 0, c.maxWidth || 1000000));
13506             }else if(this.align == 'stretchmax'){
13507                 c.setWidth((maxWidth - (cm.left + cm.right)).constrain(
13508                     c.minWidth || 0, c.maxWidth || 1000000));
13509             }else if(isStart && c.flex){
13510                 c.setWidth();
13511             }
13512
13513         }
13514
13515         
13516         for (i = 0 ; i < csLen; i++) {
13517             c = cs[i];
13518             cm = c.margins;
13519             totalFlex += c.flex || 0;
13520             ch = c.getHeight();
13521             margin = cm.top + cm.bottom;
13522             extraHeight += ch + margin;
13523             flexHeight += margin + (c.flex ? 0 : ch);
13524         }
13525         extraHeight = h - extraHeight - this.padding.top - this.padding.bottom;
13526
13527         var availHeight = Math.max(0, h - this.padding.top - this.padding.bottom - flexHeight),
13528             leftOver = availHeight;
13529         for (i = 0 ; i < csLen; i++) {
13530             c = cs[i];
13531             if(isStart && c.flex){
13532                 ch = Math.floor(availHeight * (c.flex / totalFlex));
13533                 leftOver -= ch;
13534                 heights.push(ch);
13535             }
13536         }
13537         if(this.pack == 'center'){
13538             t += extraHeight ? extraHeight / 2 : 0;
13539         }else if(this.pack == 'end'){
13540             t += extraHeight;
13541         }
13542         idx = 0;
13543         
13544         for (i = 0 ; i < csLen; i++) {
13545             c = cs[i];
13546             cm = c.margins;
13547             t += cm.top;
13548             aw = availableWidth;
13549             cl = l + cm.left 
13550
13551
13552             if(this.align == 'center'){
13553                 if((diff = availableWidth - (c.getWidth() + cm.left + cm.right)) > 0){
13554                     cl += (diff/2);
13555                     aw -= diff;
13556                 }
13557             }
13558
13559             c.setPosition(cl, t);
13560             if(isStart && c.flex){
13561                 ch = Math.max(0, heights[idx++] + (leftOver-- > 0 ? 1 : 0));
13562                 c.setSize(aw, ch);
13563             }else{
13564                 ch = c.getHeight();
13565             }
13566             t += ch + cm.bottom;
13567         }
13568     }
13569 });
13570
13571 Ext.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout;
13572
13573
13574 Ext.layout.HBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
13575     
13576     align : 'top', 
13577     
13578     
13579
13580     
13581     onLayout : function(ct, target){
13582         Ext.layout.HBoxLayout.superclass.onLayout.call(this, ct, target);
13583
13584         var cs = this.getItems(ct), cm, cw, margin, ch, diff,
13585             size = target.getViewSize(true),
13586             w = size.width - this.scrollOffset,
13587             h = size.height,
13588             l = this.padding.left, t = this.padding.top,
13589             isStart = this.pack == 'start',
13590             isRestore = ['stretch', 'stretchmax'].indexOf(this.align) == -1,
13591             stretchHeight = h - (this.padding.top + this.padding.bottom),
13592             extraWidth = 0,
13593             maxHeight = 0,
13594             totalFlex = 0,
13595             flexWidth = 0,
13596             usedWidth = 0;
13597
13598         Ext.each(cs, function(c){
13599             cm = c.margins;
13600             totalFlex += c.flex || 0;
13601             cw = c.getWidth();
13602             margin = cm.left + cm.right;
13603             extraWidth += cw + margin;
13604             flexWidth += margin + (c.flex ? 0 : cw);
13605             maxHeight = Math.max(maxHeight, c.getHeight() + cm.top + cm.bottom);
13606         });
13607         extraWidth = w - extraWidth - this.padding.left - this.padding.right;
13608
13609         var innerCtHeight = maxHeight + this.padding.top + this.padding.bottom;
13610         switch(this.align){
13611             case 'stretch':
13612                 this.innerCt.setSize(w, h);
13613                 break;
13614             case 'stretchmax':
13615             case 'top':
13616                 this.innerCt.setSize(w, innerCtHeight);
13617                 break;
13618             case 'middle':
13619                 this.innerCt.setSize(w, h = Math.max(h, innerCtHeight));
13620                 break;
13621         }
13622
13623
13624         var availWidth = Math.max(0, w - this.padding.left - this.padding.right - flexWidth),
13625             leftOver = availWidth,
13626             widths = [],
13627             restore = [],
13628             idx = 0,
13629             availableHeight = Math.max(0, h - this.padding.top - this.padding.bottom);
13630
13631
13632         Ext.each(cs, function(c){
13633             if(isStart && c.flex){
13634                 cw = Math.floor(availWidth * (c.flex / totalFlex));
13635                 leftOver -= cw;
13636                 widths.push(cw);
13637             }
13638         });
13639
13640         if(this.pack == 'center'){
13641             l += extraWidth ? extraWidth / 2 : 0;
13642         }else if(this.pack == 'end'){
13643             l += extraWidth;
13644         }
13645         Ext.each(cs, function(c){
13646             cm = c.margins;
13647             l += cm.left;
13648             c.setPosition(l, t + cm.top);
13649             if(isStart && c.flex){
13650                 cw = Math.max(0, widths[idx++] + (leftOver-- > 0 ? 1 : 0));
13651                 if(isRestore){
13652                     restore.push(c.getHeight());
13653                 }
13654                 c.setSize(cw, availableHeight);
13655             }else{
13656                 cw = c.getWidth();
13657             }
13658             l += cw + cm.right;
13659         });
13660
13661         idx = 0;
13662         Ext.each(cs, function(c){
13663             cm = c.margins;
13664             ch = c.getHeight();
13665             if(isStart && c.flex){
13666                 ch = restore[idx++];
13667             }
13668             if(this.align == 'stretch'){
13669                 c.setHeight((stretchHeight - (cm.top + cm.bottom)).constrain(
13670                     c.minHeight || 0, c.maxHeight || 1000000));
13671             }else if(this.align == 'stretchmax'){
13672                 c.setHeight((maxHeight - (cm.top + cm.bottom)).constrain(
13673                     c.minHeight || 0, c.maxHeight || 1000000));
13674             }else{
13675                 if(this.align == 'middle'){
13676                     diff = availableHeight - (ch + cm.top + cm.bottom);
13677                     ch = t + cm.top + (diff/2);
13678                     if(diff > 0){
13679                         c.setPosition(c.x, ch);
13680                     }
13681                 }
13682                 if(isStart && c.flex){
13683                     c.setHeight(ch);
13684                 }
13685             }
13686         }, this);
13687     }
13688 });
13689
13690 Ext.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout;
13691
13692 Ext.Viewport = Ext.extend(Ext.Container, {
13693     
13694     
13695     
13696     
13697     
13698     
13699     
13700     
13701     
13702     
13703     
13704     
13705
13706     initComponent : function() {
13707         Ext.Viewport.superclass.initComponent.call(this);
13708         document.getElementsByTagName('html')[0].className += ' x-viewport';
13709         this.el = Ext.getBody();
13710         this.el.setHeight = Ext.emptyFn;
13711         this.el.setWidth = Ext.emptyFn;
13712         this.el.setSize = Ext.emptyFn;
13713         this.el.dom.scroll = 'no';
13714         this.allowDomMove = false;
13715         this.autoWidth = true;
13716         this.autoHeight = true;
13717         Ext.EventManager.onWindowResize(this.fireResize, this);
13718         this.renderTo = this.el;
13719     },
13720
13721     fireResize : function(w, h){
13722         this.onResize(w, h, w, h);
13723     }
13724 });
13725 Ext.reg('viewport', Ext.Viewport);
13726
13727 Ext.Panel = Ext.extend(Ext.Container, {
13728     
13729     
13730     
13731     
13732     
13733     
13734     
13735     
13736     
13737     
13738     
13739     
13740     
13741     
13742     
13743     
13744     
13745     
13746     
13747     
13748     
13749     
13750     
13751     
13752     
13753     
13754     
13755     
13756     
13757     
13758     
13759     
13760
13761     
13762     
13763     
13764     
13765     
13766     
13767     
13768     
13769
13770
13771     
13772     baseCls : 'x-panel',
13773     
13774     collapsedCls : 'x-panel-collapsed',
13775     
13776     maskDisabled : true,
13777     
13778     animCollapse : Ext.enableFx,
13779     
13780     headerAsText : true,
13781     
13782     buttonAlign : 'right',
13783     
13784     collapsed : false,
13785     
13786     collapseFirst : true,
13787     
13788     minButtonWidth : 75,
13789     
13790     
13791     elements : 'body',
13792     
13793     preventBodyReset : false,
13794
13795     
13796     padding: undefined,
13797
13798     
13799     resizeEvent: 'bodyresize',
13800
13801     
13802     
13803     
13804     toolTarget : 'header',
13805     collapseEl : 'bwrap',
13806     slideAnchor : 't',
13807     disabledClass : '',
13808
13809     
13810     deferHeight : true,
13811     
13812     expandDefaults: {
13813         duration : 0.25
13814     },
13815     
13816     collapseDefaults : {
13817         duration : 0.25
13818     },
13819
13820     
13821     initComponent : function(){
13822         Ext.Panel.superclass.initComponent.call(this);
13823
13824         this.addEvents(
13825             
13826             'bodyresize',
13827             
13828             'titlechange',
13829             
13830             'iconchange',
13831             
13832             'collapse',
13833             
13834             'expand',
13835             
13836             'beforecollapse',
13837             
13838             'beforeexpand',
13839             
13840             'beforeclose',
13841             
13842             'close',
13843             
13844             'activate',
13845             
13846             'deactivate'
13847         );
13848
13849         if(this.unstyled){
13850             this.baseCls = 'x-plain';
13851         }
13852
13853
13854         this.toolbars = [];
13855         
13856         if(this.tbar){
13857             this.elements += ',tbar';
13858             this.topToolbar = this.createToolbar(this.tbar);
13859             delete this.tbar;
13860
13861         }
13862         if(this.bbar){
13863             this.elements += ',bbar';
13864             this.bottomToolbar = this.createToolbar(this.bbar);
13865             delete this.bbar;
13866         }
13867
13868         if(this.header === true){
13869             this.elements += ',header';
13870             delete this.header;
13871         }else if(this.headerCfg || (this.title && this.header !== false)){
13872             this.elements += ',header';
13873         }
13874
13875         if(this.footerCfg || this.footer === true){
13876             this.elements += ',footer';
13877             delete this.footer;
13878         }
13879
13880         if(this.buttons){
13881             this.fbar = this.buttons;
13882             delete this.buttons;
13883         }
13884         if(this.fbar){
13885             this.createFbar(this.fbar);
13886         }
13887         if(this.autoLoad){
13888             this.on('render', this.doAutoLoad, this, {delay:10});
13889         }
13890     },
13891
13892     
13893     createFbar : function(fbar){
13894         var min = this.minButtonWidth;
13895         this.elements += ',footer';
13896         this.fbar = this.createToolbar(fbar, {
13897             buttonAlign: this.buttonAlign,
13898             toolbarCls: 'x-panel-fbar',
13899             enableOverflow: false,
13900             defaults: function(c){
13901                 return {
13902                     minWidth: c.minWidth || min
13903                 };
13904             }
13905         });
13906         //@compat addButton and buttons could possibly be removed
13907
13908         //@target 4.0
13909
13910         
13911         this.fbar.items.each(function(c){
13912             c.minWidth = c.minWidth || this.minButtonWidth;
13913         }, this);
13914         this.buttons = this.fbar.items.items;
13915     },
13916
13917     
13918     createToolbar: function(tb, options){
13919         var result;
13920         
13921         if(Ext.isArray(tb)){
13922             tb = {
13923                 items: tb
13924             };
13925         }
13926         result = tb.events ? Ext.apply(tb, options) : this.createComponent(Ext.apply({}, tb, options), 'toolbar');
13927         result.ownerCt = this;
13928         result.bufferResize = false;
13929         this.toolbars.push(result);
13930         return result;
13931     },
13932
13933     
13934     createElement : function(name, pnode){
13935         if(this[name]){
13936             pnode.appendChild(this[name].dom);
13937             return;
13938         }
13939
13940         if(name === 'bwrap' || this.elements.indexOf(name) != -1){
13941             if(this[name+'Cfg']){
13942                 this[name] = Ext.fly(pnode).createChild(this[name+'Cfg']);
13943             }else{
13944                 var el = document.createElement('div');
13945                 el.className = this[name+'Cls'];
13946                 this[name] = Ext.get(pnode.appendChild(el));
13947             }
13948             if(this[name+'CssClass']){
13949                 this[name].addClass(this[name+'CssClass']);
13950             }
13951             if(this[name+'Style']){
13952                 this[name].applyStyles(this[name+'Style']);
13953             }
13954         }
13955     },
13956
13957     
13958     onRender : function(ct, position){
13959         Ext.Panel.superclass.onRender.call(this, ct, position);
13960         this.createClasses();
13961
13962         var el = this.el,
13963             d = el.dom,
13964             bw,
13965             ts;
13966
13967
13968         if(this.collapsible && !this.hideCollapseTool){
13969             this.tools = this.tools ? this.tools.slice(0) : [];
13970             this.tools[this.collapseFirst?'unshift':'push']({
13971                 id: 'toggle',
13972                 handler : this.toggleCollapse,
13973                 scope: this
13974             });
13975         }
13976
13977         if(this.tools){
13978             ts = this.tools;
13979             this.elements += (this.header !== false) ? ',header' : '';
13980         }
13981         this.tools = {};
13982
13983         el.addClass(this.baseCls);
13984         if(d.firstChild){ 
13985             this.header = el.down('.'+this.headerCls);
13986             this.bwrap = el.down('.'+this.bwrapCls);
13987             var cp = this.bwrap ? this.bwrap : el;
13988             this.tbar = cp.down('.'+this.tbarCls);
13989             this.body = cp.down('.'+this.bodyCls);
13990             this.bbar = cp.down('.'+this.bbarCls);
13991             this.footer = cp.down('.'+this.footerCls);
13992             this.fromMarkup = true;
13993         }
13994         if (this.preventBodyReset === true) {
13995             el.addClass('x-panel-reset');
13996         }
13997         if(this.cls){
13998             el.addClass(this.cls);
13999         }
14000
14001         if(this.buttons){
14002             this.elements += ',footer';
14003         }
14004
14005         
14006
14007         
14008         if(this.frame){
14009             el.insertHtml('afterBegin', String.format(Ext.Element.boxMarkup, this.baseCls));
14010
14011             this.createElement('header', d.firstChild.firstChild.firstChild);
14012             this.createElement('bwrap', d);
14013
14014             
14015             bw = this.bwrap.dom;
14016             var ml = d.childNodes[1], bl = d.childNodes[2];
14017             bw.appendChild(ml);
14018             bw.appendChild(bl);
14019
14020             var mc = bw.firstChild.firstChild.firstChild;
14021             this.createElement('tbar', mc);
14022             this.createElement('body', mc);
14023             this.createElement('bbar', mc);
14024             this.createElement('footer', bw.lastChild.firstChild.firstChild);
14025
14026             if(!this.footer){
14027                 this.bwrap.dom.lastChild.className += ' x-panel-nofooter';
14028             }
14029             
14030             this.ft = Ext.get(this.bwrap.dom.lastChild);
14031             this.mc = Ext.get(mc);
14032         }else{
14033             this.createElement('header', d);
14034             this.createElement('bwrap', d);
14035
14036             
14037             bw = this.bwrap.dom;
14038             this.createElement('tbar', bw);
14039             this.createElement('body', bw);
14040             this.createElement('bbar', bw);
14041             this.createElement('footer', bw);
14042
14043             if(!this.header){
14044                 this.body.addClass(this.bodyCls + '-noheader');
14045                 if(this.tbar){
14046                     this.tbar.addClass(this.tbarCls + '-noheader');
14047                 }
14048             }
14049         }
14050
14051         if(Ext.isDefined(this.padding)){
14052             this.body.setStyle('padding', this.body.addUnits(this.padding));
14053         }
14054
14055         if(this.border === false){
14056             this.el.addClass(this.baseCls + '-noborder');
14057             this.body.addClass(this.bodyCls + '-noborder');
14058             if(this.header){
14059                 this.header.addClass(this.headerCls + '-noborder');
14060             }
14061             if(this.footer){
14062                 this.footer.addClass(this.footerCls + '-noborder');
14063             }
14064             if(this.tbar){
14065                 this.tbar.addClass(this.tbarCls + '-noborder');
14066             }
14067             if(this.bbar){
14068                 this.bbar.addClass(this.bbarCls + '-noborder');
14069             }
14070         }
14071
14072         if(this.bodyBorder === false){
14073            this.body.addClass(this.bodyCls + '-noborder');
14074         }
14075
14076         this.bwrap.enableDisplayMode('block');
14077
14078         if(this.header){
14079             this.header.unselectable();
14080
14081             
14082             if(this.headerAsText){
14083                 this.header.dom.innerHTML =
14084                     '<span class="' + this.headerTextCls + '">'+this.header.dom.innerHTML+'</span>';
14085
14086                 if(this.iconCls){
14087                     this.setIconClass(this.iconCls);
14088                 }
14089             }
14090         }
14091
14092         if(this.floating){
14093             this.makeFloating(this.floating);
14094         }
14095
14096         if(this.collapsible && this.titleCollapse && this.header){
14097             this.mon(this.header, 'click', this.toggleCollapse, this);
14098             this.header.setStyle('cursor', 'pointer');
14099         }
14100         if(ts){
14101             this.addTool.apply(this, ts);
14102         }
14103         if(this.fbar){
14104             this.footer.addClass('x-panel-btns');
14105             this.fbar.render(this.footer);
14106             this.footer.createChild({cls:'x-clear'});
14107         }
14108
14109         if(this.tbar && this.topToolbar){
14110             this.topToolbar.render(this.tbar);
14111         }
14112         if(this.bbar && this.bottomToolbar){
14113             this.bottomToolbar.render(this.bbar);
14114
14115         }
14116     },
14117
14118     
14119     setIconClass : function(cls){
14120         var old = this.iconCls;
14121         this.iconCls = cls;
14122         if(this.rendered && this.header){
14123             if(this.frame){
14124                 this.header.addClass('x-panel-icon');
14125                 this.header.replaceClass(old, this.iconCls);
14126             }else{
14127                 var hd = this.header,
14128                     img = hd.child('img.x-panel-inline-icon');
14129                 if(img){
14130                     Ext.fly(img).replaceClass(old, this.iconCls);
14131                 }else{
14132                     Ext.DomHelper.insertBefore(hd.dom.firstChild, {
14133                         tag:'img', src: Ext.BLANK_IMAGE_URL, cls:'x-panel-inline-icon '+this.iconCls
14134                     });
14135                  }
14136             }
14137         }
14138         this.fireEvent('iconchange', this, cls, old);
14139     },
14140
14141     
14142     makeFloating : function(cfg){
14143         this.floating = true;
14144         this.el = new Ext.Layer(Ext.apply({}, cfg, {
14145             shadow: Ext.isDefined(this.shadow) ? this.shadow : 'sides',
14146             shadowOffset: this.shadowOffset,
14147             constrain:false,
14148             shim: this.shim === false ? false : undefined
14149         }), this.el);
14150     },
14151
14152     
14153     getTopToolbar : function(){
14154         return this.topToolbar;
14155     },
14156
14157     
14158     getBottomToolbar : function(){
14159         return this.bottomToolbar;
14160     },
14161
14162     
14163     addButton : function(config, handler, scope){
14164         if(!this.fbar){
14165             this.createFbar([]);
14166         }
14167         if(handler){
14168             if(Ext.isString(config)){
14169                 config = {text: config};
14170             }
14171             config = Ext.apply({
14172                 handler: handler,
14173                 scope: scope
14174             }, config)
14175         }
14176         return this.fbar.add(config);
14177     },
14178
14179     
14180     addTool : function(){
14181         if(!this.rendered){
14182             if(!this.tools){
14183                 this.tools = [];
14184             }
14185             Ext.each(arguments, function(arg){
14186                 this.tools.push(arg)
14187             }, this);
14188             return;
14189         }
14190          
14191         if(!this[this.toolTarget]){
14192             return;
14193         }
14194         if(!this.toolTemplate){
14195             
14196             var tt = new Ext.Template(
14197                  '<div class="x-tool x-tool-{id}">&#160;</div>'
14198             );
14199             tt.disableFormats = true;
14200             tt.compile();
14201             Ext.Panel.prototype.toolTemplate = tt;
14202         }
14203         for(var i = 0, a = arguments, len = a.length; i < len; i++) {
14204             var tc = a[i];
14205             if(!this.tools[tc.id]){
14206                 var overCls = 'x-tool-'+tc.id+'-over';
14207                 var t = this.toolTemplate.insertFirst((tc.align !== 'left') ? this[this.toolTarget] : this[this.toolTarget].child('span'), tc, true);
14208                 this.tools[tc.id] = t;
14209                 t.enableDisplayMode('block');
14210                 this.mon(t, 'click',  this.createToolHandler(t, tc, overCls, this));
14211                 if(tc.on){
14212                     this.mon(t, tc.on);
14213                 }
14214                 if(tc.hidden){
14215                     t.hide();
14216                 }
14217                 if(tc.qtip){
14218                     if(Ext.isObject(tc.qtip)){
14219                         Ext.QuickTips.register(Ext.apply({
14220                               target: t.id
14221                         }, tc.qtip));
14222                     } else {
14223                         t.dom.qtip = tc.qtip;
14224                     }
14225                 }
14226                 t.addClassOnOver(overCls);
14227             }
14228         }
14229     },
14230
14231     onLayout : function(shallow, force){
14232         if(this.hasLayout && this.toolbars.length > 0){
14233             Ext.each(this.toolbars, function(tb){
14234                 tb.doLayout(undefined, force);
14235             });
14236             this.syncHeight();
14237         }
14238     },
14239
14240     syncHeight : function(){
14241         var h = this.toolbarHeight,
14242                 bd = this.body,
14243                 lsh = this.lastSize.height,
14244                 sz;
14245
14246         if(this.autoHeight || !Ext.isDefined(lsh) || lsh == 'auto'){
14247             return;
14248         }
14249
14250
14251         if(h != this.getToolbarHeight()){
14252             h = Math.max(0, this.adjustBodyHeight(lsh - this.getFrameHeight()));
14253             bd.setHeight(h);
14254             sz = bd.getSize();
14255             this.toolbarHeight = this.getToolbarHeight();
14256             this.onBodyResize(sz.width, sz.height);
14257         }
14258     },
14259
14260     
14261     onShow : function(){
14262         if(this.floating){
14263             return this.el.show();
14264         }
14265         Ext.Panel.superclass.onShow.call(this);
14266     },
14267
14268     
14269     onHide : function(){
14270         if(this.floating){
14271             return this.el.hide();
14272         }
14273         Ext.Panel.superclass.onHide.call(this);
14274     },
14275
14276     
14277     createToolHandler : function(t, tc, overCls, panel){
14278         return function(e){
14279             t.removeClass(overCls);
14280             if(tc.stopEvent !== false){
14281                 e.stopEvent();
14282             }
14283             if(tc.handler){
14284                 tc.handler.call(tc.scope || t, e, t, panel, tc);
14285             }
14286         };
14287     },
14288
14289     
14290     afterRender : function(){
14291         if(this.floating && !this.hidden){
14292             this.el.show();
14293         }
14294         if(this.title){
14295             this.setTitle(this.title);
14296         }
14297         if(this.collapsed){
14298             this.collapsed = false;
14299             this.collapse(false);
14300         }
14301         Ext.Panel.superclass.afterRender.call(this); 
14302         this.initEvents();
14303     },    
14304
14305     
14306     getKeyMap : function(){
14307         if(!this.keyMap){
14308             this.keyMap = new Ext.KeyMap(this.el, this.keys);
14309         }
14310         return this.keyMap;
14311     },
14312
14313     
14314     initEvents : function(){
14315         if(this.keys){
14316             this.getKeyMap();
14317         }
14318         if(this.draggable){
14319             this.initDraggable();
14320         }
14321         if(this.toolbars.length > 0){
14322             Ext.each(this.toolbars, function(tb){
14323                 tb.doLayout();
14324                 tb.on({
14325                     scope: this,
14326                     afterlayout: this.syncHeight,
14327                     remove: this.syncHeight
14328                 });
14329             }, this);
14330             if(!this.ownerCt){
14331                 this.syncHeight();
14332             }
14333         }
14334
14335     },
14336
14337     
14338     initDraggable : function(){
14339         
14340         this.dd = new Ext.Panel.DD(this, Ext.isBoolean(this.draggable) ? null : this.draggable);
14341     },
14342
14343     
14344     beforeEffect : function(anim){
14345         if(this.floating){
14346             this.el.beforeAction();
14347         }
14348         if(anim !== false){
14349             this.el.addClass('x-panel-animated');
14350         }
14351     },
14352
14353     
14354     afterEffect : function(anim){
14355         this.syncShadow();
14356         if(anim !== false){
14357             this.el.removeClass('x-panel-animated');
14358         }
14359     },
14360
14361     
14362     createEffect : function(a, cb, scope){
14363         var o = {
14364             scope:scope,
14365             block:true
14366         };
14367         if(a === true){
14368             o.callback = cb;
14369             return o;
14370         }else if(!a.callback){
14371             o.callback = cb;
14372         }else { 
14373             o.callback = function(){
14374                 cb.call(scope);
14375                 Ext.callback(a.callback, a.scope);
14376             };
14377         }
14378         return Ext.applyIf(o, a);
14379     },
14380
14381     
14382     collapse : function(animate){
14383         if(this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforecollapse', this, animate) === false){
14384             return;
14385         }
14386         var doAnim = animate === true || (animate !== false && this.animCollapse);
14387         this.beforeEffect(doAnim);
14388         this.onCollapse(doAnim, animate);
14389         return this;
14390     },
14391
14392     
14393     onCollapse : function(doAnim, animArg){
14394         if(doAnim){
14395             this[this.collapseEl].slideOut(this.slideAnchor,
14396                     Ext.apply(this.createEffect(animArg||true, this.afterCollapse, this),
14397                         this.collapseDefaults));
14398         }else{
14399             this[this.collapseEl].hide();
14400             this.afterCollapse(false);
14401         }
14402     },
14403
14404     
14405     afterCollapse : function(anim){
14406         this.collapsed = true;
14407         this.el.addClass(this.collapsedCls);
14408         this.afterEffect(anim);
14409         this.fireEvent('collapse', this);
14410     },
14411
14412     
14413     expand : function(animate){
14414         if(!this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforeexpand', this, animate) === false){
14415             return;
14416         }
14417         var doAnim = animate === true || (animate !== false && this.animCollapse);
14418         this.el.removeClass(this.collapsedCls);
14419         this.beforeEffect(doAnim);
14420         this.onExpand(doAnim, animate);
14421         return this;
14422     },
14423
14424     
14425     onExpand : function(doAnim, animArg){
14426         if(doAnim){
14427             this[this.collapseEl].slideIn(this.slideAnchor,
14428                     Ext.apply(this.createEffect(animArg||true, this.afterExpand, this),
14429                         this.expandDefaults));
14430         }else{
14431             this[this.collapseEl].show();
14432             this.afterExpand(false);
14433         }
14434     },
14435
14436     
14437     afterExpand : function(anim){
14438         this.collapsed = false;
14439         this.afterEffect(anim);
14440         if(Ext.isDefined(this.deferLayout)){
14441             this.doLayout(true);
14442         }
14443         this.fireEvent('expand', this);
14444     },
14445
14446     
14447     toggleCollapse : function(animate){
14448         this[this.collapsed ? 'expand' : 'collapse'](animate);
14449         return this;
14450     },
14451
14452     
14453     onDisable : function(){
14454         if(this.rendered && this.maskDisabled){
14455             this.el.mask();
14456         }
14457         Ext.Panel.superclass.onDisable.call(this);
14458     },
14459
14460     
14461     onEnable : function(){
14462         if(this.rendered && this.maskDisabled){
14463             this.el.unmask();
14464         }
14465         Ext.Panel.superclass.onEnable.call(this);
14466     },
14467
14468     
14469     onResize : function(w, h){
14470         if(Ext.isDefined(w) || Ext.isDefined(h)){
14471             if(!this.collapsed){
14472                 
14473                 
14474                 
14475
14476                 if(Ext.isNumber(w)){
14477                     this.body.setWidth(w = this.adjustBodyWidth(w - this.getFrameWidth()));
14478                 } else if (w == 'auto') {
14479                     w = this.body.setWidth('auto').dom.offsetWidth;
14480                 } else {
14481                     w = this.body.dom.offsetWidth;
14482                 }
14483
14484                 if(this.tbar){
14485                     this.tbar.setWidth(w);
14486                     if(this.topToolbar){
14487                         this.topToolbar.setSize(w);
14488                     }
14489                 }
14490                 if(this.bbar){
14491                     this.bbar.setWidth(w);
14492                     if(this.bottomToolbar){
14493                         this.bottomToolbar.setSize(w);
14494                         
14495                         if (Ext.isIE) {
14496                             this.bbar.setStyle('position', 'static');
14497                             this.bbar.setStyle('position', '');
14498                         }
14499                     }
14500                 }
14501                 if(this.footer){
14502                     this.footer.setWidth(w);
14503                     if(this.fbar){
14504                         this.fbar.setSize(Ext.isIE ? (w - this.footer.getFrameWidth('lr')) : 'auto');
14505                     }
14506                 }
14507
14508                 
14509                 if(Ext.isNumber(h)){
14510                     h = Math.max(0, this.adjustBodyHeight(h - this.getFrameHeight()));
14511                     this.body.setHeight(h);
14512                 }else if(h == 'auto'){
14513                     this.body.setHeight(h);
14514                 }
14515
14516                 if(this.disabled && this.el._mask){
14517                     this.el._mask.setSize(this.el.dom.clientWidth, this.el.getHeight());
14518                 }
14519             }else{
14520                 this.queuedBodySize = {width: w, height: h};
14521                 if(!this.queuedExpand && this.allowQueuedExpand !== false){
14522                     this.queuedExpand = true;
14523                     this.on('expand', function(){
14524                         delete this.queuedExpand;
14525                         this.onResize(this.queuedBodySize.width, this.queuedBodySize.height);
14526                     }, this, {single:true});
14527                 }
14528             }
14529             this.onBodyResize(w, h);
14530         }
14531         this.syncShadow();
14532         Ext.Panel.superclass.onResize.call(this);
14533     },
14534
14535     
14536     onBodyResize: function(w, h){
14537         this.fireEvent('bodyresize', this, w, h);
14538     },
14539
14540     
14541     getToolbarHeight: function(){
14542         var h = 0;
14543         if(this.rendered){
14544             Ext.each(this.toolbars, function(tb){
14545                 h += tb.getHeight();
14546             }, this);
14547         }
14548         return h;
14549     },
14550
14551     
14552     adjustBodyHeight : function(h){
14553         return h;
14554     },
14555
14556     
14557     adjustBodyWidth : function(w){
14558         return w;
14559     },
14560
14561     
14562     onPosition : function(){
14563         this.syncShadow();
14564     },
14565
14566     
14567     getFrameWidth : function(){
14568         var w = this.el.getFrameWidth('lr') + this.bwrap.getFrameWidth('lr');
14569
14570         if(this.frame){
14571             var l = this.bwrap.dom.firstChild;
14572             w += (Ext.fly(l).getFrameWidth('l') + Ext.fly(l.firstChild).getFrameWidth('r'));
14573             w += this.mc.getFrameWidth('lr');
14574         }
14575         return w;
14576     },
14577
14578     
14579     getFrameHeight : function(){
14580         var h  = this.el.getFrameWidth('tb') + this.bwrap.getFrameWidth('tb');
14581         h += (this.tbar ? this.tbar.getHeight() : 0) +
14582              (this.bbar ? this.bbar.getHeight() : 0);
14583
14584         if(this.frame){
14585             h += this.el.dom.firstChild.offsetHeight + this.ft.dom.offsetHeight + this.mc.getFrameWidth('tb');
14586         }else{
14587             h += (this.header ? this.header.getHeight() : 0) +
14588                 (this.footer ? this.footer.getHeight() : 0);
14589         }
14590         return h;
14591     },
14592
14593     
14594     getInnerWidth : function(){
14595         return this.getSize().width - this.getFrameWidth();
14596     },
14597
14598     
14599     getInnerHeight : function(){
14600         return this.getSize().height - this.getFrameHeight();
14601     },
14602
14603     
14604     syncShadow : function(){
14605         if(this.floating){
14606             this.el.sync(true);
14607         }
14608     },
14609
14610     
14611     getLayoutTarget : function(){
14612         return this.body;
14613     },
14614
14615     
14616     getContentTarget : function(){
14617         return this.body;
14618     },
14619
14620     
14621     setTitle : function(title, iconCls){
14622         this.title = title;
14623         if(this.header && this.headerAsText){
14624             this.header.child('span').update(title);
14625         }
14626         if(iconCls){
14627             this.setIconClass(iconCls);
14628         }
14629         this.fireEvent('titlechange', this, title);
14630         return this;
14631     },
14632
14633     
14634     getUpdater : function(){
14635         return this.body.getUpdater();
14636     },
14637
14638      
14639     load : function(){
14640         var um = this.body.getUpdater();
14641         um.update.apply(um, arguments);
14642         return this;
14643     },
14644
14645     
14646     beforeDestroy : function(){
14647         Ext.Panel.superclass.beforeDestroy.call(this);
14648         if(this.header){
14649             this.header.removeAllListeners();
14650         }
14651         if(this.tools){
14652             for(var k in this.tools){
14653                 Ext.destroy(this.tools[k]);
14654             }
14655         }
14656         if(Ext.isArray(this.buttons)){
14657             while(this.buttons.length) {
14658                 Ext.destroy(this.buttons[0]);
14659             }
14660         }
14661         if(this.rendered){
14662             Ext.destroy(
14663                 this.ft,
14664                 this.header,
14665                 this.footer,
14666                 this.toolbars,
14667                 this.tbar,
14668                 this.bbar,
14669                 this.body,
14670                 this.mc,
14671                 this.bwrap
14672             );
14673             if (this.fbar) {
14674                 Ext.destroy(
14675                     this.fbar,
14676                     this.fbar.el
14677                 );
14678             }
14679         }else{
14680             Ext.destroy(
14681                 this.topToolbar,
14682                 this.bottomToolbar
14683             );
14684         }
14685     },
14686
14687     
14688     createClasses : function(){
14689         this.headerCls = this.baseCls + '-header';
14690         this.headerTextCls = this.baseCls + '-header-text';
14691         this.bwrapCls = this.baseCls + '-bwrap';
14692         this.tbarCls = this.baseCls + '-tbar';
14693         this.bodyCls = this.baseCls + '-body';
14694         this.bbarCls = this.baseCls + '-bbar';
14695         this.footerCls = this.baseCls + '-footer';
14696     },
14697
14698     
14699     createGhost : function(cls, useShim, appendTo){
14700         var el = document.createElement('div');
14701         el.className = 'x-panel-ghost ' + (cls ? cls : '');
14702         if(this.header){
14703             el.appendChild(this.el.dom.firstChild.cloneNode(true));
14704         }
14705         Ext.fly(el.appendChild(document.createElement('ul'))).setHeight(this.bwrap.getHeight());
14706         el.style.width = this.el.dom.offsetWidth + 'px';;
14707         if(!appendTo){
14708             this.container.dom.appendChild(el);
14709         }else{
14710             Ext.getDom(appendTo).appendChild(el);
14711         }
14712         if(useShim !== false && this.el.useShim !== false){
14713             var layer = new Ext.Layer({shadow:false, useDisplay:true, constrain:false}, el);
14714             layer.show();
14715             return layer;
14716         }else{
14717             return new Ext.Element(el);
14718         }
14719     },
14720
14721     
14722     doAutoLoad : function(){
14723         var u = this.body.getUpdater();
14724         if(this.renderer){
14725             u.setRenderer(this.renderer);
14726         }
14727         u.update(Ext.isObject(this.autoLoad) ? this.autoLoad : {url: this.autoLoad});
14728     },
14729
14730     
14731     getTool : function(id) {
14732         return this.tools[id];
14733     }
14734
14735
14736 });
14737 Ext.reg('panel', Ext.Panel);
14738
14739 Ext.Editor = function(field, config){
14740     if(field.field){
14741         this.field = Ext.create(field.field, 'textfield');
14742         config = Ext.apply({}, field); 
14743         delete config.field;
14744     }else{
14745         this.field = field;
14746     }
14747     Ext.Editor.superclass.constructor.call(this, config);
14748 };
14749
14750 Ext.extend(Ext.Editor, Ext.Component, {
14751     
14752     
14753     
14754     
14755     
14756     
14757     
14758     value : "",
14759     
14760     alignment: "c-c?",
14761     
14762     offsets: [0, 0],
14763     
14764     shadow : "frame",
14765     
14766     constrain : false,
14767     
14768     swallowKeys : true,
14769     
14770     completeOnEnter : true,
14771     
14772     cancelOnEsc : true,
14773     
14774     updateEl : false,
14775
14776     initComponent : function(){
14777         Ext.Editor.superclass.initComponent.call(this);
14778         this.addEvents(
14779             
14780             "beforestartedit",
14781             
14782             "startedit",
14783             
14784             "beforecomplete",
14785             
14786             "complete",
14787             
14788             "canceledit",
14789             
14790             "specialkey"
14791         );
14792     },
14793
14794     
14795     onRender : function(ct, position){
14796         this.el = new Ext.Layer({
14797             shadow: this.shadow,
14798             cls: "x-editor",
14799             parentEl : ct,
14800             shim : this.shim,
14801             shadowOffset: this.shadowOffset || 4,
14802             id: this.id,
14803             constrain: this.constrain
14804         });
14805         if(this.zIndex){
14806             this.el.setZIndex(this.zIndex);
14807         }
14808         this.el.setStyle("overflow", Ext.isGecko ? "auto" : "hidden");
14809         if(this.field.msgTarget != 'title'){
14810             this.field.msgTarget = 'qtip';
14811         }
14812         this.field.inEditor = true;
14813         this.mon(this.field, {
14814             scope: this,
14815             blur: this.onBlur,
14816             specialkey: this.onSpecialKey
14817         });
14818         if(this.field.grow){
14819             this.mon(this.field, "autosize", this.el.sync,  this.el, {delay:1});
14820         }
14821         this.field.render(this.el).show();
14822         this.field.getEl().dom.name = '';
14823         if(this.swallowKeys){
14824             this.field.el.swallowEvent([
14825                 'keypress', 
14826                 'keydown'   
14827             ]);
14828         }
14829     },
14830
14831     
14832     onSpecialKey : function(field, e){
14833         var key = e.getKey(),
14834             complete = this.completeOnEnter && key == e.ENTER,
14835             cancel = this.cancelOnEsc && key == e.ESC;
14836         if(complete || cancel){
14837             e.stopEvent();
14838             if(complete){
14839                 this.completeEdit();
14840             }else{
14841                 this.cancelEdit();
14842             }
14843             if(field.triggerBlur){
14844                 field.triggerBlur(); 
14845             }
14846         }
14847         this.fireEvent('specialkey', field, e);
14848     },
14849
14850     
14851     startEdit : function(el, value){
14852         if(this.editing){
14853             this.completeEdit();
14854         }
14855         this.boundEl = Ext.get(el);
14856         var v = value !== undefined ? value : this.boundEl.dom.innerHTML;
14857         if(!this.rendered){
14858             this.render(this.parentEl || document.body);
14859         }
14860         if(this.fireEvent("beforestartedit", this, this.boundEl, v) !== false){
14861             this.startValue = v;
14862             this.field.reset();
14863             this.field.setValue(v);
14864             this.realign(true);
14865             this.editing = true;
14866             this.show();
14867         }
14868     },
14869
14870     
14871     doAutoSize : function(){
14872         if(this.autoSize){
14873             var sz = this.boundEl.getSize(),
14874                 fs = this.field.getSize();
14875
14876             switch(this.autoSize){
14877                 case "width":
14878                     this.setSize(sz.width, fs.height);
14879                     break;
14880                 case "height":
14881                     this.setSize(fs.width, sz.height);
14882                     break;
14883                 case "none":
14884                     this.setSize(fs.width, fs.height);
14885                     break;
14886                 default:
14887                     this.setSize(sz.width, sz.height);
14888             }
14889         }
14890     },
14891
14892     
14893     setSize : function(w, h){
14894         delete this.field.lastSize;
14895         this.field.setSize(w, h);
14896         if(this.el){
14897             if(Ext.isGecko2 || Ext.isOpera){
14898                 
14899                 this.el.setSize(w, h);
14900             }
14901             this.el.sync();
14902         }
14903     },
14904
14905     
14906     realign : function(autoSize){
14907         if(autoSize === true){
14908             this.doAutoSize();
14909         }
14910         this.el.alignTo(this.boundEl, this.alignment, this.offsets);
14911     },
14912
14913     
14914     completeEdit : function(remainVisible){
14915         if(!this.editing){
14916             return;
14917         }
14918         var v = this.getValue();
14919         if(!this.field.isValid()){
14920             if(this.revertInvalid !== false){
14921                 this.cancelEdit(remainVisible);
14922             }
14923             return;
14924         }
14925         if(String(v) === String(this.startValue) && this.ignoreNoChange){
14926             this.hideEdit(remainVisible);
14927             return;
14928         }
14929         if(this.fireEvent("beforecomplete", this, v, this.startValue) !== false){
14930             v = this.getValue();
14931             if(this.updateEl && this.boundEl){
14932                 this.boundEl.update(v);
14933             }
14934             this.hideEdit(remainVisible);
14935             this.fireEvent("complete", this, v, this.startValue);
14936         }
14937     },
14938
14939     
14940     onShow : function(){
14941         this.el.show();
14942         if(this.hideEl !== false){
14943             this.boundEl.hide();
14944         }
14945         this.field.show().focus(false, true);
14946         this.fireEvent("startedit", this.boundEl, this.startValue);
14947     },
14948
14949     
14950     cancelEdit : function(remainVisible){
14951         if(this.editing){
14952             var v = this.getValue();
14953             this.setValue(this.startValue);
14954             this.hideEdit(remainVisible);
14955             this.fireEvent("canceledit", this, v, this.startValue);
14956         }
14957     },
14958     
14959     
14960     hideEdit: function(remainVisible){
14961         if(remainVisible !== true){
14962             this.editing = false;
14963             this.hide();
14964         }
14965     },
14966
14967     
14968     onBlur : function(){
14969         if(this.allowBlur !== true && this.editing){
14970             this.completeEdit();
14971         }
14972     },
14973
14974     
14975     onHide : function(){
14976         if(this.editing){
14977             this.completeEdit();
14978             return;
14979         }
14980         this.field.blur();
14981         if(this.field.collapse){
14982             this.field.collapse();
14983         }
14984         this.el.hide();
14985         if(this.hideEl !== false){
14986             this.boundEl.show();
14987         }
14988     },
14989
14990     
14991     setValue : function(v){
14992         this.field.setValue(v);
14993     },
14994
14995     
14996     getValue : function(){
14997         return this.field.getValue();
14998     },
14999
15000     beforeDestroy : function(){
15001         Ext.destroyMembers(this, 'field');
15002         
15003         delete this.parentEl;
15004         delete this.boundEl;
15005     }
15006 });
15007 Ext.reg('editor', Ext.Editor);
15008
15009 Ext.ColorPalette = Ext.extend(Ext.Component, {
15010         
15011     
15012     itemCls : 'x-color-palette',
15013     
15014     value : null,
15015     
15016     clickEvent :'click',
15017     
15018     ctype : 'Ext.ColorPalette',
15019
15020     
15021     allowReselect : false,
15022
15023     
15024     colors : [
15025         '000000', '993300', '333300', '003300', '003366', '000080', '333399', '333333',
15026         '800000', 'FF6600', '808000', '008000', '008080', '0000FF', '666699', '808080',
15027         'FF0000', 'FF9900', '99CC00', '339966', '33CCCC', '3366FF', '800080', '969696',
15028         'FF00FF', 'FFCC00', 'FFFF00', '00FF00', '00FFFF', '00CCFF', '993366', 'C0C0C0',
15029         'FF99CC', 'FFCC99', 'FFFF99', 'CCFFCC', 'CCFFFF', '99CCFF', 'CC99FF', 'FFFFFF'
15030     ],
15031
15032     
15033     
15034     
15035     
15036     initComponent : function(){
15037         Ext.ColorPalette.superclass.initComponent.call(this);
15038         this.addEvents(
15039             
15040             'select'
15041         );
15042
15043         if(this.handler){
15044             this.on('select', this.handler, this.scope, true);
15045         }    
15046     },
15047
15048     
15049     onRender : function(container, position){
15050         this.autoEl = {
15051             tag: 'div',
15052             cls: this.itemCls
15053         };
15054         Ext.ColorPalette.superclass.onRender.call(this, container, position);
15055         var t = this.tpl || new Ext.XTemplate(
15056             '<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on">&#160;</span></em></a></tpl>'
15057         );
15058         t.overwrite(this.el, this.colors);
15059         this.mon(this.el, this.clickEvent, this.handleClick, this, {delegate: 'a'});
15060         if(this.clickEvent != 'click'){
15061                 this.mon(this.el, 'click', Ext.emptyFn, this, {delegate: 'a', preventDefault: true});
15062         }
15063     },
15064
15065     
15066     afterRender : function(){
15067         Ext.ColorPalette.superclass.afterRender.call(this);
15068         if(this.value){
15069             var s = this.value;
15070             this.value = null;
15071             this.select(s);
15072         }
15073     },
15074
15075     
15076     handleClick : function(e, t){
15077         e.preventDefault();
15078         if(!this.disabled){
15079             var c = t.className.match(/(?:^|\s)color-(.{6})(?:\s|$)/)[1];
15080             this.select(c.toUpperCase());
15081         }
15082     },
15083
15084     
15085     select : function(color){
15086         color = color.replace('#', '');
15087         if(color != this.value || this.allowReselect){
15088             var el = this.el;
15089             if(this.value){
15090                 el.child('a.color-'+this.value).removeClass('x-color-palette-sel');
15091             }
15092             el.child('a.color-'+color).addClass('x-color-palette-sel');
15093             this.value = color;
15094             this.fireEvent('select', this, color);
15095         }
15096     }
15097
15098     
15099 });
15100 Ext.reg('colorpalette', Ext.ColorPalette);
15101
15102 Ext.DatePicker = Ext.extend(Ext.BoxComponent, {
15103     
15104     todayText : 'Today',
15105     
15106     okText : '&#160;OK&#160;',
15107     
15108     cancelText : 'Cancel',
15109     
15110      
15111     
15112     todayTip : '{0} (Spacebar)',
15113     
15114     minText : 'This date is before the minimum date',
15115     
15116     maxText : 'This date is after the maximum date',
15117     
15118     format : 'm/d/y',
15119     
15120     disabledDaysText : 'Disabled',
15121     
15122     disabledDatesText : 'Disabled',
15123     
15124     monthNames : Date.monthNames,
15125     
15126     dayNames : Date.dayNames,
15127     
15128     nextText : 'Next Month (Control+Right)',
15129     
15130     prevText : 'Previous Month (Control+Left)',
15131     
15132     monthYearText : 'Choose a month (Control+Up/Down to move years)',
15133     
15134     startDay : 0,
15135     
15136     showToday : true,
15137     
15138     
15139     
15140     
15141     
15142     
15143     
15144     
15145     focusOnSelect: true,
15146
15147     
15148     initComponent : function(){
15149         Ext.DatePicker.superclass.initComponent.call(this);
15150
15151         this.value = this.value ?
15152                  this.value.clearTime(true) : new Date().clearTime();
15153
15154         this.addEvents(
15155             
15156             'select'
15157         );
15158
15159         if(this.handler){
15160             this.on('select', this.handler,  this.scope || this);
15161         }
15162
15163         this.initDisabledDays();
15164     },
15165
15166     
15167     initDisabledDays : function(){
15168         if(!this.disabledDatesRE && this.disabledDates){
15169             var dd = this.disabledDates,
15170                 len = dd.length - 1,
15171                 re = '(?:';
15172                 
15173             Ext.each(dd, function(d, i){
15174                 re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];
15175                 if(i != len){
15176                     re += '|';
15177                 }
15178             }, this);
15179             this.disabledDatesRE = new RegExp(re + ')');
15180         }
15181     },
15182
15183     
15184     setDisabledDates : function(dd){
15185         if(Ext.isArray(dd)){
15186             this.disabledDates = dd;
15187             this.disabledDatesRE = null;
15188         }else{
15189             this.disabledDatesRE = dd;
15190         }
15191         this.initDisabledDays();
15192         this.update(this.value, true);
15193     },
15194
15195     
15196     setDisabledDays : function(dd){
15197         this.disabledDays = dd;
15198         this.update(this.value, true);
15199     },
15200
15201     
15202     setMinDate : function(dt){
15203         this.minDate = dt;
15204         this.update(this.value, true);
15205     },
15206
15207     
15208     setMaxDate : function(dt){
15209         this.maxDate = dt;
15210         this.update(this.value, true);
15211     },
15212
15213     
15214     setValue : function(value){
15215         this.value = value.clearTime(true);
15216         this.update(this.value);
15217     },
15218
15219     
15220     getValue : function(){
15221         return this.value;
15222     },
15223
15224     
15225     focus : function(){
15226         this.update(this.activeDate);
15227     },
15228     
15229     
15230     onEnable: function(initial){
15231         Ext.DatePicker.superclass.onEnable.call(this);    
15232         this.doDisabled(false);
15233         this.update(initial ? this.value : this.activeDate);
15234         if(Ext.isIE){
15235             this.el.repaint();
15236         }
15237         
15238     },
15239     
15240     
15241     onDisable : function(){
15242         Ext.DatePicker.superclass.onDisable.call(this);   
15243         this.doDisabled(true);
15244         if(Ext.isIE && !Ext.isIE8){
15245             
15246              Ext.each([].concat(this.textNodes, this.el.query('th span')), function(el){
15247                  Ext.fly(el).repaint();
15248              });
15249         }
15250     },
15251     
15252     
15253     doDisabled : function(disabled){
15254         this.keyNav.setDisabled(disabled);
15255         this.prevRepeater.setDisabled(disabled);
15256         this.nextRepeater.setDisabled(disabled);
15257         if(this.showToday){
15258             this.todayKeyListener.setDisabled(disabled);
15259             this.todayBtn.setDisabled(disabled);
15260         }
15261     },
15262
15263     
15264     onRender : function(container, position){
15265         var m = [
15266              '<table cellspacing="0">',
15267                 '<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>',
15268                 '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'],
15269                 dn = this.dayNames,
15270                 i;
15271         for(i = 0; i < 7; i++){
15272             var d = this.startDay+i;
15273             if(d > 6){
15274                 d = d-7;
15275             }
15276             m.push('<th><span>', dn[d].substr(0,1), '</span></th>');
15277         }
15278         m[m.length] = '</tr></thead><tbody><tr>';
15279         for(i = 0; i < 42; i++) {
15280             if(i % 7 === 0 && i !== 0){
15281                 m[m.length] = '</tr><tr>';
15282             }
15283             m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
15284         }
15285         m.push('</tr></tbody></table></td></tr>',
15286                 this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>' : '',
15287                 '</table><div class="x-date-mp"></div>');
15288
15289         var el = document.createElement('div');
15290         el.className = 'x-date-picker';
15291         el.innerHTML = m.join('');
15292
15293         container.dom.insertBefore(el, position);
15294
15295         this.el = Ext.get(el);
15296         this.eventEl = Ext.get(el.firstChild);
15297
15298         this.prevRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-left a'), {
15299             handler: this.showPrevMonth,
15300             scope: this,
15301             preventDefault:true,
15302             stopDefault:true
15303         });
15304
15305         this.nextRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-right a'), {
15306             handler: this.showNextMonth,
15307             scope: this,
15308             preventDefault:true,
15309             stopDefault:true
15310         });
15311
15312         this.monthPicker = this.el.down('div.x-date-mp');
15313         this.monthPicker.enableDisplayMode('block');
15314
15315         this.keyNav = new Ext.KeyNav(this.eventEl, {
15316             'left' : function(e){
15317                 if(e.ctrlKey){
15318                     this.showPrevMonth();
15319                 }else{
15320                     this.update(this.activeDate.add('d', -1));    
15321                 }
15322             },
15323
15324             'right' : function(e){
15325                 if(e.ctrlKey){
15326                     this.showNextMonth();
15327                 }else{
15328                     this.update(this.activeDate.add('d', 1));    
15329                 }
15330             },
15331
15332             'up' : function(e){
15333                 if(e.ctrlKey){
15334                     this.showNextYear();
15335                 }else{
15336                     this.update(this.activeDate.add('d', -7));
15337                 }
15338             },
15339
15340             'down' : function(e){
15341                 if(e.ctrlKey){
15342                     this.showPrevYear();
15343                 }else{
15344                     this.update(this.activeDate.add('d', 7));
15345                 }
15346             },
15347
15348             'pageUp' : function(e){
15349                 this.showNextMonth();
15350             },
15351
15352             'pageDown' : function(e){
15353                 this.showPrevMonth();
15354             },
15355
15356             'enter' : function(e){
15357                 e.stopPropagation();
15358                 return true;
15359             },
15360
15361             scope : this
15362         });
15363
15364         this.el.unselectable();
15365
15366         this.cells = this.el.select('table.x-date-inner tbody td');
15367         this.textNodes = this.el.query('table.x-date-inner tbody span');
15368
15369         this.mbtn = new Ext.Button({
15370             text: '&#160;',
15371             tooltip: this.monthYearText,
15372             renderTo: this.el.child('td.x-date-middle', true)
15373         });
15374         this.mbtn.el.child('em').addClass('x-btn-arrow');
15375
15376         if(this.showToday){
15377             this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday,  this);
15378             var today = (new Date()).dateFormat(this.format);
15379             this.todayBtn = new Ext.Button({
15380                 renderTo: this.el.child('td.x-date-bottom', true),
15381                 text: String.format(this.todayText, today),
15382                 tooltip: String.format(this.todayTip, today),
15383                 handler: this.selectToday,
15384                 scope: this
15385             });
15386         }
15387         this.mon(this.eventEl, 'mousewheel', this.handleMouseWheel, this);
15388         this.mon(this.eventEl, 'click', this.handleDateClick,  this, {delegate: 'a.x-date-date'});
15389         this.mon(this.mbtn, 'click', this.showMonthPicker, this);
15390         this.onEnable(true);
15391     },
15392
15393     
15394     createMonthPicker : function(){
15395         if(!this.monthPicker.dom.firstChild){
15396             var buf = ['<table border="0" cellspacing="0">'];
15397             for(var i = 0; i < 6; i++){
15398                 buf.push(
15399                     '<tr><td class="x-date-mp-month"><a href="#">', Date.getShortMonthName(i), '</a></td>',
15400                     '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', Date.getShortMonthName(i + 6), '</a></td>',
15401                     i === 0 ?
15402                     '<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>' :
15403                     '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'
15404                 );
15405             }
15406             buf.push(
15407                 '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',
15408                     this.okText,
15409                     '</button><button type="button" class="x-date-mp-cancel">',
15410                     this.cancelText,
15411                     '</button></td></tr>',
15412                 '</table>'
15413             );
15414             this.monthPicker.update(buf.join(''));
15415
15416             this.mon(this.monthPicker, 'click', this.onMonthClick, this);
15417             this.mon(this.monthPicker, 'dblclick', this.onMonthDblClick, this);
15418
15419             this.mpMonths = this.monthPicker.select('td.x-date-mp-month');
15420             this.mpYears = this.monthPicker.select('td.x-date-mp-year');
15421
15422             this.mpMonths.each(function(m, a, i){
15423                 i += 1;
15424                 if((i%2) === 0){
15425                     m.dom.xmonth = 5 + Math.round(i * 0.5);
15426                 }else{
15427                     m.dom.xmonth = Math.round((i-1) * 0.5);
15428                 }
15429             });
15430         }
15431     },
15432
15433     
15434     showMonthPicker : function(){
15435         if(!this.disabled){
15436             this.createMonthPicker();
15437             var size = this.el.getSize();
15438             this.monthPicker.setSize(size);
15439             this.monthPicker.child('table').setSize(size);
15440
15441             this.mpSelMonth = (this.activeDate || this.value).getMonth();
15442             this.updateMPMonth(this.mpSelMonth);
15443             this.mpSelYear = (this.activeDate || this.value).getFullYear();
15444             this.updateMPYear(this.mpSelYear);
15445
15446             this.monthPicker.slideIn('t', {duration:0.2});
15447         }
15448     },
15449
15450     
15451     updateMPYear : function(y){
15452         this.mpyear = y;
15453         var ys = this.mpYears.elements;
15454         for(var i = 1; i <= 10; i++){
15455             var td = ys[i-1], y2;
15456             if((i%2) === 0){
15457                 y2 = y + Math.round(i * 0.5);
15458                 td.firstChild.innerHTML = y2;
15459                 td.xyear = y2;
15460             }else{
15461                 y2 = y - (5-Math.round(i * 0.5));
15462                 td.firstChild.innerHTML = y2;
15463                 td.xyear = y2;
15464             }
15465             this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');
15466         }
15467     },
15468
15469     
15470     updateMPMonth : function(sm){
15471         this.mpMonths.each(function(m, a, i){
15472             m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');
15473         });
15474     },
15475
15476     
15477     selectMPMonth : function(m){
15478
15479     },
15480
15481     
15482     onMonthClick : function(e, t){
15483         e.stopEvent();
15484         var el = new Ext.Element(t), pn;
15485         if(el.is('button.x-date-mp-cancel')){
15486             this.hideMonthPicker();
15487         }
15488         else if(el.is('button.x-date-mp-ok')){
15489             var d = new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate());
15490             if(d.getMonth() != this.mpSelMonth){
15491                 
15492                 d = new Date(this.mpSelYear, this.mpSelMonth, 1).getLastDateOfMonth();
15493             }
15494             this.update(d);
15495             this.hideMonthPicker();
15496         }
15497         else if((pn = el.up('td.x-date-mp-month', 2))){
15498             this.mpMonths.removeClass('x-date-mp-sel');
15499             pn.addClass('x-date-mp-sel');
15500             this.mpSelMonth = pn.dom.xmonth;
15501         }
15502         else if((pn = el.up('td.x-date-mp-year', 2))){
15503             this.mpYears.removeClass('x-date-mp-sel');
15504             pn.addClass('x-date-mp-sel');
15505             this.mpSelYear = pn.dom.xyear;
15506         }
15507         else if(el.is('a.x-date-mp-prev')){
15508             this.updateMPYear(this.mpyear-10);
15509         }
15510         else if(el.is('a.x-date-mp-next')){
15511             this.updateMPYear(this.mpyear+10);
15512         }
15513     },
15514
15515     
15516     onMonthDblClick : function(e, t){
15517         e.stopEvent();
15518         var el = new Ext.Element(t), pn;
15519         if((pn = el.up('td.x-date-mp-month', 2))){
15520             this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));
15521             this.hideMonthPicker();
15522         }
15523         else if((pn = el.up('td.x-date-mp-year', 2))){
15524             this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
15525             this.hideMonthPicker();
15526         }
15527     },
15528
15529     
15530     hideMonthPicker : function(disableAnim){
15531         if(this.monthPicker){
15532             if(disableAnim === true){
15533                 this.monthPicker.hide();
15534             }else{
15535                 this.monthPicker.slideOut('t', {duration:0.2});
15536             }
15537         }
15538     },
15539
15540     
15541     showPrevMonth : function(e){
15542         this.update(this.activeDate.add('mo', -1));
15543     },
15544
15545     
15546     showNextMonth : function(e){
15547         this.update(this.activeDate.add('mo', 1));
15548     },
15549
15550     
15551     showPrevYear : function(){
15552         this.update(this.activeDate.add('y', -1));
15553     },
15554
15555     
15556     showNextYear : function(){
15557         this.update(this.activeDate.add('y', 1));
15558     },
15559
15560     
15561     handleMouseWheel : function(e){
15562         e.stopEvent();
15563         if(!this.disabled){
15564             var delta = e.getWheelDelta();
15565             if(delta > 0){
15566                 this.showPrevMonth();
15567             } else if(delta < 0){
15568                 this.showNextMonth();
15569             }
15570         }
15571     },
15572
15573     
15574     handleDateClick : function(e, t){
15575         e.stopEvent();
15576         if(!this.disabled && t.dateValue && !Ext.fly(t.parentNode).hasClass('x-date-disabled')){
15577             this.cancelFocus = this.focusOnSelect === false;
15578             this.setValue(new Date(t.dateValue));
15579             delete this.cancelFocus;
15580             this.fireEvent('select', this, this.value);
15581         }
15582     },
15583
15584     
15585     selectToday : function(){
15586         if(this.todayBtn && !this.todayBtn.disabled){
15587             this.setValue(new Date().clearTime());
15588             this.fireEvent('select', this, this.value);
15589         }
15590     },
15591
15592     
15593     update : function(date, forceRefresh){
15594         if(this.rendered){
15595                 var vd = this.activeDate, vis = this.isVisible();
15596                 this.activeDate = date;
15597                 if(!forceRefresh && vd && this.el){
15598                     var t = date.getTime();
15599                     if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
15600                         this.cells.removeClass('x-date-selected');
15601                         this.cells.each(function(c){
15602                            if(c.dom.firstChild.dateValue == t){
15603                                c.addClass('x-date-selected');
15604                                if(vis && !this.cancelFocus){
15605                                    Ext.fly(c.dom.firstChild).focus(50);
15606                                }
15607                                return false;
15608                            }
15609                         }, this);
15610                         return;
15611                     }
15612                 }
15613                 var days = date.getDaysInMonth(),
15614                     firstOfMonth = date.getFirstDateOfMonth(),
15615                     startingPos = firstOfMonth.getDay()-this.startDay;
15616         
15617                 if(startingPos < 0){
15618                     startingPos += 7;
15619                 }
15620                 days += startingPos;
15621         
15622                 var pm = date.add('mo', -1),
15623                     prevStart = pm.getDaysInMonth()-startingPos,
15624                     cells = this.cells.elements,
15625                     textEls = this.textNodes,
15626                     
15627                     day = 86400000,
15628                     d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart)).clearTime(),
15629                     today = new Date().clearTime().getTime(),
15630                     sel = date.clearTime(true).getTime(),
15631                     min = this.minDate ? this.minDate.clearTime(true) : Number.NEGATIVE_INFINITY,
15632                     max = this.maxDate ? this.maxDate.clearTime(true) : Number.POSITIVE_INFINITY,
15633                     ddMatch = this.disabledDatesRE,
15634                     ddText = this.disabledDatesText,
15635                     ddays = this.disabledDays ? this.disabledDays.join('') : false,
15636                     ddaysText = this.disabledDaysText,
15637                     format = this.format;
15638         
15639                 if(this.showToday){
15640                     var td = new Date().clearTime(),
15641                         disable = (td < min || td > max ||
15642                         (ddMatch && format && ddMatch.test(td.dateFormat(format))) ||
15643                         (ddays && ddays.indexOf(td.getDay()) != -1));
15644         
15645                     if(!this.disabled){
15646                         this.todayBtn.setDisabled(disable);
15647                         this.todayKeyListener[disable ? 'disable' : 'enable']();
15648                     }
15649                 }
15650         
15651                 var setCellClass = function(cal, cell){
15652                     cell.title = '';
15653                     var t = d.getTime();
15654                     cell.firstChild.dateValue = t;
15655                     if(t == today){
15656                         cell.className += ' x-date-today';
15657                         cell.title = cal.todayText;
15658                     }
15659                     if(t == sel){
15660                         cell.className += ' x-date-selected';
15661                         if(vis){
15662                             Ext.fly(cell.firstChild).focus(50);
15663                         }
15664                     }
15665                     
15666                     if(t < min) {
15667                         cell.className = ' x-date-disabled';
15668                         cell.title = cal.minText;
15669                         return;
15670                     }
15671                     if(t > max) {
15672                         cell.className = ' x-date-disabled';
15673                         cell.title = cal.maxText;
15674                         return;
15675                     }
15676                     if(ddays){
15677                         if(ddays.indexOf(d.getDay()) != -1){
15678                             cell.title = ddaysText;
15679                             cell.className = ' x-date-disabled';
15680                         }
15681                     }
15682                     if(ddMatch && format){
15683                         var fvalue = d.dateFormat(format);
15684                         if(ddMatch.test(fvalue)){
15685                             cell.title = ddText.replace('%0', fvalue);
15686                             cell.className = ' x-date-disabled';
15687                         }
15688                     }
15689                 };
15690         
15691                 var i = 0;
15692                 for(; i < startingPos; i++) {
15693                     textEls[i].innerHTML = (++prevStart);
15694                     d.setDate(d.getDate()+1);
15695                     cells[i].className = 'x-date-prevday';
15696                     setCellClass(this, cells[i]);
15697                 }
15698                 for(; i < days; i++){
15699                     var intDay = i - startingPos + 1;
15700                     textEls[i].innerHTML = (intDay);
15701                     d.setDate(d.getDate()+1);
15702                     cells[i].className = 'x-date-active';
15703                     setCellClass(this, cells[i]);
15704                 }
15705                 var extraDays = 0;
15706                 for(; i < 42; i++) {
15707                      textEls[i].innerHTML = (++extraDays);
15708                      d.setDate(d.getDate()+1);
15709                      cells[i].className = 'x-date-nextday';
15710                      setCellClass(this, cells[i]);
15711                 }
15712         
15713                 this.mbtn.setText(this.monthNames[date.getMonth()] + ' ' + date.getFullYear());
15714         
15715                 if(!this.internalRender){
15716                     var main = this.el.dom.firstChild,
15717                         w = main.offsetWidth;
15718                     this.el.setWidth(w + this.el.getBorderWidth('lr'));
15719                     Ext.fly(main).setWidth(w);
15720                     this.internalRender = true;
15721                     
15722                     
15723                     
15724                     if(Ext.isOpera && !this.secondPass){
15725                         main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + 'px';
15726                         this.secondPass = true;
15727                         this.update.defer(10, this, [date]);
15728                     }
15729                 }
15730         }
15731     },
15732
15733     
15734     beforeDestroy : function() {
15735         if(this.rendered){
15736             Ext.destroy(
15737                 this.keyNav,
15738                 this.monthPicker,
15739                 this.eventEl,
15740                 this.mbtn,
15741                 this.nextRepeater,
15742                 this.prevRepeater,
15743                 this.cells.el,
15744                 this.todayBtn
15745             );
15746             delete this.textNodes;
15747             delete this.cells.elements;
15748         }
15749     }
15750
15751     
15752 });
15753
15754 Ext.reg('datepicker', Ext.DatePicker);
15755
15756 Ext.LoadMask = function(el, config){
15757     this.el = Ext.get(el);
15758     Ext.apply(this, config);
15759     if(this.store){
15760         this.store.on({
15761             scope: this,
15762             beforeload: this.onBeforeLoad,
15763             load: this.onLoad,
15764             exception: this.onLoad
15765         });
15766         this.removeMask = Ext.value(this.removeMask, false);
15767     }else{
15768         var um = this.el.getUpdater();
15769         um.showLoadIndicator = false; 
15770         um.on({
15771             scope: this,
15772             beforeupdate: this.onBeforeLoad,
15773             update: this.onLoad,
15774             failure: this.onLoad
15775         });
15776         this.removeMask = Ext.value(this.removeMask, true);
15777     }
15778 };
15779
15780 Ext.LoadMask.prototype = {
15781     
15782     
15783     
15784     msg : 'Loading...',
15785     
15786     msgCls : 'x-mask-loading',
15787
15788     
15789     disabled: false,
15790
15791     
15792     disable : function(){
15793        this.disabled = true;
15794     },
15795
15796     
15797     enable : function(){
15798         this.disabled = false;
15799     },
15800
15801     
15802     onLoad : function(){
15803         this.el.unmask(this.removeMask);
15804     },
15805
15806     
15807     onBeforeLoad : function(){
15808         if(!this.disabled){
15809             this.el.mask(this.msg, this.msgCls);
15810         }
15811     },
15812
15813     
15814     show: function(){
15815         this.onBeforeLoad();
15816     },
15817
15818     
15819     hide: function(){
15820         this.onLoad();
15821     },
15822
15823     
15824     destroy : function(){
15825         if(this.store){
15826             this.store.un('beforeload', this.onBeforeLoad, this);
15827             this.store.un('load', this.onLoad, this);
15828             this.store.un('exception', this.onLoad, this);
15829         }else{
15830             var um = this.el.getUpdater();
15831             um.un('beforeupdate', this.onBeforeLoad, this);
15832             um.un('update', this.onLoad, this);
15833             um.un('failure', this.onLoad, this);
15834         }
15835     }
15836 };
15837 Ext.Slider = Ext.extend(Ext.BoxComponent, {
15838         
15839         
15840     vertical: false,
15841         
15842     minValue: 0,
15843         
15844     maxValue: 100,
15845     
15846     decimalPrecision: 0,
15847         
15848     keyIncrement: 1,
15849         
15850     increment: 0,
15851         
15852     clickRange: [5,15],
15853         
15854     clickToChange : true,
15855         
15856     animate: true,
15857
15858     
15859     dragging: false,
15860
15861     
15862     initComponent : function(){
15863         if(!Ext.isDefined(this.value)){
15864             this.value = this.minValue;
15865         }
15866         Ext.Slider.superclass.initComponent.call(this);
15867         this.keyIncrement = Math.max(this.increment, this.keyIncrement);
15868         this.addEvents(
15869             
15870                         'beforechange',
15871                         
15872                         'change',
15873                         
15874                         'changecomplete',
15875                         
15876                         'dragstart',
15877                         
15878                         'drag',
15879                         
15880                         'dragend'
15881                 );
15882
15883         if(this.vertical){
15884             Ext.apply(this, Ext.Slider.Vertical);
15885         }
15886     },
15887
15888         
15889     onRender : function(){
15890         this.autoEl = {
15891             cls: 'x-slider ' + (this.vertical ? 'x-slider-vert' : 'x-slider-horz'),
15892             cn:{cls:'x-slider-end',cn:{cls:'x-slider-inner',cn:[{cls:'x-slider-thumb'},{tag:'a', cls:'x-slider-focus', href:"#", tabIndex: '-1', hidefocus:'on'}]}}
15893         };
15894         Ext.Slider.superclass.onRender.apply(this, arguments);
15895         this.endEl = this.el.first();
15896         this.innerEl = this.endEl.first();
15897         this.thumb = this.innerEl.first();
15898         this.halfThumb = (this.vertical ? this.thumb.getHeight() : this.thumb.getWidth())/2;
15899         this.focusEl = this.thumb.next();
15900         this.initEvents();
15901     },
15902
15903         
15904     initEvents : function(){
15905         this.thumb.addClassOnOver('x-slider-thumb-over');
15906         this.mon(this.el, {
15907             scope: this,
15908             mousedown: this.onMouseDown,
15909             keydown: this.onKeyDown
15910         });
15911
15912         this.focusEl.swallowEvent("click", true);
15913
15914         this.tracker = new Ext.dd.DragTracker({
15915             onBeforeStart: this.onBeforeDragStart.createDelegate(this),
15916             onStart: this.onDragStart.createDelegate(this),
15917             onDrag: this.onDrag.createDelegate(this),
15918             onEnd: this.onDragEnd.createDelegate(this),
15919             tolerance: 3,
15920             autoStart: 300
15921         });
15922         this.tracker.initEl(this.thumb);
15923     },
15924
15925         
15926     onMouseDown : function(e){
15927         if(this.disabled){
15928             return;
15929         }
15930         if(this.clickToChange && e.target != this.thumb.dom){
15931             var local = this.innerEl.translatePoints(e.getXY());
15932             this.onClickChange(local);
15933         }
15934         this.focus();
15935     },
15936
15937         
15938     onClickChange : function(local){
15939         if(local.top > this.clickRange[0] && local.top < this.clickRange[1]){
15940             this.setValue(Ext.util.Format.round(this.reverseValue(local.left), this.decimalPrecision), undefined, true);
15941         }
15942     },
15943
15944         
15945     onKeyDown : function(e){
15946         if(this.disabled){e.preventDefault();return;}
15947         var k = e.getKey();
15948         switch(k){
15949             case e.UP:
15950             case e.RIGHT:
15951                 e.stopEvent();
15952                 if(e.ctrlKey){
15953                     this.setValue(this.maxValue, undefined, true);
15954                 }else{
15955                     this.setValue(this.value+this.keyIncrement, undefined, true);
15956                 }
15957             break;
15958             case e.DOWN:
15959             case e.LEFT:
15960                 e.stopEvent();
15961                 if(e.ctrlKey){
15962                     this.setValue(this.minValue, undefined, true);
15963                 }else{
15964                     this.setValue(this.value-this.keyIncrement, undefined, true);
15965                 }
15966             break;
15967             default:
15968                 e.preventDefault();
15969         }
15970     },
15971
15972         
15973     doSnap : function(value){
15974         if(!(this.increment && value)){
15975             return value;
15976         }
15977         var newValue = value, 
15978             inc = this.increment,
15979             m = value % inc;
15980         if(m != 0){
15981             newValue -= m;
15982             if(m * 2 > inc){
15983                 newValue += inc;
15984             }else if(m * 2 < -inc){
15985                 newValue -= inc;
15986             }
15987         }
15988         return newValue.constrain(this.minValue,  this.maxValue);
15989     },
15990
15991         
15992     afterRender : function(){
15993         Ext.Slider.superclass.afterRender.apply(this, arguments);
15994         if(this.value !== undefined){
15995             var v = this.normalizeValue(this.value);
15996             if(v !== this.value){
15997                 delete this.value;
15998                 this.setValue(v, false);
15999             }else{
16000                 this.moveThumb(this.translateValue(v), false);
16001             }
16002         }
16003     },
16004
16005         
16006     getRatio : function(){
16007         var w = this.innerEl.getWidth(),
16008             v = this.maxValue - this.minValue;
16009         return v == 0 ? w : (w/v);
16010     },
16011
16012         
16013     normalizeValue : function(v){
16014         v = this.doSnap(v);
16015         v = Ext.util.Format.round(v, this.decimalPrecision);
16016         v = v.constrain(this.minValue, this.maxValue);
16017         return v;
16018     },
16019
16020         
16021     setValue : function(v, animate, changeComplete){
16022         v = this.normalizeValue(v);
16023         if(v !== this.value && this.fireEvent('beforechange', this, v, this.value) !== false){
16024             this.value = v;
16025             this.moveThumb(this.translateValue(v), animate !== false);
16026             this.fireEvent('change', this, v);
16027             if(changeComplete){
16028                 this.fireEvent('changecomplete', this, v);
16029             }
16030         }
16031     },
16032
16033         
16034     translateValue : function(v){
16035         var ratio = this.getRatio();
16036         return (v * ratio) - (this.minValue * ratio) - this.halfThumb;
16037     },
16038
16039         reverseValue : function(pos){
16040         var ratio = this.getRatio();
16041         return (pos + this.halfThumb + (this.minValue * ratio)) / ratio;
16042     },
16043
16044         
16045     moveThumb: function(v, animate){
16046         if(!animate || this.animate === false){
16047             this.thumb.setLeft(v);
16048         }else{
16049             this.thumb.shift({left: v, stopFx: true, duration:.35});
16050         }
16051     },
16052
16053         
16054     focus : function(){
16055         this.focusEl.focus(10);
16056     },
16057
16058         
16059     onBeforeDragStart : function(e){
16060         return !this.disabled;
16061     },
16062
16063         
16064     onDragStart: function(e){
16065         this.thumb.addClass('x-slider-thumb-drag');
16066         this.dragging = true;
16067         this.dragStartValue = this.value;
16068         this.fireEvent('dragstart', this, e);
16069     },
16070
16071         
16072     onDrag: function(e){
16073         var pos = this.innerEl.translatePoints(this.tracker.getXY());
16074         this.setValue(Ext.util.Format.round(this.reverseValue(pos.left), this.decimalPrecision), false);
16075         this.fireEvent('drag', this, e);
16076     },
16077
16078         
16079     onDragEnd: function(e){
16080         this.thumb.removeClass('x-slider-thumb-drag');
16081         this.dragging = false;
16082         this.fireEvent('dragend', this, e);
16083         if(this.dragStartValue != this.value){
16084             this.fireEvent('changecomplete', this, this.value);
16085         }
16086     },
16087
16088         
16089     onResize : function(w, h){
16090         this.innerEl.setWidth(w - (this.el.getPadding('l') + this.endEl.getPadding('r')));
16091         this.syncThumb();
16092     },
16093     
16094     
16095     onDisable: function(){
16096         Ext.Slider.superclass.onDisable.call(this);
16097         this.thumb.addClass(this.disabledClass);
16098         if(Ext.isIE){
16099             
16100             
16101             var xy = this.thumb.getXY();
16102             this.thumb.hide();
16103             this.innerEl.addClass(this.disabledClass).dom.disabled = true;
16104             if (!this.thumbHolder){
16105                 this.thumbHolder = this.endEl.createChild({cls: 'x-slider-thumb ' + this.disabledClass});    
16106             }
16107             this.thumbHolder.show().setXY(xy);
16108         }
16109     },
16110     
16111     
16112     onEnable: function(){
16113         Ext.Slider.superclass.onEnable.call(this);
16114         this.thumb.removeClass(this.disabledClass);
16115         if(Ext.isIE){
16116             this.innerEl.removeClass(this.disabledClass).dom.disabled = false;
16117             if(this.thumbHolder){
16118                 this.thumbHolder.hide();
16119             }
16120             this.thumb.show();
16121             this.syncThumb();
16122         }
16123     },
16124     
16125     
16126     syncThumb : function(){
16127         if(this.rendered){
16128             this.moveThumb(this.translateValue(this.value));
16129         }
16130     },
16131
16132         
16133     getValue : function(){
16134         return this.value;
16135     },
16136     
16137     
16138     beforeDestroy : function(){
16139         Ext.destroyMembers(this, 'endEl', 'innerEl', 'thumb', 'halfThumb', 'focusEl', 'tracker', 'thumbHolder');
16140         Ext.Slider.superclass.beforeDestroy.call(this);
16141     }
16142 });
16143 Ext.reg('slider', Ext.Slider);
16144
16145
16146 Ext.Slider.Vertical = {
16147     onResize : function(w, h){
16148         this.innerEl.setHeight(h - (this.el.getPadding('t') + this.endEl.getPadding('b')));
16149         this.syncThumb();
16150     },
16151
16152     getRatio : function(){
16153         var h = this.innerEl.getHeight(),
16154             v = this.maxValue - this.minValue;
16155         return h/v;
16156     },
16157
16158     moveThumb: function(v, animate){
16159         if(!animate || this.animate === false){
16160             this.thumb.setBottom(v);
16161         }else{
16162             this.thumb.shift({bottom: v, stopFx: true, duration:.35});
16163         }
16164     },
16165
16166     onDrag: function(e){
16167         var pos = this.innerEl.translatePoints(this.tracker.getXY()),
16168             bottom = this.innerEl.getHeight()-pos.top;
16169         this.setValue(this.minValue + Ext.util.Format.round(bottom/this.getRatio(), this.decimalPrecision), false);
16170         this.fireEvent('drag', this, e);
16171     },
16172
16173     onClickChange : function(local){
16174         if(local.left > this.clickRange[0] && local.left < this.clickRange[1]){
16175             var bottom = this.innerEl.getHeight() - local.top;
16176             this.setValue(this.minValue + Ext.util.Format.round(bottom/this.getRatio(), this.decimalPrecision), undefined, true);
16177         }
16178     }
16179 };
16180 Ext.ProgressBar = Ext.extend(Ext.BoxComponent, {
16181    
16182     baseCls : 'x-progress',
16183     
16184     
16185     animate : false,
16186
16187     
16188     waitTimer : null,
16189
16190     
16191     initComponent : function(){
16192         Ext.ProgressBar.superclass.initComponent.call(this);
16193         this.addEvents(
16194             
16195             "update"
16196         );
16197     },
16198
16199     
16200     onRender : function(ct, position){
16201         var tpl = new Ext.Template(
16202             '<div class="{cls}-wrap">',
16203                 '<div class="{cls}-inner">',
16204                     '<div class="{cls}-bar">',
16205                         '<div class="{cls}-text">',
16206                             '<div>&#160;</div>',
16207                         '</div>',
16208                     '</div>',
16209                     '<div class="{cls}-text {cls}-text-back">',
16210                         '<div>&#160;</div>',
16211                     '</div>',
16212                 '</div>',
16213             '</div>'
16214         );
16215
16216         this.el = position ? tpl.insertBefore(position, {cls: this.baseCls}, true)
16217                 : tpl.append(ct, {cls: this.baseCls}, true);
16218                         
16219         if(this.id){
16220             this.el.dom.id = this.id;
16221         }
16222         var inner = this.el.dom.firstChild;
16223         this.progressBar = Ext.get(inner.firstChild);
16224
16225         if(this.textEl){
16226             
16227             this.textEl = Ext.get(this.textEl);
16228             delete this.textTopEl;
16229         }else{
16230             
16231             this.textTopEl = Ext.get(this.progressBar.dom.firstChild);
16232             var textBackEl = Ext.get(inner.childNodes[1]);
16233             this.textTopEl.setStyle("z-index", 99).addClass('x-hidden');
16234             this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, textBackEl.dom.firstChild]);
16235             this.textEl.setWidth(inner.offsetWidth);
16236         }
16237         this.progressBar.setHeight(inner.offsetHeight);
16238     },
16239     
16240     
16241     afterRender : function(){
16242         Ext.ProgressBar.superclass.afterRender.call(this);
16243         if(this.value){
16244             this.updateProgress(this.value, this.text);
16245         }else{
16246             this.updateText(this.text);
16247         }
16248     },
16249
16250     
16251     updateProgress : function(value, text, animate){
16252         this.value = value || 0;
16253         if(text){
16254             this.updateText(text);
16255         }
16256         if(this.rendered){
16257             var w = Math.floor(value*this.el.dom.firstChild.offsetWidth);
16258             this.progressBar.setWidth(w, animate === true || (animate !== false && this.animate));
16259             if(this.textTopEl){
16260                 
16261                 this.textTopEl.removeClass('x-hidden').setWidth(w);
16262             }
16263         }
16264         this.fireEvent('update', this, value, text);
16265         return this;
16266     },
16267
16268     
16269     wait : function(o){
16270         if(!this.waitTimer){
16271             var scope = this;
16272             o = o || {};
16273             this.updateText(o.text);
16274             this.waitTimer = Ext.TaskMgr.start({
16275                 run: function(i){
16276                     var inc = o.increment || 10;
16277                     i -= 1;
16278                     this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate);
16279                 },
16280                 interval: o.interval || 1000,
16281                 duration: o.duration,
16282                 onStop: function(){
16283                     if(o.fn){
16284                         o.fn.apply(o.scope || this);
16285                     }
16286                     this.reset();
16287                 },
16288                 scope: scope
16289             });
16290         }
16291         return this;
16292     },
16293
16294     
16295     isWaiting : function(){
16296         return this.waitTimer !== null;
16297     },
16298
16299     
16300     updateText : function(text){
16301         this.text = text || '&#160;';
16302         if(this.rendered){
16303             this.textEl.update(this.text);
16304         }
16305         return this;
16306     },
16307     
16308     
16309     syncProgressBar : function(){
16310         if(this.value){
16311             this.updateProgress(this.value, this.text);
16312         }
16313         return this;
16314     },
16315
16316     
16317     setSize : function(w, h){
16318         Ext.ProgressBar.superclass.setSize.call(this, w, h);
16319         if(this.textTopEl){
16320             var inner = this.el.dom.firstChild;
16321             this.textEl.setSize(inner.offsetWidth, inner.offsetHeight);
16322         }
16323         this.syncProgressBar();
16324         return this;
16325     },
16326
16327     
16328     reset : function(hide){
16329         this.updateProgress(0);
16330         if(this.textTopEl){
16331             this.textTopEl.addClass('x-hidden');
16332         }
16333         if(this.waitTimer){
16334             this.waitTimer.onStop = null; 
16335             Ext.TaskMgr.stop(this.waitTimer);
16336             this.waitTimer = null;
16337         }
16338         if(hide === true){
16339             this.hide();
16340         }
16341         return this;
16342     },
16343     
16344     onDestroy: function(){
16345         if(this.rendered){
16346             if(this.textEl.isComposite){
16347                 this.textEl.clear();
16348             }
16349             Ext.destroyMembers(this, 'textEl', 'progressBar', 'textTopEl');
16350         }
16351         Ext.ProgressBar.superclass.onDestroy.call(this);
16352     }
16353 });
16354 Ext.reg('progress', Ext.ProgressBar);
16355
16356 (function() {
16357
16358 var Event=Ext.EventManager;
16359 var Dom=Ext.lib.Dom;
16360
16361
16362 Ext.dd.DragDrop = function(id, sGroup, config) {
16363     if(id) {
16364         this.init(id, sGroup, config);
16365     }
16366 };
16367
16368 Ext.dd.DragDrop.prototype = {
16369
16370     
16371
16372     
16373     id: null,
16374
16375     
16376     config: null,
16377
16378     
16379     dragElId: null,
16380
16381     
16382     handleElId: null,
16383
16384     
16385     invalidHandleTypes: null,
16386
16387     
16388     invalidHandleIds: null,
16389
16390     
16391     invalidHandleClasses: null,
16392
16393     
16394     startPageX: 0,
16395
16396     
16397     startPageY: 0,
16398
16399     
16400     groups: null,
16401
16402     
16403     locked: false,
16404
16405     
16406     lock: function() { this.locked = true; },
16407
16408     
16409     moveOnly: false,
16410
16411     
16412     unlock: function() { this.locked = false; },
16413
16414     
16415     isTarget: true,
16416
16417     
16418     padding: null,
16419
16420     
16421     _domRef: null,
16422
16423     
16424     __ygDragDrop: true,
16425
16426     
16427     constrainX: false,
16428
16429     
16430     constrainY: false,
16431
16432     
16433     minX: 0,
16434
16435     
16436     maxX: 0,
16437
16438     
16439     minY: 0,
16440
16441     
16442     maxY: 0,
16443
16444     
16445     maintainOffset: false,
16446
16447     
16448     xTicks: null,
16449
16450     
16451     yTicks: null,
16452
16453     
16454     primaryButtonOnly: true,
16455
16456     
16457     available: false,
16458
16459     
16460     hasOuterHandles: false,
16461
16462     
16463     b4StartDrag: function(x, y) { },
16464
16465     
16466     startDrag: function(x, y) {  },
16467
16468     
16469     b4Drag: function(e) { },
16470
16471     
16472     onDrag: function(e) {  },
16473
16474     
16475     onDragEnter: function(e, id) {  },
16476
16477     
16478     b4DragOver: function(e) { },
16479
16480     
16481     onDragOver: function(e, id) {  },
16482
16483     
16484     b4DragOut: function(e) { },
16485
16486     
16487     onDragOut: function(e, id) {  },
16488
16489     
16490     b4DragDrop: function(e) { },
16491
16492     
16493     onDragDrop: function(e, id) {  },
16494
16495     
16496     onInvalidDrop: function(e) {  },
16497
16498     
16499     b4EndDrag: function(e) { },
16500
16501     
16502     endDrag: function(e) {  },
16503
16504     
16505     b4MouseDown: function(e) {  },
16506
16507     
16508     onMouseDown: function(e) {  },
16509
16510     
16511     onMouseUp: function(e) {  },
16512
16513     
16514     onAvailable: function () {
16515     },
16516
16517     
16518     defaultPadding : {left:0, right:0, top:0, bottom:0},
16519
16520     
16521     constrainTo : function(constrainTo, pad, inContent){
16522         if(Ext.isNumber(pad)){
16523             pad = {left: pad, right:pad, top:pad, bottom:pad};
16524         }
16525         pad = pad || this.defaultPadding;
16526         var b = Ext.get(this.getEl()).getBox(),
16527             ce = Ext.get(constrainTo),
16528             s = ce.getScroll(),
16529             c, 
16530             cd = ce.dom;
16531         if(cd == document.body){
16532             c = { x: s.left, y: s.top, width: Ext.lib.Dom.getViewWidth(), height: Ext.lib.Dom.getViewHeight()};
16533         }else{
16534             var xy = ce.getXY();
16535             c = {x : xy[0], y: xy[1], width: cd.clientWidth, height: cd.clientHeight};
16536         }
16537
16538
16539         var topSpace = b.y - c.y,
16540             leftSpace = b.x - c.x;
16541
16542         this.resetConstraints();
16543         this.setXConstraint(leftSpace - (pad.left||0), 
16544                 c.width - leftSpace - b.width - (pad.right||0), 
16545                                 this.xTickSize
16546         );
16547         this.setYConstraint(topSpace - (pad.top||0), 
16548                 c.height - topSpace - b.height - (pad.bottom||0), 
16549                                 this.yTickSize
16550         );
16551     },
16552
16553     
16554     getEl: function() {
16555         if (!this._domRef) {
16556             this._domRef = Ext.getDom(this.id);
16557         }
16558
16559         return this._domRef;
16560     },
16561
16562     
16563     getDragEl: function() {
16564         return Ext.getDom(this.dragElId);
16565     },
16566
16567     
16568     init: function(id, sGroup, config) {
16569         this.initTarget(id, sGroup, config);
16570         Event.on(this.id, "mousedown", this.handleMouseDown, this);
16571         
16572     },
16573
16574     
16575     initTarget: function(id, sGroup, config) {
16576
16577         
16578         this.config = config || {};
16579
16580         
16581         this.DDM = Ext.dd.DDM;
16582         
16583         this.groups = {};
16584
16585         
16586         
16587         if (typeof id !== "string") {
16588             id = Ext.id(id);
16589         }
16590
16591         
16592         this.id = id;
16593
16594         
16595         this.addToGroup((sGroup) ? sGroup : "default");
16596
16597         
16598         
16599         this.handleElId = id;
16600
16601         
16602         this.setDragElId(id);
16603
16604         
16605         this.invalidHandleTypes = { A: "A" };
16606         this.invalidHandleIds = {};
16607         this.invalidHandleClasses = [];
16608
16609         this.applyConfig();
16610
16611         this.handleOnAvailable();
16612     },
16613
16614     
16615     applyConfig: function() {
16616
16617         
16618         
16619         this.padding           = this.config.padding || [0, 0, 0, 0];
16620         this.isTarget          = (this.config.isTarget !== false);
16621         this.maintainOffset    = (this.config.maintainOffset);
16622         this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
16623
16624     },
16625
16626     
16627     handleOnAvailable: function() {
16628         this.available = true;
16629         this.resetConstraints();
16630         this.onAvailable();
16631     },
16632
16633      
16634     setPadding: function(iTop, iRight, iBot, iLeft) {
16635         
16636         if (!iRight && 0 !== iRight) {
16637             this.padding = [iTop, iTop, iTop, iTop];
16638         } else if (!iBot && 0 !== iBot) {
16639             this.padding = [iTop, iRight, iTop, iRight];
16640         } else {
16641             this.padding = [iTop, iRight, iBot, iLeft];
16642         }
16643     },
16644
16645     
16646     setInitPosition: function(diffX, diffY) {
16647         var el = this.getEl();
16648
16649         if (!this.DDM.verifyEl(el)) {
16650             return;
16651         }
16652
16653         var dx = diffX || 0;
16654         var dy = diffY || 0;
16655
16656         var p = Dom.getXY( el );
16657
16658         this.initPageX = p[0] - dx;
16659         this.initPageY = p[1] - dy;
16660
16661         this.lastPageX = p[0];
16662         this.lastPageY = p[1];
16663
16664
16665         this.setStartPosition(p);
16666     },
16667
16668     
16669     setStartPosition: function(pos) {
16670         var p = pos || Dom.getXY( this.getEl() );
16671         this.deltaSetXY = null;
16672
16673         this.startPageX = p[0];
16674         this.startPageY = p[1];
16675     },
16676
16677     
16678     addToGroup: function(sGroup) {
16679         this.groups[sGroup] = true;
16680         this.DDM.regDragDrop(this, sGroup);
16681     },
16682
16683     
16684     removeFromGroup: function(sGroup) {
16685         if (this.groups[sGroup]) {
16686             delete this.groups[sGroup];
16687         }
16688
16689         this.DDM.removeDDFromGroup(this, sGroup);
16690     },
16691
16692     
16693     setDragElId: function(id) {
16694         this.dragElId = id;
16695     },
16696
16697     
16698     setHandleElId: function(id) {
16699         if (typeof id !== "string") {
16700             id = Ext.id(id);
16701         }
16702         this.handleElId = id;
16703         this.DDM.regHandle(this.id, id);
16704     },
16705
16706     
16707     setOuterHandleElId: function(id) {
16708         if (typeof id !== "string") {
16709             id = Ext.id(id);
16710         }
16711         Event.on(id, "mousedown",
16712                 this.handleMouseDown, this);
16713         this.setHandleElId(id);
16714
16715         this.hasOuterHandles = true;
16716     },
16717
16718     
16719     unreg: function() {
16720         Event.un(this.id, "mousedown",
16721                 this.handleMouseDown);
16722         this._domRef = null;
16723         this.DDM._remove(this);
16724     },
16725
16726     destroy : function(){
16727         this.unreg();
16728     },
16729
16730     
16731     isLocked: function() {
16732         return (this.DDM.isLocked() || this.locked);
16733     },
16734
16735     
16736     handleMouseDown: function(e, oDD){
16737         if (this.primaryButtonOnly && e.button != 0) {
16738             return;
16739         }
16740
16741         if (this.isLocked()) {
16742             return;
16743         }
16744
16745         this.DDM.refreshCache(this.groups);
16746
16747         var pt = new Ext.lib.Point(Ext.lib.Event.getPageX(e), Ext.lib.Event.getPageY(e));
16748         if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) )  {
16749         } else {
16750             if (this.clickValidator(e)) {
16751
16752                 
16753                 this.setStartPosition();
16754
16755
16756                 this.b4MouseDown(e);
16757                 this.onMouseDown(e);
16758
16759                 this.DDM.handleMouseDown(e, this);
16760
16761                 this.DDM.stopEvent(e);
16762             } else {
16763
16764
16765             }
16766         }
16767     },
16768
16769     clickValidator: function(e) {
16770         var target = e.getTarget();
16771         return ( this.isValidHandleChild(target) &&
16772                     (this.id == this.handleElId ||
16773                         this.DDM.handleWasClicked(target, this.id)) );
16774     },
16775
16776     
16777     addInvalidHandleType: function(tagName) {
16778         var type = tagName.toUpperCase();
16779         this.invalidHandleTypes[type] = type;
16780     },
16781
16782     
16783     addInvalidHandleId: function(id) {
16784         if (typeof id !== "string") {
16785             id = Ext.id(id);
16786         }
16787         this.invalidHandleIds[id] = id;
16788     },
16789
16790     
16791     addInvalidHandleClass: function(cssClass) {
16792         this.invalidHandleClasses.push(cssClass);
16793     },
16794
16795     
16796     removeInvalidHandleType: function(tagName) {
16797         var type = tagName.toUpperCase();
16798         
16799         delete this.invalidHandleTypes[type];
16800     },
16801
16802     
16803     removeInvalidHandleId: function(id) {
16804         if (typeof id !== "string") {
16805             id = Ext.id(id);
16806         }
16807         delete this.invalidHandleIds[id];
16808     },
16809
16810     
16811     removeInvalidHandleClass: function(cssClass) {
16812         for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {
16813             if (this.invalidHandleClasses[i] == cssClass) {
16814                 delete this.invalidHandleClasses[i];
16815             }
16816         }
16817     },
16818
16819     
16820     isValidHandleChild: function(node) {
16821
16822         var valid = true;
16823         
16824         var nodeName;
16825         try {
16826             nodeName = node.nodeName.toUpperCase();
16827         } catch(e) {
16828             nodeName = node.nodeName;
16829         }
16830         valid = valid && !this.invalidHandleTypes[nodeName];
16831         valid = valid && !this.invalidHandleIds[node.id];
16832
16833         for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {
16834             valid = !Ext.fly(node).hasClass(this.invalidHandleClasses[i]);
16835         }
16836
16837
16838         return valid;
16839
16840     },
16841
16842     
16843     setXTicks: function(iStartX, iTickSize) {
16844         this.xTicks = [];
16845         this.xTickSize = iTickSize;
16846
16847         var tickMap = {};
16848
16849         for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
16850             if (!tickMap[i]) {
16851                 this.xTicks[this.xTicks.length] = i;
16852                 tickMap[i] = true;
16853             }
16854         }
16855
16856         for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
16857             if (!tickMap[i]) {
16858                 this.xTicks[this.xTicks.length] = i;
16859                 tickMap[i] = true;
16860             }
16861         }
16862
16863         this.xTicks.sort(this.DDM.numericSort) ;
16864     },
16865
16866     
16867     setYTicks: function(iStartY, iTickSize) {
16868         this.yTicks = [];
16869         this.yTickSize = iTickSize;
16870
16871         var tickMap = {};
16872
16873         for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
16874             if (!tickMap[i]) {
16875                 this.yTicks[this.yTicks.length] = i;
16876                 tickMap[i] = true;
16877             }
16878         }
16879
16880         for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
16881             if (!tickMap[i]) {
16882                 this.yTicks[this.yTicks.length] = i;
16883                 tickMap[i] = true;
16884             }
16885         }
16886
16887         this.yTicks.sort(this.DDM.numericSort) ;
16888     },
16889
16890     
16891     setXConstraint: function(iLeft, iRight, iTickSize) {
16892         this.leftConstraint = iLeft;
16893         this.rightConstraint = iRight;
16894
16895         this.minX = this.initPageX - iLeft;
16896         this.maxX = this.initPageX + iRight;
16897         if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
16898
16899         this.constrainX = true;
16900     },
16901
16902     
16903     clearConstraints: function() {
16904         this.constrainX = false;
16905         this.constrainY = false;
16906         this.clearTicks();
16907     },
16908
16909     
16910     clearTicks: function() {
16911         this.xTicks = null;
16912         this.yTicks = null;
16913         this.xTickSize = 0;
16914         this.yTickSize = 0;
16915     },
16916
16917     
16918     setYConstraint: function(iUp, iDown, iTickSize) {
16919         this.topConstraint = iUp;
16920         this.bottomConstraint = iDown;
16921
16922         this.minY = this.initPageY - iUp;
16923         this.maxY = this.initPageY + iDown;
16924         if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
16925
16926         this.constrainY = true;
16927
16928     },
16929
16930     
16931     resetConstraints: function() {
16932
16933
16934         
16935         if (this.initPageX || this.initPageX === 0) {
16936             
16937             var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
16938             var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
16939
16940             this.setInitPosition(dx, dy);
16941
16942         
16943         } else {
16944             this.setInitPosition();
16945         }
16946
16947         if (this.constrainX) {
16948             this.setXConstraint( this.leftConstraint,
16949                                  this.rightConstraint,
16950                                  this.xTickSize        );
16951         }
16952
16953         if (this.constrainY) {
16954             this.setYConstraint( this.topConstraint,
16955                                  this.bottomConstraint,
16956                                  this.yTickSize         );
16957         }
16958     },
16959
16960     
16961     getTick: function(val, tickArray) {
16962
16963         if (!tickArray) {
16964             
16965             
16966             return val;
16967         } else if (tickArray[0] >= val) {
16968             
16969             
16970             return tickArray[0];
16971         } else {
16972             for (var i=0, len=tickArray.length; i<len; ++i) {
16973                 var next = i + 1;
16974                 if (tickArray[next] && tickArray[next] >= val) {
16975                     var diff1 = val - tickArray[i];
16976                     var diff2 = tickArray[next] - val;
16977                     return (diff2 > diff1) ? tickArray[i] : tickArray[next];
16978                 }
16979             }
16980
16981             
16982             
16983             return tickArray[tickArray.length - 1];
16984         }
16985     },
16986
16987     
16988     toString: function() {
16989         return ("DragDrop " + this.id);
16990     }
16991
16992 };
16993
16994 })();
16995
16996
16997
16998
16999 if (!Ext.dd.DragDropMgr) {
17000
17001
17002 Ext.dd.DragDropMgr = function() {
17003
17004     var Event = Ext.EventManager;
17005
17006     return {
17007
17008         
17009         ids: {},
17010
17011         
17012         handleIds: {},
17013
17014         
17015         dragCurrent: null,
17016
17017         
17018         dragOvers: {},
17019
17020         
17021         deltaX: 0,
17022
17023         
17024         deltaY: 0,
17025
17026         
17027         preventDefault: true,
17028
17029         
17030         stopPropagation: true,
17031
17032         
17033         initialized: false,
17034
17035         
17036         locked: false,
17037
17038         
17039         init: function() {
17040             this.initialized = true;
17041         },
17042
17043         
17044         POINT: 0,
17045
17046         
17047         INTERSECT: 1,
17048
17049         
17050         mode: 0,
17051
17052         
17053         _execOnAll: function(sMethod, args) {
17054             for (var i in this.ids) {
17055                 for (var j in this.ids[i]) {
17056                     var oDD = this.ids[i][j];
17057                     if (! this.isTypeOfDD(oDD)) {
17058                         continue;
17059                     }
17060                     oDD[sMethod].apply(oDD, args);
17061                 }
17062             }
17063         },
17064
17065         
17066         _onLoad: function() {
17067
17068             this.init();
17069
17070
17071             Event.on(document, "mouseup",   this.handleMouseUp, this, true);
17072             Event.on(document, "mousemove", this.handleMouseMove, this, true);
17073             Event.on(window,   "unload",    this._onUnload, this, true);
17074             Event.on(window,   "resize",    this._onResize, this, true);
17075             
17076
17077         },
17078
17079         
17080         _onResize: function(e) {
17081             this._execOnAll("resetConstraints", []);
17082         },
17083
17084         
17085         lock: function() { this.locked = true; },
17086
17087         
17088         unlock: function() { this.locked = false; },
17089
17090         
17091         isLocked: function() { return this.locked; },
17092
17093         
17094         locationCache: {},
17095
17096         
17097         useCache: true,
17098
17099         
17100         clickPixelThresh: 3,
17101
17102         
17103         clickTimeThresh: 350,
17104
17105         
17106         dragThreshMet: false,
17107
17108         
17109         clickTimeout: null,
17110
17111         
17112         startX: 0,
17113
17114         
17115         startY: 0,
17116
17117         
17118         regDragDrop: function(oDD, sGroup) {
17119             if (!this.initialized) { this.init(); }
17120
17121             if (!this.ids[sGroup]) {
17122                 this.ids[sGroup] = {};
17123             }
17124             this.ids[sGroup][oDD.id] = oDD;
17125         },
17126
17127         
17128         removeDDFromGroup: function(oDD, sGroup) {
17129             if (!this.ids[sGroup]) {
17130                 this.ids[sGroup] = {};
17131             }
17132
17133             var obj = this.ids[sGroup];
17134             if (obj && obj[oDD.id]) {
17135                 delete obj[oDD.id];
17136             }
17137         },
17138
17139         
17140         _remove: function(oDD) {
17141             for (var g in oDD.groups) {
17142                 if (g && this.ids[g] && this.ids[g][oDD.id]) {
17143                     delete this.ids[g][oDD.id];
17144                 }
17145             }
17146             delete this.handleIds[oDD.id];
17147         },
17148
17149         
17150         regHandle: function(sDDId, sHandleId) {
17151             if (!this.handleIds[sDDId]) {
17152                 this.handleIds[sDDId] = {};
17153             }
17154             this.handleIds[sDDId][sHandleId] = sHandleId;
17155         },
17156
17157         
17158         isDragDrop: function(id) {
17159             return ( this.getDDById(id) ) ? true : false;
17160         },
17161
17162         
17163         getRelated: function(p_oDD, bTargetsOnly) {
17164             var oDDs = [];
17165             for (var i in p_oDD.groups) {
17166                 for (var j in this.ids[i]) {
17167                     var dd = this.ids[i][j];
17168                     if (! this.isTypeOfDD(dd)) {
17169                         continue;
17170                     }
17171                     if (!bTargetsOnly || dd.isTarget) {
17172                         oDDs[oDDs.length] = dd;
17173                     }
17174                 }
17175             }
17176
17177             return oDDs;
17178         },
17179
17180         
17181         isLegalTarget: function (oDD, oTargetDD) {
17182             var targets = this.getRelated(oDD, true);
17183             for (var i=0, len=targets.length;i<len;++i) {
17184                 if (targets[i].id == oTargetDD.id) {
17185                     return true;
17186                 }
17187             }
17188
17189             return false;
17190         },
17191
17192         
17193         isTypeOfDD: function (oDD) {
17194             return (oDD && oDD.__ygDragDrop);
17195         },
17196
17197         
17198         isHandle: function(sDDId, sHandleId) {
17199             return ( this.handleIds[sDDId] &&
17200                             this.handleIds[sDDId][sHandleId] );
17201         },
17202
17203         
17204         getDDById: function(id) {
17205             for (var i in this.ids) {
17206                 if (this.ids[i][id]) {
17207                     return this.ids[i][id];
17208                 }
17209             }
17210             return null;
17211         },
17212
17213         
17214         handleMouseDown: function(e, oDD) {
17215             if(Ext.QuickTips){
17216                 Ext.QuickTips.disable();
17217             }
17218             if(this.dragCurrent){
17219                 
17220                 
17221                 this.handleMouseUp(e);
17222             }
17223             
17224             this.currentTarget = e.getTarget();
17225             this.dragCurrent = oDD;
17226
17227             var el = oDD.getEl();
17228
17229             
17230             this.startX = e.getPageX();
17231             this.startY = e.getPageY();
17232
17233             this.deltaX = this.startX - el.offsetLeft;
17234             this.deltaY = this.startY - el.offsetTop;
17235
17236             this.dragThreshMet = false;
17237
17238             this.clickTimeout = setTimeout(
17239                     function() {
17240                         var DDM = Ext.dd.DDM;
17241                         DDM.startDrag(DDM.startX, DDM.startY);
17242                     },
17243                     this.clickTimeThresh );
17244         },
17245
17246         
17247         startDrag: function(x, y) {
17248             clearTimeout(this.clickTimeout);
17249             if (this.dragCurrent) {
17250                 this.dragCurrent.b4StartDrag(x, y);
17251                 this.dragCurrent.startDrag(x, y);
17252             }
17253             this.dragThreshMet = true;
17254         },
17255
17256         
17257         handleMouseUp: function(e) {
17258
17259             if(Ext.QuickTips){
17260                 Ext.QuickTips.enable();
17261             }
17262             if (! this.dragCurrent) {
17263                 return;
17264             }
17265
17266             clearTimeout(this.clickTimeout);
17267
17268             if (this.dragThreshMet) {
17269                 this.fireEvents(e, true);
17270             } else {
17271             }
17272
17273             this.stopDrag(e);
17274
17275             this.stopEvent(e);
17276         },
17277
17278         
17279         stopEvent: function(e){
17280             if(this.stopPropagation) {
17281                 e.stopPropagation();
17282             }
17283
17284             if (this.preventDefault) {
17285                 e.preventDefault();
17286             }
17287         },
17288
17289         
17290         stopDrag: function(e) {
17291             
17292             if (this.dragCurrent) {
17293                 if (this.dragThreshMet) {
17294                     this.dragCurrent.b4EndDrag(e);
17295                     this.dragCurrent.endDrag(e);
17296                 }
17297
17298                 this.dragCurrent.onMouseUp(e);
17299             }
17300
17301             this.dragCurrent = null;
17302             this.dragOvers = {};
17303         },
17304
17305         
17306         handleMouseMove: function(e) {
17307             if (! this.dragCurrent) {
17308                 return true;
17309             }
17310             
17311
17312             
17313             if (Ext.isIE && (e.button !== 0 && e.button !== 1 && e.button !== 2)) {
17314                 this.stopEvent(e);
17315                 return this.handleMouseUp(e);
17316             }
17317
17318             if (!this.dragThreshMet) {
17319                 var diffX = Math.abs(this.startX - e.getPageX());
17320                 var diffY = Math.abs(this.startY - e.getPageY());
17321                 if (diffX > this.clickPixelThresh ||
17322                             diffY > this.clickPixelThresh) {
17323                     this.startDrag(this.startX, this.startY);
17324                 }
17325             }
17326
17327             if (this.dragThreshMet) {
17328                 this.dragCurrent.b4Drag(e);
17329                 this.dragCurrent.onDrag(e);
17330                 if(!this.dragCurrent.moveOnly){
17331                     this.fireEvents(e, false);
17332                 }
17333             }
17334
17335             this.stopEvent(e);
17336
17337             return true;
17338         },
17339
17340         
17341         fireEvents: function(e, isDrop) {
17342             var dc = this.dragCurrent;
17343
17344             
17345             
17346             if (!dc || dc.isLocked()) {
17347                 return;
17348             }
17349
17350             var pt = e.getPoint();
17351
17352             
17353             var oldOvers = [];
17354
17355             var outEvts   = [];
17356             var overEvts  = [];
17357             var dropEvts  = [];
17358             var enterEvts = [];
17359
17360             
17361             
17362             for (var i in this.dragOvers) {
17363
17364                 var ddo = this.dragOvers[i];
17365
17366                 if (! this.isTypeOfDD(ddo)) {
17367                     continue;
17368                 }
17369
17370                 if (! this.isOverTarget(pt, ddo, this.mode)) {
17371                     outEvts.push( ddo );
17372                 }
17373
17374                 oldOvers[i] = true;
17375                 delete this.dragOvers[i];
17376             }
17377
17378             for (var sGroup in dc.groups) {
17379
17380                 if ("string" != typeof sGroup) {
17381                     continue;
17382                 }
17383
17384                 for (i in this.ids[sGroup]) {
17385                     var oDD = this.ids[sGroup][i];
17386                     if (! this.isTypeOfDD(oDD)) {
17387                         continue;
17388                     }
17389
17390                     if (oDD.isTarget && !oDD.isLocked() && ((oDD != dc) || (dc.ignoreSelf === false))) {
17391                         if (this.isOverTarget(pt, oDD, this.mode)) {
17392                             
17393                             if (isDrop) {
17394                                 dropEvts.push( oDD );
17395                             
17396                             } else {
17397
17398                                 
17399                                 if (!oldOvers[oDD.id]) {
17400                                     enterEvts.push( oDD );
17401                                 
17402                                 } else {
17403                                     overEvts.push( oDD );
17404                                 }
17405
17406                                 this.dragOvers[oDD.id] = oDD;
17407                             }
17408                         }
17409                     }
17410                 }
17411             }
17412
17413             if (this.mode) {
17414                 if (outEvts.length) {
17415                     dc.b4DragOut(e, outEvts);
17416                     dc.onDragOut(e, outEvts);
17417                 }
17418
17419                 if (enterEvts.length) {
17420                     dc.onDragEnter(e, enterEvts);
17421                 }
17422
17423                 if (overEvts.length) {
17424                     dc.b4DragOver(e, overEvts);
17425                     dc.onDragOver(e, overEvts);
17426                 }
17427
17428                 if (dropEvts.length) {
17429                     dc.b4DragDrop(e, dropEvts);
17430                     dc.onDragDrop(e, dropEvts);
17431                 }
17432
17433             } else {
17434                 
17435                 var len = 0;
17436                 for (i=0, len=outEvts.length; i<len; ++i) {
17437                     dc.b4DragOut(e, outEvts[i].id);
17438                     dc.onDragOut(e, outEvts[i].id);
17439                 }
17440
17441                 
17442                 for (i=0,len=enterEvts.length; i<len; ++i) {
17443                     
17444                     dc.onDragEnter(e, enterEvts[i].id);
17445                 }
17446
17447                 
17448                 for (i=0,len=overEvts.length; i<len; ++i) {
17449                     dc.b4DragOver(e, overEvts[i].id);
17450                     dc.onDragOver(e, overEvts[i].id);
17451                 }
17452
17453                 
17454                 for (i=0, len=dropEvts.length; i<len; ++i) {
17455                     dc.b4DragDrop(e, dropEvts[i].id);
17456                     dc.onDragDrop(e, dropEvts[i].id);
17457                 }
17458
17459             }
17460
17461             
17462             if (isDrop && !dropEvts.length) {
17463                 dc.onInvalidDrop(e);
17464             }
17465
17466         },
17467
17468         
17469         getBestMatch: function(dds) {
17470             var winner = null;
17471             
17472             
17473                
17474             
17475             
17476
17477             var len = dds.length;
17478
17479             if (len == 1) {
17480                 winner = dds[0];
17481             } else {
17482                 
17483                 for (var i=0; i<len; ++i) {
17484                     var dd = dds[i];
17485                     
17486                     
17487                     
17488                     if (dd.cursorIsOver) {
17489                         winner = dd;
17490                         break;
17491                     
17492                     } else {
17493                         if (!winner ||
17494                             winner.overlap.getArea() < dd.overlap.getArea()) {
17495                             winner = dd;
17496                         }
17497                     }
17498                 }
17499             }
17500
17501             return winner;
17502         },
17503
17504         
17505         refreshCache: function(groups) {
17506             for (var sGroup in groups) {
17507                 if ("string" != typeof sGroup) {
17508                     continue;
17509                 }
17510                 for (var i in this.ids[sGroup]) {
17511                     var oDD = this.ids[sGroup][i];
17512
17513                     if (this.isTypeOfDD(oDD)) {
17514                     
17515                         var loc = this.getLocation(oDD);
17516                         if (loc) {
17517                             this.locationCache[oDD.id] = loc;
17518                         } else {
17519                             delete this.locationCache[oDD.id];
17520                             
17521                             
17522                             
17523                         }
17524                     }
17525                 }
17526             }
17527         },
17528
17529         
17530         verifyEl: function(el) {
17531             if (el) {
17532                 var parent;
17533                 if(Ext.isIE){
17534                     try{
17535                         parent = el.offsetParent;
17536                     }catch(e){}
17537                 }else{
17538                     parent = el.offsetParent;
17539                 }
17540                 if (parent) {
17541                     return true;
17542                 }
17543             }
17544
17545             return false;
17546         },
17547
17548         
17549         getLocation: function(oDD) {
17550             if (! this.isTypeOfDD(oDD)) {
17551                 return null;
17552             }
17553
17554             var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
17555
17556             try {
17557                 pos= Ext.lib.Dom.getXY(el);
17558             } catch (e) { }
17559
17560             if (!pos) {
17561                 return null;
17562             }
17563
17564             x1 = pos[0];
17565             x2 = x1 + el.offsetWidth;
17566             y1 = pos[1];
17567             y2 = y1 + el.offsetHeight;
17568
17569             t = y1 - oDD.padding[0];
17570             r = x2 + oDD.padding[1];
17571             b = y2 + oDD.padding[2];
17572             l = x1 - oDD.padding[3];
17573
17574             return new Ext.lib.Region( t, r, b, l );
17575         },
17576
17577         
17578         isOverTarget: function(pt, oTarget, intersect) {
17579             
17580             var loc = this.locationCache[oTarget.id];
17581             if (!loc || !this.useCache) {
17582                 loc = this.getLocation(oTarget);
17583                 this.locationCache[oTarget.id] = loc;
17584
17585             }
17586
17587             if (!loc) {
17588                 return false;
17589             }
17590
17591             oTarget.cursorIsOver = loc.contains( pt );
17592
17593             
17594             
17595             
17596             
17597             
17598             var dc = this.dragCurrent;
17599             if (!dc || !dc.getTargetCoord ||
17600                     (!intersect && !dc.constrainX && !dc.constrainY)) {
17601                 return oTarget.cursorIsOver;
17602             }
17603
17604             oTarget.overlap = null;
17605
17606             
17607             
17608             
17609             
17610             var pos = dc.getTargetCoord(pt.x, pt.y);
17611
17612             var el = dc.getDragEl();
17613             var curRegion = new Ext.lib.Region( pos.y,
17614                                                    pos.x + el.offsetWidth,
17615                                                    pos.y + el.offsetHeight,
17616                                                    pos.x );
17617
17618             var overlap = curRegion.intersect(loc);
17619
17620             if (overlap) {
17621                 oTarget.overlap = overlap;
17622                 return (intersect) ? true : oTarget.cursorIsOver;
17623             } else {
17624                 return false;
17625             }
17626         },
17627
17628         
17629         _onUnload: function(e, me) {
17630             Ext.dd.DragDropMgr.unregAll();
17631         },
17632
17633         
17634         unregAll: function() {
17635
17636             if (this.dragCurrent) {
17637                 this.stopDrag();
17638                 this.dragCurrent = null;
17639             }
17640
17641             this._execOnAll("unreg", []);
17642
17643             for (var i in this.elementCache) {
17644                 delete this.elementCache[i];
17645             }
17646
17647             this.elementCache = {};
17648             this.ids = {};
17649         },
17650
17651         
17652         elementCache: {},
17653
17654         
17655         getElWrapper: function(id) {
17656             var oWrapper = this.elementCache[id];
17657             if (!oWrapper || !oWrapper.el) {
17658                 oWrapper = this.elementCache[id] =
17659                     new this.ElementWrapper(Ext.getDom(id));
17660             }
17661             return oWrapper;
17662         },
17663
17664         
17665         getElement: function(id) {
17666             return Ext.getDom(id);
17667         },
17668
17669         
17670         getCss: function(id) {
17671             var el = Ext.getDom(id);
17672             return (el) ? el.style : null;
17673         },
17674
17675         
17676         ElementWrapper: function(el) {
17677                 
17678                 this.el = el || null;
17679                 
17680                 this.id = this.el && el.id;
17681                 
17682                 this.css = this.el && el.style;
17683             },
17684
17685         
17686         getPosX: function(el) {
17687             return Ext.lib.Dom.getX(el);
17688         },
17689
17690         
17691         getPosY: function(el) {
17692             return Ext.lib.Dom.getY(el);
17693         },
17694
17695         
17696         swapNode: function(n1, n2) {
17697             if (n1.swapNode) {
17698                 n1.swapNode(n2);
17699             } else {
17700                 var p = n2.parentNode;
17701                 var s = n2.nextSibling;
17702
17703                 if (s == n1) {
17704                     p.insertBefore(n1, n2);
17705                 } else if (n2 == n1.nextSibling) {
17706                     p.insertBefore(n2, n1);
17707                 } else {
17708                     n1.parentNode.replaceChild(n2, n1);
17709                     p.insertBefore(n1, s);
17710                 }
17711             }
17712         },
17713
17714         
17715         getScroll: function () {
17716             var t, l, dde=document.documentElement, db=document.body;
17717             if (dde && (dde.scrollTop || dde.scrollLeft)) {
17718                 t = dde.scrollTop;
17719                 l = dde.scrollLeft;
17720             } else if (db) {
17721                 t = db.scrollTop;
17722                 l = db.scrollLeft;
17723             } else {
17724
17725             }
17726             return { top: t, left: l };
17727         },
17728
17729         
17730         getStyle: function(el, styleProp) {
17731             return Ext.fly(el).getStyle(styleProp);
17732         },
17733
17734         
17735         getScrollTop: function () { return this.getScroll().top; },
17736
17737         
17738         getScrollLeft: function () { return this.getScroll().left; },
17739
17740         
17741         moveToEl: function (moveEl, targetEl) {
17742             var aCoord = Ext.lib.Dom.getXY(targetEl);
17743             Ext.lib.Dom.setXY(moveEl, aCoord);
17744         },
17745
17746         
17747         numericSort: function(a, b) { return (a - b); },
17748
17749         
17750         _timeoutCount: 0,
17751
17752         
17753         _addListeners: function() {
17754             var DDM = Ext.dd.DDM;
17755             if ( Ext.lib.Event && document ) {
17756                 DDM._onLoad();
17757             } else {
17758                 if (DDM._timeoutCount > 2000) {
17759                 } else {
17760                     setTimeout(DDM._addListeners, 10);
17761                     if (document && document.body) {
17762                         DDM._timeoutCount += 1;
17763                     }
17764                 }
17765             }
17766         },
17767
17768         
17769         handleWasClicked: function(node, id) {
17770             if (this.isHandle(id, node.id)) {
17771                 return true;
17772             } else {
17773                 
17774                 var p = node.parentNode;
17775
17776                 while (p) {
17777                     if (this.isHandle(id, p.id)) {
17778                         return true;
17779                     } else {
17780                         p = p.parentNode;
17781                     }
17782                 }
17783             }
17784
17785             return false;
17786         }
17787
17788     };
17789
17790 }();
17791
17792
17793 Ext.dd.DDM = Ext.dd.DragDropMgr;
17794 Ext.dd.DDM._addListeners();
17795
17796 }
17797
17798
17799 Ext.dd.DD = function(id, sGroup, config) {
17800     if (id) {
17801         this.init(id, sGroup, config);
17802     }
17803 };
17804
17805 Ext.extend(Ext.dd.DD, Ext.dd.DragDrop, {
17806
17807     
17808     scroll: true,
17809
17810     
17811     autoOffset: function(iPageX, iPageY) {
17812         var x = iPageX - this.startPageX;
17813         var y = iPageY - this.startPageY;
17814         this.setDelta(x, y);
17815     },
17816
17817     
17818     setDelta: function(iDeltaX, iDeltaY) {
17819         this.deltaX = iDeltaX;
17820         this.deltaY = iDeltaY;
17821     },
17822
17823     
17824     setDragElPos: function(iPageX, iPageY) {
17825         
17826         
17827
17828         var el = this.getDragEl();
17829         this.alignElWithMouse(el, iPageX, iPageY);
17830     },
17831
17832     
17833     alignElWithMouse: function(el, iPageX, iPageY) {
17834         var oCoord = this.getTargetCoord(iPageX, iPageY);
17835         var fly = el.dom ? el : Ext.fly(el, '_dd');
17836         if (!this.deltaSetXY) {
17837             var aCoord = [oCoord.x, oCoord.y];
17838             fly.setXY(aCoord);
17839             var newLeft = fly.getLeft(true);
17840             var newTop  = fly.getTop(true);
17841             this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ];
17842         } else {
17843             fly.setLeftTop(oCoord.x + this.deltaSetXY[0], oCoord.y + this.deltaSetXY[1]);
17844         }
17845
17846         this.cachePosition(oCoord.x, oCoord.y);
17847         this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
17848         return oCoord;
17849     },
17850
17851     
17852     cachePosition: function(iPageX, iPageY) {
17853         if (iPageX) {
17854             this.lastPageX = iPageX;
17855             this.lastPageY = iPageY;
17856         } else {
17857             var aCoord = Ext.lib.Dom.getXY(this.getEl());
17858             this.lastPageX = aCoord[0];
17859             this.lastPageY = aCoord[1];
17860         }
17861     },
17862
17863     
17864     autoScroll: function(x, y, h, w) {
17865
17866         if (this.scroll) {
17867             
17868             var clientH = Ext.lib.Dom.getViewHeight();
17869
17870             
17871             var clientW = Ext.lib.Dom.getViewWidth();
17872
17873             
17874             var st = this.DDM.getScrollTop();
17875
17876             
17877             var sl = this.DDM.getScrollLeft();
17878
17879             
17880             var bot = h + y;
17881
17882             
17883             var right = w + x;
17884
17885             
17886             
17887             
17888             var toBot = (clientH + st - y - this.deltaY);
17889
17890             
17891             var toRight = (clientW + sl - x - this.deltaX);
17892
17893
17894             
17895             
17896             var thresh = 40;
17897
17898             
17899             
17900             
17901             var scrAmt = (document.all) ? 80 : 30;
17902
17903             
17904             
17905             if ( bot > clientH && toBot < thresh ) {
17906                 window.scrollTo(sl, st + scrAmt);
17907             }
17908
17909             
17910             
17911             if ( y < st && st > 0 && y - st < thresh ) {
17912                 window.scrollTo(sl, st - scrAmt);
17913             }
17914
17915             
17916             
17917             if ( right > clientW && toRight < thresh ) {
17918                 window.scrollTo(sl + scrAmt, st);
17919             }
17920
17921             
17922             
17923             if ( x < sl && sl > 0 && x - sl < thresh ) {
17924                 window.scrollTo(sl - scrAmt, st);
17925             }
17926         }
17927     },
17928
17929     
17930     getTargetCoord: function(iPageX, iPageY) {
17931
17932
17933         var x = iPageX - this.deltaX;
17934         var y = iPageY - this.deltaY;
17935
17936         if (this.constrainX) {
17937             if (x < this.minX) { x = this.minX; }
17938             if (x > this.maxX) { x = this.maxX; }
17939         }
17940
17941         if (this.constrainY) {
17942             if (y < this.minY) { y = this.minY; }
17943             if (y > this.maxY) { y = this.maxY; }
17944         }
17945
17946         x = this.getTick(x, this.xTicks);
17947         y = this.getTick(y, this.yTicks);
17948
17949
17950         return {x:x, y:y};
17951     },
17952
17953     
17954     applyConfig: function() {
17955         Ext.dd.DD.superclass.applyConfig.call(this);
17956         this.scroll = (this.config.scroll !== false);
17957     },
17958
17959     
17960     b4MouseDown: function(e) {
17961         
17962         this.autoOffset(e.getPageX(),
17963                             e.getPageY());
17964     },
17965
17966     
17967     b4Drag: function(e) {
17968         this.setDragElPos(e.getPageX(),
17969                             e.getPageY());
17970     },
17971
17972     toString: function() {
17973         return ("DD " + this.id);
17974     }
17975
17976     
17977     
17978     
17979     
17980
17981 });
17982
17983 Ext.dd.DDProxy = function(id, sGroup, config) {
17984     if (id) {
17985         this.init(id, sGroup, config);
17986         this.initFrame();
17987     }
17988 };
17989
17990
17991 Ext.dd.DDProxy.dragElId = "ygddfdiv";
17992
17993 Ext.extend(Ext.dd.DDProxy, Ext.dd.DD, {
17994
17995     
17996     resizeFrame: true,
17997
17998     
17999     centerFrame: false,
18000
18001     
18002     createFrame: function() {
18003         var self = this;
18004         var body = document.body;
18005
18006         if (!body || !body.firstChild) {
18007             setTimeout( function() { self.createFrame(); }, 50 );
18008             return;
18009         }
18010
18011         var div = this.getDragEl();
18012
18013         if (!div) {
18014             div    = document.createElement("div");
18015             div.id = this.dragElId;
18016             var s  = div.style;
18017
18018             s.position   = "absolute";
18019             s.visibility = "hidden";
18020             s.cursor     = "move";
18021             s.border     = "2px solid #aaa";
18022             s.zIndex     = 999;
18023
18024             
18025             
18026             
18027             body.insertBefore(div, body.firstChild);
18028         }
18029     },
18030
18031     
18032     initFrame: function() {
18033         this.createFrame();
18034     },
18035
18036     applyConfig: function() {
18037         Ext.dd.DDProxy.superclass.applyConfig.call(this);
18038
18039         this.resizeFrame = (this.config.resizeFrame !== false);
18040         this.centerFrame = (this.config.centerFrame);
18041         this.setDragElId(this.config.dragElId || Ext.dd.DDProxy.dragElId);
18042     },
18043
18044     
18045     showFrame: function(iPageX, iPageY) {
18046         var el = this.getEl();
18047         var dragEl = this.getDragEl();
18048         var s = dragEl.style;
18049
18050         this._resizeProxy();
18051
18052         if (this.centerFrame) {
18053             this.setDelta( Math.round(parseInt(s.width,  10)/2),
18054                            Math.round(parseInt(s.height, 10)/2) );
18055         }
18056
18057         this.setDragElPos(iPageX, iPageY);
18058
18059         Ext.fly(dragEl).show();
18060     },
18061
18062     
18063     _resizeProxy: function() {
18064         if (this.resizeFrame) {
18065             var el = this.getEl();
18066             Ext.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);
18067         }
18068     },
18069
18070     
18071     b4MouseDown: function(e) {
18072         var x = e.getPageX();
18073         var y = e.getPageY();
18074         this.autoOffset(x, y);
18075         this.setDragElPos(x, y);
18076     },
18077
18078     
18079     b4StartDrag: function(x, y) {
18080         
18081         this.showFrame(x, y);
18082     },
18083
18084     
18085     b4EndDrag: function(e) {
18086         Ext.fly(this.getDragEl()).hide();
18087     },
18088
18089     
18090     
18091     
18092     endDrag: function(e) {
18093
18094         var lel = this.getEl();
18095         var del = this.getDragEl();
18096
18097         
18098         del.style.visibility = "";
18099
18100         this.beforeMove();
18101         
18102         
18103         lel.style.visibility = "hidden";
18104         Ext.dd.DDM.moveToEl(lel, del);
18105         del.style.visibility = "hidden";
18106         lel.style.visibility = "";
18107
18108         this.afterDrag();
18109     },
18110
18111     beforeMove : function(){
18112
18113     },
18114
18115     afterDrag : function(){
18116
18117     },
18118
18119     toString: function() {
18120         return ("DDProxy " + this.id);
18121     }
18122
18123 });
18124
18125 Ext.dd.DDTarget = function(id, sGroup, config) {
18126     if (id) {
18127         this.initTarget(id, sGroup, config);
18128     }
18129 };
18130
18131
18132 Ext.extend(Ext.dd.DDTarget, Ext.dd.DragDrop, {
18133     
18134     getDragEl: Ext.emptyFn,
18135     
18136     isValidHandleChild: Ext.emptyFn,
18137     
18138     startDrag: Ext.emptyFn,
18139     
18140     endDrag: Ext.emptyFn,
18141     
18142     onDrag: Ext.emptyFn,
18143     
18144     onDragDrop: Ext.emptyFn,
18145     
18146     onDragEnter: Ext.emptyFn,
18147     
18148     onDragOut: Ext.emptyFn,
18149     
18150     onDragOver: Ext.emptyFn,
18151     
18152     onInvalidDrop: Ext.emptyFn,
18153     
18154     onMouseDown: Ext.emptyFn,
18155     
18156     onMouseUp: Ext.emptyFn,
18157     
18158     setXConstraint: Ext.emptyFn,
18159     
18160     setYConstraint: Ext.emptyFn,
18161     
18162     resetConstraints: Ext.emptyFn,
18163     
18164     clearConstraints: Ext.emptyFn,
18165     
18166     clearTicks: Ext.emptyFn,
18167     
18168     setInitPosition: Ext.emptyFn,
18169     
18170     setDragElId: Ext.emptyFn,
18171     
18172     setHandleElId: Ext.emptyFn,
18173     
18174     setOuterHandleElId: Ext.emptyFn,
18175     
18176     addInvalidHandleClass: Ext.emptyFn,
18177     
18178     addInvalidHandleId: Ext.emptyFn,
18179     
18180     addInvalidHandleType: Ext.emptyFn,
18181     
18182     removeInvalidHandleClass: Ext.emptyFn,
18183     
18184     removeInvalidHandleId: Ext.emptyFn,
18185     
18186     removeInvalidHandleType: Ext.emptyFn,
18187
18188     toString: function() {
18189         return ("DDTarget " + this.id);
18190     }
18191 });
18192 Ext.dd.DragTracker = Ext.extend(Ext.util.Observable,  {
18193         
18194     active: false,
18195         
18196     tolerance: 5,
18197         
18198     autoStart: false,
18199     
18200     constructor : function(config){
18201         Ext.apply(this, config);
18202             this.addEvents(
18203                 
18204                 'mousedown',
18205                 
18206                 'mouseup',
18207                 
18208                 'mousemove',
18209                 
18210                 'dragstart',
18211                 
18212                 'dragend',
18213                 
18214                 'drag'
18215             );
18216         
18217             this.dragRegion = new Ext.lib.Region(0,0,0,0);
18218         
18219             if(this.el){
18220                 this.initEl(this.el);
18221             }
18222         Ext.dd.DragTracker.superclass.constructor.call(this, config);
18223     },
18224
18225     initEl: function(el){
18226         this.el = Ext.get(el);
18227         el.on('mousedown', this.onMouseDown, this,
18228                 this.delegate ? {delegate: this.delegate} : undefined);
18229     },
18230
18231     destroy : function(){
18232         this.el.un('mousedown', this.onMouseDown, this);
18233     },
18234
18235     onMouseDown: function(e, target){
18236         if(this.fireEvent('mousedown', this, e) !== false && this.onBeforeStart(e) !== false){
18237             this.startXY = this.lastXY = e.getXY();
18238             this.dragTarget = this.delegate ? target : this.el.dom;
18239             if(this.preventDefault !== false){
18240                 e.preventDefault();
18241             }
18242             var doc = Ext.getDoc();
18243             doc.on('mouseup', this.onMouseUp, this);
18244             doc.on('mousemove', this.onMouseMove, this);
18245             doc.on('selectstart', this.stopSelect, this);
18246             if(this.autoStart){
18247                 this.timer = this.triggerStart.defer(this.autoStart === true ? 1000 : this.autoStart, this);
18248             }
18249         }
18250     },
18251
18252     onMouseMove: function(e, target){
18253         
18254         if(this.active && Ext.isIE && !e.browserEvent.button){
18255             e.preventDefault();
18256             this.onMouseUp(e);
18257             return;
18258         }
18259
18260         e.preventDefault();
18261         var xy = e.getXY(), s = this.startXY;
18262         this.lastXY = xy;
18263         if(!this.active){
18264             if(Math.abs(s[0]-xy[0]) > this.tolerance || Math.abs(s[1]-xy[1]) > this.tolerance){
18265                 this.triggerStart();
18266             }else{
18267                 return;
18268             }
18269         }
18270         this.fireEvent('mousemove', this, e);
18271         this.onDrag(e);
18272         this.fireEvent('drag', this, e);
18273     },
18274
18275     onMouseUp: function(e){
18276         var doc = Ext.getDoc();
18277         doc.un('mousemove', this.onMouseMove, this);
18278         doc.un('mouseup', this.onMouseUp, this);
18279         doc.un('selectstart', this.stopSelect, this);
18280         e.preventDefault();
18281         this.clearStart();
18282         var wasActive = this.active;
18283         this.active = false;
18284         delete this.elRegion;
18285         this.fireEvent('mouseup', this, e);
18286         if(wasActive){
18287             this.onEnd(e);
18288             this.fireEvent('dragend', this, e);
18289         }
18290     },
18291
18292     triggerStart: function(isTimer){
18293         this.clearStart();
18294         this.active = true;
18295         this.onStart(this.startXY);
18296         this.fireEvent('dragstart', this, this.startXY);
18297     },
18298
18299     clearStart : function(){
18300         if(this.timer){
18301             clearTimeout(this.timer);
18302             delete this.timer;
18303         }
18304     },
18305
18306     stopSelect : function(e){
18307         e.stopEvent();
18308         return false;
18309     },
18310
18311     onBeforeStart : function(e){
18312
18313     },
18314
18315     onStart : function(xy){
18316
18317     },
18318
18319     onDrag : function(e){
18320
18321     },
18322
18323     onEnd : function(e){
18324
18325     },
18326
18327     getDragTarget : function(){
18328         return this.dragTarget;
18329     },
18330
18331     getDragCt : function(){
18332         return this.el;
18333     },
18334
18335     getXY : function(constrain){
18336         return constrain ?
18337                this.constrainModes[constrain].call(this, this.lastXY) : this.lastXY;
18338     },
18339
18340     getOffset : function(constrain){
18341         var xy = this.getXY(constrain);
18342         var s = this.startXY;
18343         return [s[0]-xy[0], s[1]-xy[1]];
18344     },
18345
18346     constrainModes: {
18347         'point' : function(xy){
18348
18349             if(!this.elRegion){
18350                 this.elRegion = this.getDragCt().getRegion();
18351             }
18352
18353             var dr = this.dragRegion;
18354
18355             dr.left = xy[0];
18356             dr.top = xy[1];
18357             dr.right = xy[0];
18358             dr.bottom = xy[1];
18359
18360             dr.constrainTo(this.elRegion);
18361
18362             return [dr.left, dr.top];
18363         }
18364     }
18365 });
18366 Ext.dd.ScrollManager = function(){
18367     var ddm = Ext.dd.DragDropMgr;
18368     var els = {};
18369     var dragEl = null;
18370     var proc = {};
18371     
18372     var onStop = function(e){
18373         dragEl = null;
18374         clearProc();
18375     };
18376     
18377     var triggerRefresh = function(){
18378         if(ddm.dragCurrent){
18379              ddm.refreshCache(ddm.dragCurrent.groups);
18380         }
18381     };
18382     
18383     var doScroll = function(){
18384         if(ddm.dragCurrent){
18385             var dds = Ext.dd.ScrollManager;
18386             var inc = proc.el.ddScrollConfig ?
18387                       proc.el.ddScrollConfig.increment : dds.increment;
18388             if(!dds.animate){
18389                 if(proc.el.scroll(proc.dir, inc)){
18390                     triggerRefresh();
18391                 }
18392             }else{
18393                 proc.el.scroll(proc.dir, inc, true, dds.animDuration, triggerRefresh);
18394             }
18395         }
18396     };
18397     
18398     var clearProc = function(){
18399         if(proc.id){
18400             clearInterval(proc.id);
18401         }
18402         proc.id = 0;
18403         proc.el = null;
18404         proc.dir = "";
18405     };
18406     
18407     var startProc = function(el, dir){
18408         clearProc();
18409         proc.el = el;
18410         proc.dir = dir;
18411         var freq = (el.ddScrollConfig && el.ddScrollConfig.frequency) ? 
18412                 el.ddScrollConfig.frequency : Ext.dd.ScrollManager.frequency;
18413         proc.id = setInterval(doScroll, freq);
18414     };
18415     
18416     var onFire = function(e, isDrop){
18417         if(isDrop || !ddm.dragCurrent){ return; }
18418         var dds = Ext.dd.ScrollManager;
18419         if(!dragEl || dragEl != ddm.dragCurrent){
18420             dragEl = ddm.dragCurrent;
18421             
18422             dds.refreshCache();
18423         }
18424         
18425         var xy = Ext.lib.Event.getXY(e);
18426         var pt = new Ext.lib.Point(xy[0], xy[1]);
18427         for(var id in els){
18428             var el = els[id], r = el._region;
18429             var c = el.ddScrollConfig ? el.ddScrollConfig : dds;
18430             if(r && r.contains(pt) && el.isScrollable()){
18431                 if(r.bottom - pt.y <= c.vthresh){
18432                     if(proc.el != el){
18433                         startProc(el, "down");
18434                     }
18435                     return;
18436                 }else if(r.right - pt.x <= c.hthresh){
18437                     if(proc.el != el){
18438                         startProc(el, "left");
18439                     }
18440                     return;
18441                 }else if(pt.y - r.top <= c.vthresh){
18442                     if(proc.el != el){
18443                         startProc(el, "up");
18444                     }
18445                     return;
18446                 }else if(pt.x - r.left <= c.hthresh){
18447                     if(proc.el != el){
18448                         startProc(el, "right");
18449                     }
18450                     return;
18451                 }
18452             }
18453         }
18454         clearProc();
18455     };
18456     
18457     ddm.fireEvents = ddm.fireEvents.createSequence(onFire, ddm);
18458     ddm.stopDrag = ddm.stopDrag.createSequence(onStop, ddm);
18459     
18460     return {
18461         
18462         register : function(el){
18463             if(Ext.isArray(el)){
18464                 for(var i = 0, len = el.length; i < len; i++) {
18465                         this.register(el[i]);
18466                 }
18467             }else{
18468                 el = Ext.get(el);
18469                 els[el.id] = el;
18470             }
18471         },
18472         
18473         
18474         unregister : function(el){
18475             if(Ext.isArray(el)){
18476                 for(var i = 0, len = el.length; i < len; i++) {
18477                         this.unregister(el[i]);
18478                 }
18479             }else{
18480                 el = Ext.get(el);
18481                 delete els[el.id];
18482             }
18483         },
18484         
18485         
18486         vthresh : 25,
18487         
18488         hthresh : 25,
18489
18490         
18491         increment : 100,
18492         
18493         
18494         frequency : 500,
18495         
18496         
18497         animate: true,
18498         
18499         
18500         animDuration: .4,
18501         
18502         
18503         refreshCache : function(){
18504             for(var id in els){
18505                 if(typeof els[id] == 'object'){ 
18506                     els[id]._region = els[id].getRegion();
18507                 }
18508             }
18509         }
18510     };
18511 }();
18512 Ext.dd.Registry = function(){
18513     var elements = {}; 
18514     var handles = {}; 
18515     var autoIdSeed = 0;
18516
18517     var getId = function(el, autogen){
18518         if(typeof el == "string"){
18519             return el;
18520         }
18521         var id = el.id;
18522         if(!id && autogen !== false){
18523             id = "extdd-" + (++autoIdSeed);
18524             el.id = id;
18525         }
18526         return id;
18527     };
18528     
18529     return {
18530     
18531         register : function(el, data){
18532             data = data || {};
18533             if(typeof el == "string"){
18534                 el = document.getElementById(el);
18535             }
18536             data.ddel = el;
18537             elements[getId(el)] = data;
18538             if(data.isHandle !== false){
18539                 handles[data.ddel.id] = data;
18540             }
18541             if(data.handles){
18542                 var hs = data.handles;
18543                 for(var i = 0, len = hs.length; i < len; i++){
18544                         handles[getId(hs[i])] = data;
18545                 }
18546             }
18547         },
18548
18549     
18550         unregister : function(el){
18551             var id = getId(el, false);
18552             var data = elements[id];
18553             if(data){
18554                 delete elements[id];
18555                 if(data.handles){
18556                     var hs = data.handles;
18557                     for(var i = 0, len = hs.length; i < len; i++){
18558                         delete handles[getId(hs[i], false)];
18559                     }
18560                 }
18561             }
18562         },
18563
18564     
18565         getHandle : function(id){
18566             if(typeof id != "string"){ 
18567                 id = id.id;
18568             }
18569             return handles[id];
18570         },
18571
18572     
18573         getHandleFromEvent : function(e){
18574             var t = Ext.lib.Event.getTarget(e);
18575             return t ? handles[t.id] : null;
18576         },
18577
18578     
18579         getTarget : function(id){
18580             if(typeof id != "string"){ 
18581                 id = id.id;
18582             }
18583             return elements[id];
18584         },
18585
18586     
18587         getTargetFromEvent : function(e){
18588             var t = Ext.lib.Event.getTarget(e);
18589             return t ? elements[t.id] || handles[t.id] : null;
18590         }
18591     };
18592 }();
18593 Ext.dd.StatusProxy = function(config){
18594     Ext.apply(this, config);
18595     this.id = this.id || Ext.id();
18596     this.el = new Ext.Layer({
18597         dh: {
18598             id: this.id, tag: "div", cls: "x-dd-drag-proxy "+this.dropNotAllowed, children: [
18599                 {tag: "div", cls: "x-dd-drop-icon"},
18600                 {tag: "div", cls: "x-dd-drag-ghost"}
18601             ]
18602         }, 
18603         shadow: !config || config.shadow !== false
18604     });
18605     this.ghost = Ext.get(this.el.dom.childNodes[1]);
18606     this.dropStatus = this.dropNotAllowed;
18607 };
18608
18609 Ext.dd.StatusProxy.prototype = {
18610     
18611     dropAllowed : "x-dd-drop-ok",
18612     
18613     dropNotAllowed : "x-dd-drop-nodrop",
18614
18615     
18616     setStatus : function(cssClass){
18617         cssClass = cssClass || this.dropNotAllowed;
18618         if(this.dropStatus != cssClass){
18619             this.el.replaceClass(this.dropStatus, cssClass);
18620             this.dropStatus = cssClass;
18621         }
18622     },
18623
18624     
18625     reset : function(clearGhost){
18626         this.el.dom.className = "x-dd-drag-proxy " + this.dropNotAllowed;
18627         this.dropStatus = this.dropNotAllowed;
18628         if(clearGhost){
18629             this.ghost.update("");
18630         }
18631     },
18632
18633     
18634     update : function(html){
18635         if(typeof html == "string"){
18636             this.ghost.update(html);
18637         }else{
18638             this.ghost.update("");
18639             html.style.margin = "0";
18640             this.ghost.dom.appendChild(html);
18641         }
18642         var el = this.ghost.dom.firstChild; 
18643         if(el){
18644             Ext.fly(el).setStyle('float', 'none');
18645         }
18646     },
18647
18648     
18649     getEl : function(){
18650         return this.el;
18651     },
18652
18653     
18654     getGhost : function(){
18655         return this.ghost;
18656     },
18657
18658     
18659     hide : function(clear){
18660         this.el.hide();
18661         if(clear){
18662             this.reset(true);
18663         }
18664     },
18665
18666     
18667     stop : function(){
18668         if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){
18669             this.anim.stop();
18670         }
18671     },
18672
18673     
18674     show : function(){
18675         this.el.show();
18676     },
18677
18678     
18679     sync : function(){
18680         this.el.sync();
18681     },
18682
18683     
18684     repair : function(xy, callback, scope){
18685         this.callback = callback;
18686         this.scope = scope;
18687         if(xy && this.animRepair !== false){
18688             this.el.addClass("x-dd-drag-repair");
18689             this.el.hideUnders(true);
18690             this.anim = this.el.shift({
18691                 duration: this.repairDuration || .5,
18692                 easing: 'easeOut',
18693                 xy: xy,
18694                 stopFx: true,
18695                 callback: this.afterRepair,
18696                 scope: this
18697             });
18698         }else{
18699             this.afterRepair();
18700         }
18701     },
18702
18703     
18704     afterRepair : function(){
18705         this.hide(true);
18706         if(typeof this.callback == "function"){
18707             this.callback.call(this.scope || this);
18708         }
18709         this.callback = null;
18710         this.scope = null;
18711     },
18712     
18713     destroy: function(){
18714         Ext.destroy(this.ghost, this.el);    
18715     }
18716 };
18717 Ext.dd.DragSource = function(el, config){
18718     this.el = Ext.get(el);
18719     if(!this.dragData){
18720         this.dragData = {};
18721     }
18722     
18723     Ext.apply(this, config);
18724     
18725     if(!this.proxy){
18726         this.proxy = new Ext.dd.StatusProxy();
18727     }
18728     Ext.dd.DragSource.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group, 
18729           {dragElId : this.proxy.id, resizeFrame: false, isTarget: false, scroll: this.scroll === true});
18730     
18731     this.dragging = false;
18732 };
18733
18734 Ext.extend(Ext.dd.DragSource, Ext.dd.DDProxy, {
18735     
18736     
18737     dropAllowed : "x-dd-drop-ok",
18738     
18739     dropNotAllowed : "x-dd-drop-nodrop",
18740
18741     
18742     getDragData : function(e){
18743         return this.dragData;
18744     },
18745
18746     
18747     onDragEnter : function(e, id){
18748         var target = Ext.dd.DragDropMgr.getDDById(id);
18749         this.cachedTarget = target;
18750         if(this.beforeDragEnter(target, e, id) !== false){
18751             if(target.isNotifyTarget){
18752                 var status = target.notifyEnter(this, e, this.dragData);
18753                 this.proxy.setStatus(status);
18754             }else{
18755                 this.proxy.setStatus(this.dropAllowed);
18756             }
18757             
18758             if(this.afterDragEnter){
18759                 
18760                 this.afterDragEnter(target, e, id);
18761             }
18762         }
18763     },
18764
18765     
18766     beforeDragEnter : function(target, e, id){
18767         return true;
18768     },
18769
18770     
18771     alignElWithMouse: function() {
18772         Ext.dd.DragSource.superclass.alignElWithMouse.apply(this, arguments);
18773         this.proxy.sync();
18774     },
18775
18776     
18777     onDragOver : function(e, id){
18778         var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
18779         if(this.beforeDragOver(target, e, id) !== false){
18780             if(target.isNotifyTarget){
18781                 var status = target.notifyOver(this, e, this.dragData);
18782                 this.proxy.setStatus(status);
18783             }
18784
18785             if(this.afterDragOver){
18786                 
18787                 this.afterDragOver(target, e, id);
18788             }
18789         }
18790     },
18791
18792     
18793     beforeDragOver : function(target, e, id){
18794         return true;
18795     },
18796
18797     
18798     onDragOut : function(e, id){
18799         var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
18800         if(this.beforeDragOut(target, e, id) !== false){
18801             if(target.isNotifyTarget){
18802                 target.notifyOut(this, e, this.dragData);
18803             }
18804             this.proxy.reset();
18805             if(this.afterDragOut){
18806                 
18807                 this.afterDragOut(target, e, id);
18808             }
18809         }
18810         this.cachedTarget = null;
18811     },
18812
18813     
18814     beforeDragOut : function(target, e, id){
18815         return true;
18816     },
18817     
18818     
18819     onDragDrop : function(e, id){
18820         var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
18821         if(this.beforeDragDrop(target, e, id) !== false){
18822             if(target.isNotifyTarget){
18823                 if(target.notifyDrop(this, e, this.dragData)){ 
18824                     this.onValidDrop(target, e, id);
18825                 }else{
18826                     this.onInvalidDrop(target, e, id);
18827                 }
18828             }else{
18829                 this.onValidDrop(target, e, id);
18830             }
18831             
18832             if(this.afterDragDrop){
18833                 
18834                 this.afterDragDrop(target, e, id);
18835             }
18836         }
18837         delete this.cachedTarget;
18838     },
18839
18840     
18841     beforeDragDrop : function(target, e, id){
18842         return true;
18843     },
18844
18845     
18846     onValidDrop : function(target, e, id){
18847         this.hideProxy();
18848         if(this.afterValidDrop){
18849             
18850             this.afterValidDrop(target, e, id);
18851         }
18852     },
18853
18854     
18855     getRepairXY : function(e, data){
18856         return this.el.getXY();  
18857     },
18858
18859     
18860     onInvalidDrop : function(target, e, id){
18861         this.beforeInvalidDrop(target, e, id);
18862         if(this.cachedTarget){
18863             if(this.cachedTarget.isNotifyTarget){
18864                 this.cachedTarget.notifyOut(this, e, this.dragData);
18865             }
18866             this.cacheTarget = null;
18867         }
18868         this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);
18869
18870         if(this.afterInvalidDrop){
18871             
18872             this.afterInvalidDrop(e, id);
18873         }
18874     },
18875
18876     
18877     afterRepair : function(){
18878         if(Ext.enableFx){
18879             this.el.highlight(this.hlColor || "c3daf9");
18880         }
18881         this.dragging = false;
18882     },
18883
18884     
18885     beforeInvalidDrop : function(target, e, id){
18886         return true;
18887     },
18888
18889     
18890     handleMouseDown : function(e){
18891         if(this.dragging) {
18892             return;
18893         }
18894         var data = this.getDragData(e);
18895         if(data && this.onBeforeDrag(data, e) !== false){
18896             this.dragData = data;
18897             this.proxy.stop();
18898             Ext.dd.DragSource.superclass.handleMouseDown.apply(this, arguments);
18899         } 
18900     },
18901
18902     
18903     onBeforeDrag : function(data, e){
18904         return true;
18905     },
18906
18907     
18908     onStartDrag : Ext.emptyFn,
18909
18910     
18911     startDrag : function(x, y){
18912         this.proxy.reset();
18913         this.dragging = true;
18914         this.proxy.update("");
18915         this.onInitDrag(x, y);
18916         this.proxy.show();
18917     },
18918
18919     
18920     onInitDrag : function(x, y){
18921         var clone = this.el.dom.cloneNode(true);
18922         clone.id = Ext.id(); 
18923         this.proxy.update(clone);
18924         this.onStartDrag(x, y);
18925         return true;
18926     },
18927
18928     
18929     getProxy : function(){
18930         return this.proxy;  
18931     },
18932
18933     
18934     hideProxy : function(){
18935         this.proxy.hide();  
18936         this.proxy.reset(true);
18937         this.dragging = false;
18938     },
18939
18940     
18941     triggerCacheRefresh : function(){
18942         Ext.dd.DDM.refreshCache(this.groups);
18943     },
18944
18945     
18946     b4EndDrag: function(e) {
18947     },
18948
18949     
18950     endDrag : function(e){
18951         this.onEndDrag(this.dragData, e);
18952     },
18953
18954     
18955     onEndDrag : function(data, e){
18956     },
18957     
18958     
18959     autoOffset : function(x, y) {
18960         this.setDelta(-12, -20);
18961     },
18962     
18963     destroy: function(){
18964         Ext.dd.DragSource.superclass.destroy.call(this);
18965         Ext.destroy(this.proxy);
18966     }
18967 });
18968 Ext.dd.DropTarget = function(el, config){
18969     this.el = Ext.get(el);
18970     
18971     Ext.apply(this, config);
18972     
18973     if(this.containerScroll){
18974         Ext.dd.ScrollManager.register(this.el);
18975     }
18976     
18977     Ext.dd.DropTarget.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group, 
18978           {isTarget: true});
18979
18980 };
18981
18982 Ext.extend(Ext.dd.DropTarget, Ext.dd.DDTarget, {
18983     
18984     
18985     
18986     dropAllowed : "x-dd-drop-ok",
18987     
18988     dropNotAllowed : "x-dd-drop-nodrop",
18989
18990     
18991     isTarget : true,
18992
18993     
18994     isNotifyTarget : true,
18995
18996     
18997     notifyEnter : function(dd, e, data){
18998         if(this.overClass){
18999             this.el.addClass(this.overClass);
19000         }
19001         return this.dropAllowed;
19002     },
19003
19004     
19005     notifyOver : function(dd, e, data){
19006         return this.dropAllowed;
19007     },
19008
19009     
19010     notifyOut : function(dd, e, data){
19011         if(this.overClass){
19012             this.el.removeClass(this.overClass);
19013         }
19014     },
19015
19016     
19017     notifyDrop : function(dd, e, data){
19018         return false;
19019     }
19020 });
19021 Ext.dd.DragZone = function(el, config){
19022     Ext.dd.DragZone.superclass.constructor.call(this, el, config);
19023     if(this.containerScroll){
19024         Ext.dd.ScrollManager.register(this.el);
19025     }
19026 };
19027
19028 Ext.extend(Ext.dd.DragZone, Ext.dd.DragSource, {
19029     
19030     
19031     
19032
19033     
19034     getDragData : function(e){
19035         return Ext.dd.Registry.getHandleFromEvent(e);
19036     },
19037     
19038     
19039     onInitDrag : function(x, y){
19040         this.proxy.update(this.dragData.ddel.cloneNode(true));
19041         this.onStartDrag(x, y);
19042         return true;
19043     },
19044     
19045     
19046     afterRepair : function(){
19047         if(Ext.enableFx){
19048             Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
19049         }
19050         this.dragging = false;
19051     },
19052
19053     
19054     getRepairXY : function(e){
19055         return Ext.Element.fly(this.dragData.ddel).getXY();  
19056     }
19057 });
19058 Ext.dd.DropZone = function(el, config){
19059     Ext.dd.DropZone.superclass.constructor.call(this, el, config);
19060 };
19061
19062 Ext.extend(Ext.dd.DropZone, Ext.dd.DropTarget, {
19063     
19064     getTargetFromEvent : function(e){
19065         return Ext.dd.Registry.getTargetFromEvent(e);
19066     },
19067
19068     
19069     onNodeEnter : function(n, dd, e, data){
19070         
19071     },
19072
19073     
19074     onNodeOver : function(n, dd, e, data){
19075         return this.dropAllowed;
19076     },
19077
19078     
19079     onNodeOut : function(n, dd, e, data){
19080         
19081     },
19082
19083     
19084     onNodeDrop : function(n, dd, e, data){
19085         return false;
19086     },
19087
19088     
19089     onContainerOver : function(dd, e, data){
19090         return this.dropNotAllowed;
19091     },
19092
19093     
19094     onContainerDrop : function(dd, e, data){
19095         return false;
19096     },
19097
19098     
19099     notifyEnter : function(dd, e, data){
19100         return this.dropNotAllowed;
19101     },
19102
19103     
19104     notifyOver : function(dd, e, data){
19105         var n = this.getTargetFromEvent(e);
19106         if(!n){ 
19107             if(this.lastOverNode){
19108                 this.onNodeOut(this.lastOverNode, dd, e, data);
19109                 this.lastOverNode = null;
19110             }
19111             return this.onContainerOver(dd, e, data);
19112         }
19113         if(this.lastOverNode != n){
19114             if(this.lastOverNode){
19115                 this.onNodeOut(this.lastOverNode, dd, e, data);
19116             }
19117             this.onNodeEnter(n, dd, e, data);
19118             this.lastOverNode = n;
19119         }
19120         return this.onNodeOver(n, dd, e, data);
19121     },
19122
19123     
19124     notifyOut : function(dd, e, data){
19125         if(this.lastOverNode){
19126             this.onNodeOut(this.lastOverNode, dd, e, data);
19127             this.lastOverNode = null;
19128         }
19129     },
19130
19131     
19132     notifyDrop : function(dd, e, data){
19133         if(this.lastOverNode){
19134             this.onNodeOut(this.lastOverNode, dd, e, data);
19135             this.lastOverNode = null;
19136         }
19137         var n = this.getTargetFromEvent(e);
19138         return n ?
19139             this.onNodeDrop(n, dd, e, data) :
19140             this.onContainerDrop(dd, e, data);
19141     },
19142
19143     
19144     triggerCacheRefresh : function(){
19145         Ext.dd.DDM.refreshCache(this.groups);
19146     }  
19147 });
19148 Ext.Element.addMethods({
19149     
19150     initDD : function(group, config, overrides){
19151         var dd = new Ext.dd.DD(Ext.id(this.dom), group, config);
19152         return Ext.apply(dd, overrides);
19153     },
19154
19155     
19156     initDDProxy : function(group, config, overrides){
19157         var dd = new Ext.dd.DDProxy(Ext.id(this.dom), group, config);
19158         return Ext.apply(dd, overrides);
19159     },
19160
19161     
19162     initDDTarget : function(group, config, overrides){
19163         var dd = new Ext.dd.DDTarget(Ext.id(this.dom), group, config);
19164         return Ext.apply(dd, overrides);
19165     }
19166 });
19167
19168 Ext.data.Api = (function() {
19169
19170     
19171     
19172     
19173     
19174     var validActions = {};
19175
19176     return {
19177         
19178         actions : {
19179             create  : 'create',
19180             read    : 'read',
19181             update  : 'update',
19182             destroy : 'destroy'
19183         },
19184
19185         
19186         restActions : {
19187             create  : 'POST',
19188             read    : 'GET',
19189             update  : 'PUT',
19190             destroy : 'DELETE'
19191         },
19192
19193         
19194         isAction : function(action) {
19195             return (Ext.data.Api.actions[action]) ? true : false;
19196         },
19197
19198         
19199         getVerb : function(name) {
19200             if (validActions[name]) {
19201                 return validActions[name];  
19202             }
19203             for (var verb in this.actions) {
19204                 if (this.actions[verb] === name) {
19205                     validActions[name] = verb;
19206                     break;
19207                 }
19208             }
19209             return (validActions[name] !== undefined) ? validActions[name] : null;
19210         },
19211
19212         
19213         isValid : function(api){
19214             var invalid = [];
19215             var crud = this.actions; 
19216             for (var action in api) {
19217                 if (!(action in crud)) {
19218                     invalid.push(action);
19219                 }
19220             }
19221             return (!invalid.length) ? true : invalid;
19222         },
19223
19224         
19225         hasUniqueUrl : function(proxy, verb) {
19226             var url = (proxy.api[verb]) ? proxy.api[verb].url : null;
19227             var unique = true;
19228             for (var action in proxy.api) {
19229                 if ((unique = (action === verb) ? true : (proxy.api[action].url != url) ? true : false) === false) {
19230                     break;
19231                 }
19232             }
19233             return unique;
19234         },
19235
19236         
19237         prepare : function(proxy) {
19238             if (!proxy.api) {
19239                 proxy.api = {}; 
19240             }
19241             for (var verb in this.actions) {
19242                 var action = this.actions[verb];
19243                 proxy.api[action] = proxy.api[action] || proxy.url || proxy.directFn;
19244                 if (typeof(proxy.api[action]) == 'string') {
19245                     proxy.api[action] = {
19246                         url: proxy.api[action],
19247                         method: (proxy.restful === true) ? Ext.data.Api.restActions[action] : undefined
19248                     };
19249                 }
19250             }
19251         },
19252
19253         
19254         restify : function(proxy) {
19255             proxy.restful = true;
19256             for (var verb in this.restActions) {
19257                 proxy.api[this.actions[verb]].method = this.restActions[verb];
19258             }
19259             
19260             
19261             proxy.onWrite = proxy.onWrite.createInterceptor(function(action, o, response, rs) {
19262                 var reader = o.reader;
19263                 var res = new Ext.data.Response({
19264                     action: action,
19265                     raw: response
19266                 });
19267
19268                 switch (response.status) {
19269                     case 200:   
19270                         return true;
19271                         break;
19272                     case 201:   
19273                         res.success = true;
19274                         break;
19275                     case 204:  
19276                         res.success = true;
19277                         res.data = null;
19278                         break;
19279                     default:
19280                         return true;
19281                         break;
19282                 }
19283                 if (res.success === true) {
19284                     this.fireEvent("write", this, action, res.data, res, rs, o.request.arg);
19285                 } else {
19286                     this.fireEvent('exception', this, 'remote', action, o, res, rs);
19287                 }
19288                 o.request.callback.call(o.request.scope, res.data, res, res.success);
19289
19290                 return false;   
19291             }, proxy);
19292         }
19293     };
19294 })();
19295
19296
19297 Ext.data.Response = function(params, response) {
19298     Ext.apply(this, params, {
19299         raw: response
19300     });
19301 };
19302 Ext.data.Response.prototype = {
19303     message : null,
19304     success : false,
19305     status : null,
19306     root : null,
19307     raw : null,
19308
19309     getMessage : function() {
19310         return this.message;
19311     },
19312     getSuccess : function() {
19313         return this.success;
19314     },
19315     getStatus : function() {
19316         return this.status
19317     },
19318     getRoot : function() {
19319         return this.root;
19320     },
19321     getRawResponse : function() {
19322         return this.raw;
19323     }
19324 };
19325
19326
19327 Ext.data.Api.Error = Ext.extend(Ext.Error, {
19328     constructor : function(message, arg) {
19329         this.arg = arg;
19330         Ext.Error.call(this, message);
19331     },
19332     name: 'Ext.data.Api'
19333 });
19334 Ext.apply(Ext.data.Api.Error.prototype, {
19335     lang: {
19336         '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.',
19337         'invalid': 'received an invalid API-configuration.  Please ensure your proxy API-configuration contains only the actions defined in Ext.data.Api.actions',
19338         'invalid-url': 'Invalid url.  Please review your proxy configuration.',
19339         'execute': 'Attempted to execute an unknown action.  Valid API actions are defined in Ext.data.Api.actions"'
19340     }
19341 });
19342
19343
19344
19345
19346 Ext.data.SortTypes = {
19347     
19348     none : function(s){
19349         return s;
19350     },
19351     
19352     
19353     stripTagsRE : /<\/?[^>]+>/gi,
19354     
19355     
19356     asText : function(s){
19357         return String(s).replace(this.stripTagsRE, "");
19358     },
19359     
19360     
19361     asUCText : function(s){
19362         return String(s).toUpperCase().replace(this.stripTagsRE, "");
19363     },
19364     
19365     
19366     asUCString : function(s) {
19367         return String(s).toUpperCase();
19368     },
19369     
19370     
19371     asDate : function(s) {
19372         if(!s){
19373             return 0;
19374         }
19375         if(Ext.isDate(s)){
19376             return s.getTime();
19377         }
19378         return Date.parse(String(s));
19379     },
19380     
19381     
19382     asFloat : function(s) {
19383         var val = parseFloat(String(s).replace(/,/g, ""));
19384         return isNaN(val) ? 0 : val;
19385     },
19386     
19387     
19388     asInt : function(s) {
19389         var val = parseInt(String(s).replace(/,/g, ""), 10);
19390         return isNaN(val) ? 0 : val;
19391     }
19392 };
19393 Ext.data.Record = function(data, id){
19394     
19395     this.id = (id || id === 0) ? id : Ext.data.Record.id(this);
19396     this.data = data || {};
19397 };
19398
19399
19400 Ext.data.Record.create = function(o){
19401     var f = Ext.extend(Ext.data.Record, {});
19402     var p = f.prototype;
19403     p.fields = new Ext.util.MixedCollection(false, function(field){
19404         return field.name;
19405     });
19406     for(var i = 0, len = o.length; i < len; i++){
19407         p.fields.add(new Ext.data.Field(o[i]));
19408     }
19409     f.getField = function(name){
19410         return p.fields.get(name);
19411     };
19412     return f;
19413 };
19414
19415 Ext.data.Record.PREFIX = 'ext-record';
19416 Ext.data.Record.AUTO_ID = 1;
19417 Ext.data.Record.EDIT = 'edit';
19418 Ext.data.Record.REJECT = 'reject';
19419 Ext.data.Record.COMMIT = 'commit';
19420
19421
19422
19423 Ext.data.Record.id = function(rec) {
19424     rec.phantom = true;
19425     return [Ext.data.Record.PREFIX, '-', Ext.data.Record.AUTO_ID++].join('');
19426 };
19427
19428 Ext.data.Record.prototype = {
19429     
19430     
19431     
19432     
19433     
19434     
19435     dirty : false,
19436     editing : false,
19437     error : null,
19438     
19439     modified : null,
19440     
19441     phantom : false,
19442
19443     
19444     join : function(store){
19445         
19446         this.store = store;
19447     },
19448
19449     
19450     set : function(name, value){
19451         var encode = Ext.isPrimitive(value) ? String : Ext.encode;
19452         if(encode(this.data[name]) == encode(value)) {
19453             return;
19454         }        
19455         this.dirty = true;
19456         if(!this.modified){
19457             this.modified = {};
19458         }
19459         if(this.modified[name] === undefined){
19460             this.modified[name] = this.data[name];
19461         }
19462         this.data[name] = value;
19463         if(!this.editing){
19464             this.afterEdit();
19465         }
19466     },
19467
19468     
19469     afterEdit : function(){
19470         if(this.store){
19471             this.store.afterEdit(this);
19472         }
19473     },
19474
19475     
19476     afterReject : function(){
19477         if(this.store){
19478             this.store.afterReject(this);
19479         }
19480     },
19481
19482     
19483     afterCommit : function(){
19484         if(this.store){
19485             this.store.afterCommit(this);
19486         }
19487     },
19488
19489     
19490     get : function(name){
19491         return this.data[name];
19492     },
19493
19494     
19495     beginEdit : function(){
19496         this.editing = true;
19497         this.modified = this.modified || {};
19498     },
19499
19500     
19501     cancelEdit : function(){
19502         this.editing = false;
19503         delete this.modified;
19504     },
19505
19506     
19507     endEdit : function(){
19508         this.editing = false;
19509         if(this.dirty){
19510             this.afterEdit();
19511         }
19512     },
19513
19514     
19515     reject : function(silent){
19516         var m = this.modified;
19517         for(var n in m){
19518             if(typeof m[n] != "function"){
19519                 this.data[n] = m[n];
19520             }
19521         }
19522         this.dirty = false;
19523         delete this.modified;
19524         this.editing = false;
19525         if(silent !== true){
19526             this.afterReject();
19527         }
19528     },
19529
19530     
19531     commit : function(silent){
19532         this.dirty = false;
19533         delete this.modified;
19534         this.editing = false;
19535         if(silent !== true){
19536             this.afterCommit();
19537         }
19538     },
19539
19540     
19541     getChanges : function(){
19542         var m = this.modified, cs = {};
19543         for(var n in m){
19544             if(m.hasOwnProperty(n)){
19545                 cs[n] = this.data[n];
19546             }
19547         }
19548         return cs;
19549     },
19550
19551     
19552     hasError : function(){
19553         return this.error !== null;
19554     },
19555
19556     
19557     clearError : function(){
19558         this.error = null;
19559     },
19560
19561     
19562     copy : function(newId) {
19563         return new this.constructor(Ext.apply({}, this.data), newId || this.id);
19564     },
19565
19566     
19567     isModified : function(fieldName){
19568         return !!(this.modified && this.modified.hasOwnProperty(fieldName));
19569     },
19570
19571     
19572     isValid : function() {
19573         return this.fields.find(function(f) {
19574             return (f.allowBlank === false && Ext.isEmpty(this.data[f.name])) ? true : false;
19575         },this) ? false : true;
19576     },
19577
19578     
19579     markDirty : function(){
19580         this.dirty = true;
19581         if(!this.modified){
19582             this.modified = {};
19583         }
19584         this.fields.each(function(f) {
19585             this.modified[f.name] = this.data[f.name];
19586         },this);
19587     }
19588 };
19589
19590 Ext.StoreMgr = Ext.apply(new Ext.util.MixedCollection(), {
19591     
19592
19593     
19594     register : function(){
19595         for(var i = 0, s; (s = arguments[i]); i++){
19596             this.add(s);
19597         }
19598     },
19599
19600     
19601     unregister : function(){
19602         for(var i = 0, s; (s = arguments[i]); i++){
19603             this.remove(this.lookup(s));
19604         }
19605     },
19606
19607     
19608     lookup : function(id){
19609         if(Ext.isArray(id)){
19610             var fields = ['field1'], expand = !Ext.isArray(id[0]);
19611             if(!expand){
19612                 for(var i = 2, len = id[0].length; i <= len; ++i){
19613                     fields.push('field' + i);
19614                 }
19615             }
19616             return new Ext.data.ArrayStore({
19617                 fields: fields,
19618                 data: id,
19619                 expandData: expand,
19620                 autoDestroy: true,
19621                 autoCreated: true
19622
19623             });
19624         }
19625         return Ext.isObject(id) ? (id.events ? id : Ext.create(id, 'store')) : this.get(id);
19626     },
19627
19628     
19629     getKey : function(o){
19630          return o.storeId;
19631     }
19632 });
19633 Ext.data.Store = Ext.extend(Ext.util.Observable, {
19634     
19635     
19636     
19637     
19638     
19639     
19640     
19641     writer : undefined,
19642     
19643     
19644     
19645     remoteSort : false,
19646
19647     
19648     autoDestroy : false,
19649
19650     
19651     pruneModifiedRecords : false,
19652
19653     
19654     lastOptions : null,
19655
19656     
19657     autoSave : true,
19658
19659     
19660     batch : true,
19661
19662     
19663     restful: false,
19664
19665     
19666     paramNames : undefined,
19667
19668     
19669     defaultParamNames : {
19670         start : 'start',
19671         limit : 'limit',
19672         sort : 'sort',
19673         dir : 'dir'
19674     },
19675
19676     
19677     batchKey : '_ext_batch_',
19678
19679     constructor : function(config){
19680         this.data = new Ext.util.MixedCollection(false);
19681         this.data.getKey = function(o){
19682             return o.id;
19683         };
19684         
19685         this.baseParams = {};
19686
19687         
19688         this.removed = [];
19689
19690         if(config && config.data){
19691             this.inlineData = config.data;
19692             delete config.data;
19693         }
19694
19695         Ext.apply(this, config);
19696
19697         this.paramNames = Ext.applyIf(this.paramNames || {}, this.defaultParamNames);
19698
19699         if((this.url || this.api) && !this.proxy){
19700             this.proxy = new Ext.data.HttpProxy({url: this.url, api: this.api});
19701         }
19702         
19703         if (this.restful === true && this.proxy) {
19704             
19705             
19706             this.batch = false;
19707             Ext.data.Api.restify(this.proxy);
19708         }
19709
19710         if(this.reader){ 
19711             if(!this.recordType){
19712                 this.recordType = this.reader.recordType;
19713             }
19714             if(this.reader.onMetaChange){
19715                 this.reader.onMetaChange = this.reader.onMetaChange.createSequence(this.onMetaChange, this);
19716             }
19717             if (this.writer) { 
19718                 if (this.writer instanceof(Ext.data.DataWriter) === false) {    
19719                     this.writer = this.buildWriter(this.writer);
19720                 }
19721                 this.writer.meta = this.reader.meta;
19722                 this.pruneModifiedRecords = true;
19723             }
19724         }
19725
19726         
19727
19728         if(this.recordType){
19729             
19730             this.fields = this.recordType.prototype.fields;
19731         }
19732         this.modified = [];
19733
19734         this.addEvents(
19735             
19736             'datachanged',
19737             
19738             'metachange',
19739             
19740             'add',
19741             
19742             'remove',
19743             
19744             'update',
19745             
19746             'clear',
19747             
19748             'exception',
19749             
19750             'beforeload',
19751             
19752             'load',
19753             
19754             'loadexception',
19755             
19756             'beforewrite',
19757             
19758             'write',
19759             
19760             'beforesave',
19761             
19762             'save'
19763
19764         );
19765
19766         if(this.proxy){
19767             
19768             this.relayEvents(this.proxy,  ['loadexception', 'exception']);
19769         }
19770         
19771         if (this.writer) {
19772             this.on({
19773                 scope: this,
19774                 add: this.createRecords,
19775                 remove: this.destroyRecord,
19776                 update: this.updateRecord,
19777                 clear: this.onClear
19778             });
19779         }
19780
19781         this.sortToggle = {};
19782         if(this.sortField){
19783             this.setDefaultSort(this.sortField, this.sortDir);
19784         }else if(this.sortInfo){
19785             this.setDefaultSort(this.sortInfo.field, this.sortInfo.direction);
19786         }
19787
19788         Ext.data.Store.superclass.constructor.call(this);
19789
19790         if(this.id){
19791             this.storeId = this.id;
19792             delete this.id;
19793         }
19794         if(this.storeId){
19795             Ext.StoreMgr.register(this);
19796         }
19797         if(this.inlineData){
19798             this.loadData(this.inlineData);
19799             delete this.inlineData;
19800         }else if(this.autoLoad){
19801             this.load.defer(10, this, [
19802                 typeof this.autoLoad == 'object' ?
19803                     this.autoLoad : undefined]);
19804         }
19805         
19806         this.batchCounter = 0;
19807         this.batches = {};
19808     },
19809
19810     
19811     buildWriter : function(config) {
19812         var klass = undefined;
19813         type = (config.format || 'json').toLowerCase();
19814         switch (type) {
19815             case 'json':
19816                 klass = Ext.data.JsonWriter;
19817                 break;
19818             case 'xml':
19819                 klass = Ext.data.XmlWriter;
19820                 break;
19821             default:
19822                 klass = Ext.data.JsonWriter;
19823         }
19824         return new klass(config);
19825     },
19826
19827     
19828     destroy : function(){
19829         if(!this.isDestroyed){
19830             if(this.storeId){
19831                 Ext.StoreMgr.unregister(this);
19832             }
19833             this.clearData();
19834             this.data = null;
19835             Ext.destroy(this.proxy);
19836             this.reader = this.writer = null;
19837             this.purgeListeners();
19838             this.isDestroyed = true;
19839         }
19840     },
19841
19842     
19843     add : function(records){
19844         records = [].concat(records);
19845         if(records.length < 1){
19846             return;
19847         }
19848         for(var i = 0, len = records.length; i < len; i++){
19849             records[i].join(this);
19850         }
19851         var index = this.data.length;
19852         this.data.addAll(records);
19853         if(this.snapshot){
19854             this.snapshot.addAll(records);
19855         }
19856         this.fireEvent('add', this, records, index);
19857     },
19858
19859     
19860     addSorted : function(record){
19861         var index = this.findInsertIndex(record);
19862         this.insert(index, record);
19863     },
19864
19865     
19866     remove : function(record){
19867         if(Ext.isArray(record)){
19868             Ext.each(record, function(r){
19869                 this.remove(r);
19870             }, this);
19871         }
19872         var index = this.data.indexOf(record);
19873         if(index > -1){
19874             record.join(null);
19875             this.data.removeAt(index);
19876         }
19877         if(this.pruneModifiedRecords){
19878             this.modified.remove(record);
19879         }
19880         if(this.snapshot){
19881             this.snapshot.remove(record);
19882         }
19883         if(index > -1){
19884             this.fireEvent('remove', this, record, index);
19885         }
19886     },
19887
19888     
19889     removeAt : function(index){
19890         this.remove(this.getAt(index));
19891     },
19892
19893     
19894     removeAll : function(silent){
19895         var items = [];
19896         this.each(function(rec){
19897             items.push(rec);
19898         });
19899         this.clearData();
19900         if(this.snapshot){
19901             this.snapshot.clear();
19902         }
19903         if(this.pruneModifiedRecords){
19904             this.modified = [];
19905         }
19906         if (silent !== true) {  
19907             this.fireEvent('clear', this, items);
19908         }
19909     },
19910
19911     
19912     onClear: function(store, records){
19913         Ext.each(records, function(rec, index){
19914             this.destroyRecord(this, rec, index);
19915         }, this);
19916     },
19917
19918     
19919     insert : function(index, records){
19920         records = [].concat(records);
19921         for(var i = 0, len = records.length; i < len; i++){
19922             this.data.insert(index, records[i]);
19923             records[i].join(this);
19924         }
19925         if(this.snapshot){
19926             this.snapshot.addAll(records);
19927         }
19928         this.fireEvent('add', this, records, index);
19929     },
19930
19931     
19932     indexOf : function(record){
19933         return this.data.indexOf(record);
19934     },
19935
19936     
19937     indexOfId : function(id){
19938         return this.data.indexOfKey(id);
19939     },
19940
19941     
19942     getById : function(id){
19943         return (this.snapshot || this.data).key(id);
19944     },
19945
19946     
19947     getAt : function(index){
19948         return this.data.itemAt(index);
19949     },
19950
19951     
19952     getRange : function(start, end){
19953         return this.data.getRange(start, end);
19954     },
19955
19956     
19957     storeOptions : function(o){
19958         o = Ext.apply({}, o);
19959         delete o.callback;
19960         delete o.scope;
19961         this.lastOptions = o;
19962     },
19963
19964     
19965     clearData: function(){
19966         this.data.each(function(rec) {
19967             rec.join(null);
19968         });
19969         this.data.clear();
19970     },
19971
19972     
19973     load : function(options) {
19974         options = options || {};
19975         this.storeOptions(options);
19976         if(this.sortInfo && this.remoteSort){
19977             var pn = this.paramNames;
19978             options.params = options.params || {};
19979             options.params[pn.sort] = this.sortInfo.field;
19980             options.params[pn.dir] = this.sortInfo.direction;
19981         }
19982         try {
19983             return this.execute('read', null, options); 
19984         } catch(e) {
19985             this.handleException(e);
19986             return false;
19987         }
19988     },
19989
19990     
19991     updateRecord : function(store, record, action) {
19992         if (action == Ext.data.Record.EDIT && this.autoSave === true && (!record.phantom || (record.phantom && record.isValid()))) {
19993             this.save();
19994         }
19995     },
19996
19997     
19998     createRecords : function(store, rs, index) {
19999         for (var i = 0, len = rs.length; i < len; i++) {
20000             if (rs[i].phantom && rs[i].isValid()) {
20001                 rs[i].markDirty();  
20002                 this.modified.push(rs[i]);  
20003             }
20004         }
20005         if (this.autoSave === true) {
20006             this.save();
20007         }
20008     },
20009
20010     
20011     destroyRecord : function(store, record, index) {
20012         if (this.modified.indexOf(record) != -1) {  
20013             this.modified.remove(record);
20014         }
20015         if (!record.phantom) {
20016             this.removed.push(record);
20017
20018             
20019             
20020             
20021             record.lastIndex = index;
20022
20023             if (this.autoSave === true) {
20024                 this.save();
20025             }
20026         }
20027     },
20028
20029     
20030     execute : function(action, rs, options,  batch) {
20031         
20032         if (!Ext.data.Api.isAction(action)) {
20033             throw new Ext.data.Api.Error('execute', action);
20034         }
20035         
20036         options = Ext.applyIf(options||{}, {
20037             params: {}
20038         });
20039         if(batch !== undefined){
20040             this.addToBatch(batch);
20041         }
20042         
20043         
20044         var doRequest = true;
20045
20046         if (action === 'read') {
20047             Ext.applyIf(options.params, this.baseParams);
20048             doRequest = this.fireEvent('beforeload', this, options);
20049         }
20050         else {
20051             
20052             
20053             if (this.writer.listful === true && this.restful !== true) {
20054                 rs = (Ext.isArray(rs)) ? rs : [rs];
20055             }
20056             
20057             else if (Ext.isArray(rs) && rs.length == 1) {
20058                 rs = rs.shift();
20059             }
20060             
20061             if ((doRequest = this.fireEvent('beforewrite', this, action, rs, options)) !== false) {
20062                 this.writer.apply(options.params, this.baseParams, action, rs);
20063             }
20064         }
20065         if (doRequest !== false) {
20066             
20067             if (this.writer && this.proxy.url && !this.proxy.restful && !Ext.data.Api.hasUniqueUrl(this.proxy, action)) {
20068                 options.params.xaction = action;    
20069             }
20070             
20071             
20072             
20073             
20074             
20075             this.proxy.request(Ext.data.Api.actions[action], rs, options.params, this.reader, this.createCallback(action, rs, batch), this, options);
20076         }
20077         return doRequest;
20078     },
20079
20080     
20081     save : function() {
20082         if (!this.writer) {
20083             throw new Ext.data.Store.Error('writer-undefined');
20084         }
20085
20086         var queue = [],
20087             len,
20088             trans,
20089             batch,
20090             data = {};
20091         
20092         if(this.removed.length){
20093             queue.push(['destroy', this.removed]);
20094         }
20095
20096         
20097         var rs = [].concat(this.getModifiedRecords());
20098         if(rs.length){
20099             
20100             var phantoms = [];
20101             for(var i = rs.length-1; i >= 0; i--){
20102                 if(rs[i].phantom === true){
20103                     var rec = rs.splice(i, 1).shift();
20104                     if(rec.isValid()){
20105                         phantoms.push(rec);
20106                     }
20107                 }else if(!rs[i].isValid()){ 
20108                     rs.splice(i,1);
20109                 }
20110             }
20111             
20112             if(phantoms.length){
20113                 queue.push(['create', phantoms]);
20114             }
20115
20116             
20117             if(rs.length){
20118                 queue.push(['update', rs]);
20119             }
20120         }
20121         len = queue.length;
20122         if(len){
20123             batch = ++this.batchCounter;
20124             for(var i = 0; i < len; ++i){
20125                 trans = queue[i];
20126                 data[trans[0]] = trans[1];
20127             }
20128             if(this.fireEvent('beforesave', this, data) !== false){
20129                 for(var i = 0; i < len; ++i){
20130                     trans = queue[i];
20131                     this.doTransaction(trans[0], trans[1], batch);
20132                 }
20133                 return batch;
20134             }
20135         }
20136         return -1;
20137     },
20138
20139     
20140     doTransaction : function(action, rs, batch) {
20141         function transaction(records) {
20142             try{
20143                 this.execute(action, records, undefined, batch);
20144             }catch (e){
20145                 this.handleException(e);
20146             }
20147         }
20148         if(this.batch === false){
20149             for(var i = 0, len = rs.length; i < len; i++){
20150                 transaction.call(this, rs[i]);
20151             }
20152         }else{
20153             transaction.call(this, rs);
20154         }
20155     },
20156
20157     
20158     addToBatch : function(batch){
20159         var b = this.batches,
20160             key = this.batchKey + batch,
20161             o = b[key];
20162
20163         if(!o){
20164             b[key] = o = {
20165                 id: batch,
20166                 count: 0,
20167                 data: {}
20168             }
20169         }
20170         ++o.count;
20171     },
20172
20173     removeFromBatch : function(batch, action, data){
20174         var b = this.batches,
20175             key = this.batchKey + batch,
20176             o = b[key],
20177             data,
20178             arr;
20179
20180
20181         if(o){
20182             arr = o.data[action] || [];
20183             o.data[action] = arr.concat(data);
20184             if(o.count === 1){
20185                 data = o.data;
20186                 delete b[key];
20187                 this.fireEvent('save', this, batch, data);
20188             }else{
20189                 --o.count;
20190             }
20191         }
20192     },
20193
20194     
20195     
20196     createCallback : function(action, rs, batch) {
20197         var actions = Ext.data.Api.actions;
20198         return (action == 'read') ? this.loadRecords : function(data, response, success) {
20199             
20200             this['on' + Ext.util.Format.capitalize(action) + 'Records'](success, rs, [].concat(data));
20201             
20202             if (success === true) {
20203                 this.fireEvent('write', this, action, data, response, rs);
20204             }
20205             this.removeFromBatch(batch, action, data);
20206         };
20207     },
20208
20209     
20210     
20211     
20212     clearModified : function(rs) {
20213         if (Ext.isArray(rs)) {
20214             for (var n=rs.length-1;n>=0;n--) {
20215                 this.modified.splice(this.modified.indexOf(rs[n]), 1);
20216             }
20217         } else {
20218             this.modified.splice(this.modified.indexOf(rs), 1);
20219         }
20220     },
20221
20222     
20223     reMap : function(record) {
20224         if (Ext.isArray(record)) {
20225             for (var i = 0, len = record.length; i < len; i++) {
20226                 this.reMap(record[i]);
20227             }
20228         } else {
20229             delete this.data.map[record._phid];
20230             this.data.map[record.id] = record;
20231             var index = this.data.keys.indexOf(record._phid);
20232             this.data.keys.splice(index, 1, record.id);
20233             delete record._phid;
20234         }
20235     },
20236
20237     
20238     onCreateRecords : function(success, rs, data) {
20239         if (success === true) {
20240             try {
20241                 this.reader.realize(rs, data);
20242                 this.reMap(rs);
20243             }
20244             catch (e) {
20245                 this.handleException(e);
20246                 if (Ext.isArray(rs)) {
20247                     
20248                     this.onCreateRecords(success, rs, data);
20249                 }
20250             }
20251         }
20252     },
20253
20254     
20255     onUpdateRecords : function(success, rs, data) {
20256         if (success === true) {
20257             try {
20258                 this.reader.update(rs, data);
20259             } catch (e) {
20260                 this.handleException(e);
20261                 if (Ext.isArray(rs)) {
20262                     
20263                     this.onUpdateRecords(success, rs, data);
20264                 }
20265             }
20266         }
20267     },
20268
20269     
20270     onDestroyRecords : function(success, rs, data) {
20271         
20272         rs = (rs instanceof Ext.data.Record) ? [rs] : [].concat(rs);
20273         for (var i=0,len=rs.length;i<len;i++) {
20274             this.removed.splice(this.removed.indexOf(rs[i]), 1);
20275         }
20276         if (success === false) {
20277             
20278             
20279             for (i=rs.length-1;i>=0;i--) {
20280                 this.insert(rs[i].lastIndex, rs[i]);    
20281             }
20282         }
20283     },
20284
20285     
20286     handleException : function(e) {
20287         
20288         Ext.handleError(e);
20289     },
20290
20291     
20292     reload : function(options){
20293         this.load(Ext.applyIf(options||{}, this.lastOptions));
20294     },
20295
20296     
20297     
20298     loadRecords : function(o, options, success){
20299         if (this.isDestroyed === true) {
20300             return;
20301         }
20302         if(!o || success === false){
20303             if(success !== false){
20304                 this.fireEvent('load', this, [], options);
20305             }
20306             if(options.callback){
20307                 options.callback.call(options.scope || this, [], options, false, o);
20308             }
20309             return;
20310         }
20311         var r = o.records, t = o.totalRecords || r.length;
20312         if(!options || options.add !== true){
20313             if(this.pruneModifiedRecords){
20314                 this.modified = [];
20315             }
20316             for(var i = 0, len = r.length; i < len; i++){
20317                 r[i].join(this);
20318             }
20319             if(this.snapshot){
20320                 this.data = this.snapshot;
20321                 delete this.snapshot;
20322             }
20323             this.clearData();
20324             this.data.addAll(r);
20325             this.totalLength = t;
20326             this.applySort();
20327             this.fireEvent('datachanged', this);
20328         }else{
20329             this.totalLength = Math.max(t, this.data.length+r.length);
20330             this.add(r);
20331         }
20332         this.fireEvent('load', this, r, options);
20333         if(options.callback){
20334             options.callback.call(options.scope || this, r, options, true);
20335         }
20336     },
20337
20338     
20339     loadData : function(o, append){
20340         var r = this.reader.readRecords(o);
20341         this.loadRecords(r, {add: append}, true);
20342     },
20343
20344     
20345     getCount : function(){
20346         return this.data.length || 0;
20347     },
20348
20349     
20350     getTotalCount : function(){
20351         return this.totalLength || 0;
20352     },
20353
20354     
20355     getSortState : function(){
20356         return this.sortInfo;
20357     },
20358
20359     
20360     applySort : function(){
20361         if(this.sortInfo && !this.remoteSort){
20362             var s = this.sortInfo, f = s.field;
20363             this.sortData(f, s.direction);
20364         }
20365     },
20366
20367     
20368     sortData : function(f, direction){
20369         direction = direction || 'ASC';
20370         var st = this.fields.get(f).sortType;
20371         var fn = function(r1, r2){
20372             var v1 = st(r1.data[f]), v2 = st(r2.data[f]);
20373             return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
20374         };
20375         this.data.sort(direction, fn);
20376         if(this.snapshot && this.snapshot != this.data){
20377             this.snapshot.sort(direction, fn);
20378         }
20379     },
20380
20381     
20382     setDefaultSort : function(field, dir){
20383         dir = dir ? dir.toUpperCase() : 'ASC';
20384         this.sortInfo = {field: field, direction: dir};
20385         this.sortToggle[field] = dir;
20386     },
20387
20388     
20389     sort : function(fieldName, dir){
20390         var f = this.fields.get(fieldName);
20391         if(!f){
20392             return false;
20393         }
20394         if(!dir){
20395             if(this.sortInfo && this.sortInfo.field == f.name){ 
20396                 dir = (this.sortToggle[f.name] || 'ASC').toggle('ASC', 'DESC');
20397             }else{
20398                 dir = f.sortDir;
20399             }
20400         }
20401         var st = (this.sortToggle) ? this.sortToggle[f.name] : null;
20402         var si = (this.sortInfo) ? this.sortInfo : null;
20403
20404         this.sortToggle[f.name] = dir;
20405         this.sortInfo = {field: f.name, direction: dir};
20406         if(!this.remoteSort){
20407             this.applySort();
20408             this.fireEvent('datachanged', this);
20409         }else{
20410             if (!this.load(this.lastOptions)) {
20411                 if (st) {
20412                     this.sortToggle[f.name] = st;
20413                 }
20414                 if (si) {
20415                     this.sortInfo = si;
20416                 }
20417             }
20418         }
20419     },
20420
20421     
20422     each : function(fn, scope){
20423         this.data.each(fn, scope);
20424     },
20425
20426     
20427     getModifiedRecords : function(){
20428         return this.modified;
20429     },
20430
20431     
20432     createFilterFn : function(property, value, anyMatch, caseSensitive){
20433         if(Ext.isEmpty(value, false)){
20434             return false;
20435         }
20436         value = this.data.createValueMatcher(value, anyMatch, caseSensitive);
20437         return function(r){
20438             return value.test(r.data[property]);
20439         };
20440     },
20441
20442     
20443     sum : function(property, start, end){
20444         var rs = this.data.items, v = 0;
20445         start = start || 0;
20446         end = (end || end === 0) ? end : rs.length-1;
20447
20448         for(var i = start; i <= end; i++){
20449             v += (rs[i].data[property] || 0);
20450         }
20451         return v;
20452     },
20453
20454     
20455     filter : function(property, value, anyMatch, caseSensitive){
20456         var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
20457         return fn ? this.filterBy(fn) : this.clearFilter();
20458     },
20459
20460     
20461     filterBy : function(fn, scope){
20462         this.snapshot = this.snapshot || this.data;
20463         this.data = this.queryBy(fn, scope||this);
20464         this.fireEvent('datachanged', this);
20465     },
20466
20467     
20468     query : function(property, value, anyMatch, caseSensitive){
20469         var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
20470         return fn ? this.queryBy(fn) : this.data.clone();
20471     },
20472
20473     
20474     queryBy : function(fn, scope){
20475         var data = this.snapshot || this.data;
20476         return data.filterBy(fn, scope||this);
20477     },
20478
20479     
20480     find : function(property, value, start, anyMatch, caseSensitive){
20481         var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
20482         return fn ? this.data.findIndexBy(fn, null, start) : -1;
20483     },
20484
20485     
20486     findExact: function(property, value, start){
20487         return this.data.findIndexBy(function(rec){
20488             return rec.get(property) === value;
20489         }, this, start);
20490     },
20491
20492     
20493     findBy : function(fn, scope, start){
20494         return this.data.findIndexBy(fn, scope, start);
20495     },
20496
20497     
20498     collect : function(dataIndex, allowNull, bypassFilter){
20499         var d = (bypassFilter === true && this.snapshot) ?
20500                 this.snapshot.items : this.data.items;
20501         var v, sv, r = [], l = {};
20502         for(var i = 0, len = d.length; i < len; i++){
20503             v = d[i].data[dataIndex];
20504             sv = String(v);
20505             if((allowNull || !Ext.isEmpty(v)) && !l[sv]){
20506                 l[sv] = true;
20507                 r[r.length] = v;
20508             }
20509         }
20510         return r;
20511     },
20512
20513     
20514     clearFilter : function(suppressEvent){
20515         if(this.isFiltered()){
20516             this.data = this.snapshot;
20517             delete this.snapshot;
20518             if(suppressEvent !== true){
20519                 this.fireEvent('datachanged', this);
20520             }
20521         }
20522     },
20523
20524     
20525     isFiltered : function(){
20526         return this.snapshot && this.snapshot != this.data;
20527     },
20528
20529     
20530     afterEdit : function(record){
20531         if(this.modified.indexOf(record) == -1){
20532             this.modified.push(record);
20533         }
20534         this.fireEvent('update', this, record, Ext.data.Record.EDIT);
20535     },
20536
20537     
20538     afterReject : function(record){
20539         this.modified.remove(record);
20540         this.fireEvent('update', this, record, Ext.data.Record.REJECT);
20541     },
20542
20543     
20544     afterCommit : function(record){
20545         this.modified.remove(record);
20546         this.fireEvent('update', this, record, Ext.data.Record.COMMIT);
20547     },
20548
20549     
20550     commitChanges : function(){
20551         var m = this.modified.slice(0);
20552         this.modified = [];
20553         for(var i = 0, len = m.length; i < len; i++){
20554             m[i].commit();
20555         }
20556     },
20557
20558     
20559     rejectChanges : function(){
20560         var m = this.modified.slice(0);
20561         this.modified = [];
20562         for(var i = 0, len = m.length; i < len; i++){
20563             m[i].reject();
20564         }
20565         var m = this.removed.slice(0).reverse();
20566         this.removed = [];
20567         for(var i = 0, len = m.length; i < len; i++){
20568             this.insert(m[i].lastIndex||0, m[i]);
20569             m[i].reject();
20570         }
20571     },
20572
20573     
20574     onMetaChange : function(meta){
20575         this.recordType = this.reader.recordType;
20576         this.fields = this.recordType.prototype.fields;
20577         delete this.snapshot;
20578         if(this.reader.meta.sortInfo){
20579             this.sortInfo = this.reader.meta.sortInfo;
20580         }else if(this.sortInfo  && !this.fields.get(this.sortInfo.field)){
20581             delete this.sortInfo;
20582         }
20583         if(this.writer){
20584             this.writer.meta = this.reader.meta;
20585         }
20586         this.modified = [];
20587         this.fireEvent('metachange', this, this.reader.meta);
20588     },
20589
20590     
20591     findInsertIndex : function(record){
20592         this.suspendEvents();
20593         var data = this.data.clone();
20594         this.data.add(record);
20595         this.applySort();
20596         var index = this.data.indexOf(record);
20597         this.data = data;
20598         this.resumeEvents();
20599         return index;
20600     },
20601
20602     
20603     setBaseParam : function (name, value){
20604         this.baseParams = this.baseParams || {};
20605         this.baseParams[name] = value;
20606     }
20607 });
20608
20609 Ext.reg('store', Ext.data.Store);
20610
20611
20612 Ext.data.Store.Error = Ext.extend(Ext.Error, {
20613     name: 'Ext.data.Store'
20614 });
20615 Ext.apply(Ext.data.Store.Error.prototype, {
20616     lang: {
20617         'writer-undefined' : 'Attempted to execute a write-action without a DataWriter installed.'
20618     }
20619 });
20620
20621 Ext.data.Field = function(config){
20622     if(typeof config == "string"){
20623         config = {name: config};
20624     }
20625     Ext.apply(this, config);
20626
20627     if(!this.type){
20628         this.type = "auto";
20629     }
20630
20631     var st = Ext.data.SortTypes;
20632     
20633     if(typeof this.sortType == "string"){
20634         this.sortType = st[this.sortType];
20635     }
20636
20637     
20638     if(!this.sortType){
20639         switch(this.type){
20640             case "string":
20641                 this.sortType = st.asUCString;
20642                 break;
20643             case "date":
20644                 this.sortType = st.asDate;
20645                 break;
20646             default:
20647                 this.sortType = st.none;
20648         }
20649     }
20650
20651     
20652     var stripRe = /[\$,%]/g;
20653
20654     
20655     
20656     if(!this.convert){
20657         var cv, dateFormat = this.dateFormat;
20658         switch(this.type){
20659             case "":
20660             case "auto":
20661             case undefined:
20662                 cv = function(v){ return v; };
20663                 break;
20664             case "string":
20665                 cv = function(v){ return (v === undefined || v === null) ? '' : String(v); };
20666                 break;
20667             case "int":
20668                 cv = function(v){
20669                     return v !== undefined && v !== null && v !== '' ?
20670                         parseInt(String(v).replace(stripRe, ""), 10) : '';
20671                     };
20672                 break;
20673             case "float":
20674                 cv = function(v){
20675                     return v !== undefined && v !== null && v !== '' ?
20676                         parseFloat(String(v).replace(stripRe, ""), 10) : '';
20677                     };
20678                 break;
20679             case "bool":
20680                 cv = function(v){ return v === true || v === "true" || v == 1; };
20681                 break;
20682             case "date":
20683                 cv = function(v){
20684                     if(!v){
20685                         return '';
20686                     }
20687                     if(Ext.isDate(v)){
20688                         return v;
20689                     }
20690                     if(dateFormat){
20691                         if(dateFormat == "timestamp"){
20692                             return new Date(v*1000);
20693                         }
20694                         if(dateFormat == "time"){
20695                             return new Date(parseInt(v, 10));
20696                         }
20697                         return Date.parseDate(v, dateFormat);
20698                     }
20699                     var parsed = Date.parse(v);
20700                     return parsed ? new Date(parsed) : null;
20701                 };
20702                 break;
20703             default:
20704                 cv = function(v){ return v; };
20705                 break;
20706
20707         }
20708         this.convert = cv;
20709     }
20710 };
20711
20712 Ext.data.Field.prototype = {
20713     
20714     
20715     
20716     
20717     dateFormat: null,
20718     
20719     defaultValue: "",
20720     
20721     mapping: null,
20722     
20723     sortType : null,
20724     
20725     sortDir : "ASC",
20726     
20727     allowBlank : true
20728 };
20729 Ext.data.DataReader = function(meta, recordType){
20730     
20731     this.meta = meta;
20732     
20733     this.recordType = Ext.isArray(recordType) ?
20734         Ext.data.Record.create(recordType) : recordType;
20735
20736     
20737     if (this.recordType){
20738         this.buildExtractors();
20739     }
20740 };
20741
20742 Ext.data.DataReader.prototype = {
20743     
20744     
20745     getTotal: Ext.emptyFn,
20746     
20747     getRoot: Ext.emptyFn,
20748     
20749     getMessage: Ext.emptyFn,
20750     
20751     getSuccess: Ext.emptyFn,
20752     
20753     getId: Ext.emptyFn,
20754     
20755     buildExtractors : Ext.emptyFn,
20756     
20757     extractData : Ext.emptyFn,
20758     
20759     extractValues : Ext.emptyFn,
20760
20761     
20762     realize: function(rs, data){
20763         if (Ext.isArray(rs)) {
20764             for (var i = rs.length - 1; i >= 0; i--) {
20765                 
20766                 if (Ext.isArray(data)) {
20767                     this.realize(rs.splice(i,1).shift(), data.splice(i,1).shift());
20768                 }
20769                 else {
20770                     
20771                     
20772                     this.realize(rs.splice(i,1).shift(), data);
20773                 }
20774             }
20775         }
20776         else {
20777             
20778             if (Ext.isArray(data) && data.length == 1) {
20779                 data = data.shift();
20780             }
20781             if (!this.isData(data)) {
20782                 
20783                 
20784                 throw new Ext.data.DataReader.Error('realize', rs);
20785             }
20786             rs.phantom = false; 
20787             rs._phid = rs.id;  
20788             rs.id = this.getId(data);
20789
20790             rs.fields.each(function(f) {
20791                 if (data[f.name] !== f.defaultValue) {
20792                     rs.data[f.name] = data[f.name];
20793                 }
20794             });
20795             rs.commit();
20796         }
20797     },
20798
20799     
20800     update : function(rs, data) {
20801         if (Ext.isArray(rs)) {
20802             for (var i=rs.length-1; i >= 0; i--) {
20803                 if (Ext.isArray(data)) {
20804                     this.update(rs.splice(i,1).shift(), data.splice(i,1).shift());
20805                 }
20806                 else {
20807                     
20808                     
20809                     this.update(rs.splice(i,1).shift(), data);
20810                 }
20811             }
20812         }
20813         else {
20814             
20815             if (Ext.isArray(data) && data.length == 1) {
20816                 data = data.shift();
20817             }
20818             if (this.isData(data)) {
20819                 rs.fields.each(function(f) {
20820                     if (data[f.name] !== f.defaultValue) {
20821                         rs.data[f.name] = data[f.name];
20822                     }
20823                 });
20824             }
20825             rs.commit();
20826         }
20827     },
20828
20829     
20830     extractData : function(root, returnRecords) {
20831         
20832         var rawName = (this instanceof Ext.data.JsonReader) ? 'json' : 'node';
20833
20834         var rs = [];
20835
20836         
20837         
20838         if (this.isData(root) && !(this instanceof Ext.data.XmlReader)) {
20839             root = [root];
20840         }
20841         var f       = this.recordType.prototype.fields,
20842             fi      = f.items,
20843             fl      = f.length,
20844             rs      = [];
20845         if (returnRecords === true) {
20846             var Record = this.recordType;
20847             for (var i = 0; i < root.length; i++) {
20848                 var n = root[i];
20849                 var record = new Record(this.extractValues(n, fi, fl), this.getId(n));
20850                 record[rawName] = n;    
20851                 rs.push(record);
20852             }
20853         }
20854         else {
20855             for (var i = 0; i < root.length; i++) {
20856                 var data = this.extractValues(root[i], fi, fl);
20857                 data[this.meta.idProperty] = this.getId(root[i]);
20858                 rs.push(data);
20859             }
20860         }
20861         return rs;
20862     },
20863
20864     
20865     isData : function(data) {
20866         return (data && Ext.isObject(data) && !Ext.isEmpty(this.getId(data))) ? true : false;
20867     },
20868
20869     
20870     onMetaChange : function(meta){
20871         delete this.ef;
20872         this.meta = meta;
20873         this.recordType = Ext.data.Record.create(meta.fields);
20874         this.buildExtractors();
20875     }
20876 };
20877
20878
20879 Ext.data.DataReader.Error = Ext.extend(Ext.Error, {
20880     constructor : function(message, arg) {
20881         this.arg = arg;
20882         Ext.Error.call(this, message);
20883     },
20884     name: 'Ext.data.DataReader'
20885 });
20886 Ext.apply(Ext.data.DataReader.Error.prototype, {
20887     lang : {
20888         'update': "#update received invalid data from server.  Please see docs for DataReader#update and review your DataReader configuration.",
20889         'realize': "#realize was called with invalid remote-data.  Please see the docs for DataReader#realize and review your DataReader configuration.",
20890         'invalid-response': "#readResponse received an invalid response from the server."
20891     }
20892 });
20893
20894 Ext.data.DataWriter = function(config){
20895     Ext.apply(this, config);
20896 };
20897 Ext.data.DataWriter.prototype = {
20898
20899     
20900     writeAllFields : false,
20901     
20902     listful : false,    
20903
20904     
20905     apply : function(params, baseParams, action, rs) {
20906         var data    = [],
20907         renderer    = action + 'Record';
20908         
20909         if (Ext.isArray(rs)) {
20910             Ext.each(rs, function(rec){
20911                 data.push(this[renderer](rec));
20912             }, this);
20913         }
20914         else if (rs instanceof Ext.data.Record) {
20915             data = this[renderer](rs);
20916         }
20917         this.render(params, baseParams, data);
20918     },
20919
20920     
20921     render : Ext.emptyFn,
20922
20923     
20924     updateRecord : Ext.emptyFn,
20925
20926     
20927     createRecord : Ext.emptyFn,
20928
20929     
20930     destroyRecord : Ext.emptyFn,
20931
20932     
20933     toHash : function(rec, config) {
20934         var map = rec.fields.map,
20935             data = {},
20936             raw = (this.writeAllFields === false && rec.phantom === false) ? rec.getChanges() : rec.data,
20937             m;
20938         Ext.iterate(raw, function(prop, value){
20939             if((m = map[prop])){
20940                 data[m.mapping ? m.mapping : m.name] = value;
20941             }
20942         });
20943         
20944         
20945         
20946         if (rec.phantom) {
20947             if (rec.fields.containsKey(this.meta.idProperty) && Ext.isEmpty(rec.data[this.meta.idProperty])) {
20948                 delete data[this.meta.idProperty];
20949             }
20950         } else {
20951             data[this.meta.idProperty] = rec.id
20952         }
20953         return data;
20954     },
20955
20956     
20957     toArray : function(data) {
20958         var fields = [];
20959         Ext.iterate(data, function(k, v) {fields.push({name: k, value: v});},this);
20960         return fields;
20961     }
20962 };
20963 Ext.data.DataProxy = function(conn){
20964     
20965     
20966     conn = conn || {};
20967
20968     
20969     
20970     
20971
20972     this.api     = conn.api;
20973     this.url     = conn.url;
20974     this.restful = conn.restful;
20975     this.listeners = conn.listeners;
20976
20977     
20978     this.prettyUrls = conn.prettyUrls;
20979
20980     
20981
20982     this.addEvents(
20983         
20984         'exception',
20985         
20986         'beforeload',
20987         
20988         'load',
20989         
20990         'loadexception',
20991         
20992         'beforewrite',
20993         
20994         'write'
20995     );
20996     Ext.data.DataProxy.superclass.constructor.call(this);
20997
20998     
20999     try {
21000         Ext.data.Api.prepare(this);
21001     } catch (e) {
21002         if (e instanceof Ext.data.Api.Error) {
21003             e.toConsole();
21004         }
21005     }
21006     
21007     Ext.data.DataProxy.relayEvents(this, ['beforewrite', 'write', 'exception']);
21008 };
21009
21010 Ext.extend(Ext.data.DataProxy, Ext.util.Observable, {
21011     
21012     restful: false,
21013
21014     
21015     setApi : function() {
21016         if (arguments.length == 1) {
21017             var valid = Ext.data.Api.isValid(arguments[0]);
21018             if (valid === true) {
21019                 this.api = arguments[0];
21020             }
21021             else {
21022                 throw new Ext.data.Api.Error('invalid', valid);
21023             }
21024         }
21025         else if (arguments.length == 2) {
21026             if (!Ext.data.Api.isAction(arguments[0])) {
21027                 throw new Ext.data.Api.Error('invalid', arguments[0]);
21028             }
21029             this.api[arguments[0]] = arguments[1];
21030         }
21031         Ext.data.Api.prepare(this);
21032     },
21033
21034     
21035     isApiAction : function(action) {
21036         return (this.api[action]) ? true : false;
21037     },
21038
21039     
21040     request : function(action, rs, params, reader, callback, scope, options) {
21041         if (!this.api[action] && !this.load) {
21042             throw new Ext.data.DataProxy.Error('action-undefined', action);
21043         }
21044         params = params || {};
21045         if ((action === Ext.data.Api.actions.read) ? this.fireEvent("beforeload", this, params) : this.fireEvent("beforewrite", this, action, rs, params) !== false) {
21046             this.doRequest.apply(this, arguments);
21047         }
21048         else {
21049             callback.call(scope || this, null, options, false);
21050         }
21051     },
21052
21053
21054     
21055     load : null,
21056
21057     
21058     doRequest : function(action, rs, params, reader, callback, scope, options) {
21059         
21060         
21061         
21062         this.load(params, reader, callback, scope, options);
21063     },
21064
21065     
21066     onRead : Ext.emptyFn,
21067     
21068     onWrite : Ext.emptyFn,
21069     
21070     buildUrl : function(action, record) {
21071         record = record || null;
21072
21073         
21074         
21075         
21076         var url = (this.conn && this.conn.url) ? this.conn.url : (this.api[action]) ? this.api[action].url : this.url;
21077         if (!url) {
21078             throw new Ext.data.Api.Error('invalid-url', action);
21079         }
21080
21081         
21082         
21083         
21084         
21085         
21086         
21087         var provides = null;
21088         var m = url.match(/(.*)(\.json|\.xml|\.html)$/);
21089         if (m) {
21090             provides = m[2];    
21091             url      = m[1];    
21092         }
21093         
21094         if ((this.restful === true || this.prettyUrls === true) && record instanceof Ext.data.Record && !record.phantom) {
21095             url += '/' + record.id;
21096         }
21097         return (provides === null) ? url : url + provides;
21098     },
21099
21100     
21101     destroy: function(){
21102         this.purgeListeners();
21103     }
21104 });
21105
21106
21107
21108 Ext.apply(Ext.data.DataProxy, Ext.util.Observable.prototype);
21109 Ext.util.Observable.call(Ext.data.DataProxy);
21110
21111
21112 Ext.data.DataProxy.Error = Ext.extend(Ext.Error, {
21113     constructor : function(message, arg) {
21114         this.arg = arg;
21115         Ext.Error.call(this, message);
21116     },
21117     name: 'Ext.data.DataProxy'
21118 });
21119 Ext.apply(Ext.data.DataProxy.Error.prototype, {
21120     lang: {
21121         'action-undefined': "DataProxy attempted to execute an API-action but found an undefined url / function.  Please review your Proxy url/api-configuration.",
21122         'api-invalid': 'Recieved an invalid API-configuration.  Please ensure your proxy API-configuration contains only the actions from Ext.data.Api.actions.'
21123     }
21124 });
21125
21126
21127
21128 Ext.data.Request = function(params) {
21129     Ext.apply(this, params);
21130 };
21131 Ext.data.Request.prototype = {
21132     
21133     action : undefined,
21134     
21135     rs : undefined,
21136     
21137     params: undefined,
21138     
21139     callback : Ext.emptyFn,
21140     
21141     scope : undefined,
21142     
21143     reader : undefined
21144 };
21145
21146 Ext.data.Response = function(params) {
21147     Ext.apply(this, params);
21148 };
21149 Ext.data.Response.prototype = {
21150     
21151     action: undefined,
21152     
21153     success : undefined,
21154     
21155     message : undefined,
21156     
21157     data: undefined,
21158     
21159     raw: undefined,
21160     
21161     records: undefined
21162 };
21163
21164 Ext.data.ScriptTagProxy = function(config){
21165     Ext.apply(this, config);
21166
21167     Ext.data.ScriptTagProxy.superclass.constructor.call(this, config);
21168
21169     this.head = document.getElementsByTagName("head")[0];
21170
21171     
21172 };
21173
21174 Ext.data.ScriptTagProxy.TRANS_ID = 1000;
21175
21176 Ext.extend(Ext.data.ScriptTagProxy, Ext.data.DataProxy, {
21177     
21178     
21179     timeout : 30000,
21180     
21181     callbackParam : "callback",
21182     
21183     nocache : true,
21184
21185     
21186     doRequest : function(action, rs, params, reader, callback, scope, arg) {
21187         var p = Ext.urlEncode(Ext.apply(params, this.extraParams));
21188
21189         var url = this.buildUrl(action, rs);
21190         if (!url) {
21191             throw new Ext.data.Api.Error('invalid-url', url);
21192         }
21193         url = Ext.urlAppend(url, p);
21194
21195         if(this.nocache){
21196             url = Ext.urlAppend(url, '_dc=' + (new Date().getTime()));
21197         }
21198         var transId = ++Ext.data.ScriptTagProxy.TRANS_ID;
21199         var trans = {
21200             id : transId,
21201             action: action,
21202             cb : "stcCallback"+transId,
21203             scriptId : "stcScript"+transId,
21204             params : params,
21205             arg : arg,
21206             url : url,
21207             callback : callback,
21208             scope : scope,
21209             reader : reader
21210         };
21211         window[trans.cb] = this.createCallback(action, rs, trans);
21212         url += String.format("&{0}={1}", this.callbackParam, trans.cb);
21213         if(this.autoAbort !== false){
21214             this.abort();
21215         }
21216
21217         trans.timeoutId = this.handleFailure.defer(this.timeout, this, [trans]);
21218
21219         var script = document.createElement("script");
21220         script.setAttribute("src", url);
21221         script.setAttribute("type", "text/javascript");
21222         script.setAttribute("id", trans.scriptId);
21223         this.head.appendChild(script);
21224
21225         this.trans = trans;
21226     },
21227
21228     
21229     createCallback : function(action, rs, trans) {
21230         var self = this;
21231         return function(res) {
21232             self.trans = false;
21233             self.destroyTrans(trans, true);
21234             if (action === Ext.data.Api.actions.read) {
21235                 self.onRead.call(self, action, trans, res);
21236             } else {
21237                 self.onWrite.call(self, action, trans, res, rs);
21238             }
21239         };
21240     },
21241     
21242     onRead : function(action, trans, res) {
21243         var result;
21244         try {
21245             result = trans.reader.readRecords(res);
21246         }catch(e){
21247             
21248             this.fireEvent("loadexception", this, trans, res, e);
21249
21250             this.fireEvent('exception', this, 'response', action, trans, res, e);
21251             trans.callback.call(trans.scope||window, null, trans.arg, false);
21252             return;
21253         }
21254         if (result.success === false) {
21255             
21256             this.fireEvent('loadexception', this, trans, res);
21257
21258             this.fireEvent('exception', this, 'remote', action, trans, res, null);
21259         } else {
21260             this.fireEvent("load", this, res, trans.arg);
21261         }
21262         trans.callback.call(trans.scope||window, result, trans.arg, result.success);
21263     },
21264     
21265     onWrite : function(action, trans, response, rs) {
21266         var reader = trans.reader;
21267         try {
21268             
21269             var res = reader.readResponse(action, response);
21270         } catch (e) {
21271             this.fireEvent('exception', this, 'response', action, trans, res, e);
21272             trans.callback.call(trans.scope||window, null, res, false);
21273             return;
21274         }
21275         if(!res.success === true){
21276             this.fireEvent('exception', this, 'remote', action, trans, res, rs);
21277             trans.callback.call(trans.scope||window, null, res, false);
21278             return;
21279         }
21280         this.fireEvent("write", this, action, res.data, res, rs, trans.arg );
21281         trans.callback.call(trans.scope||window, res.data, res, true);
21282     },
21283
21284     
21285     isLoading : function(){
21286         return this.trans ? true : false;
21287     },
21288
21289     
21290     abort : function(){
21291         if(this.isLoading()){
21292             this.destroyTrans(this.trans);
21293         }
21294     },
21295
21296     
21297     destroyTrans : function(trans, isLoaded){
21298         this.head.removeChild(document.getElementById(trans.scriptId));
21299         clearTimeout(trans.timeoutId);
21300         if(isLoaded){
21301             window[trans.cb] = undefined;
21302             try{
21303                 delete window[trans.cb];
21304             }catch(e){}
21305         }else{
21306             
21307             window[trans.cb] = function(){
21308                 window[trans.cb] = undefined;
21309                 try{
21310                     delete window[trans.cb];
21311                 }catch(e){}
21312             };
21313         }
21314     },
21315
21316     
21317     handleFailure : function(trans){
21318         this.trans = false;
21319         this.destroyTrans(trans, false);
21320         if (trans.action === Ext.data.Api.actions.read) {
21321             
21322             this.fireEvent("loadexception", this, null, trans.arg);
21323         }
21324
21325         this.fireEvent('exception', this, 'response', trans.action, {
21326             response: null,
21327             options: trans.arg
21328         });
21329         trans.callback.call(trans.scope||window, null, trans.arg, false);
21330     },
21331
21332     
21333     destroy: function(){
21334         this.abort();
21335         Ext.data.ScriptTagProxy.superclass.destroy.call(this);
21336     }
21337 });
21338 Ext.data.HttpProxy = function(conn){
21339     Ext.data.HttpProxy.superclass.constructor.call(this, conn);
21340
21341     
21342     this.conn = conn;
21343
21344     
21345     
21346     
21347     
21348     this.conn.url = null;
21349
21350     this.useAjax = !conn || !conn.events;
21351
21352     
21353     var actions = Ext.data.Api.actions;
21354     this.activeRequest = {};
21355     for (var verb in actions) {
21356         this.activeRequest[actions[verb]] = undefined;
21357     }
21358 };
21359
21360 Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {
21361     
21362     getConnection : function() {
21363         return this.useAjax ? Ext.Ajax : this.conn;
21364     },
21365
21366     
21367     setUrl : function(url, makePermanent) {
21368         this.conn.url = url;
21369         if (makePermanent === true) {
21370             this.url = url;
21371             this.api = null;
21372             Ext.data.Api.prepare(this);
21373         }
21374     },
21375
21376     
21377     doRequest : function(action, rs, params, reader, cb, scope, arg) {
21378         var  o = {
21379             method: (this.api[action]) ? this.api[action]['method'] : undefined,
21380             request: {
21381                 callback : cb,
21382                 scope : scope,
21383                 arg : arg
21384             },
21385             reader: reader,
21386             callback : this.createCallback(action, rs),
21387             scope: this
21388         };
21389
21390         
21391         
21392         if (params.jsonData) {
21393             o.jsonData = params.jsonData;
21394         } else if (params.xmlData) {
21395             o.xmlData = params.xmlData;
21396         } else {
21397             o.params = params || {};
21398         }
21399         
21400         
21401         
21402         this.conn.url = this.buildUrl(action, rs);
21403
21404         if(this.useAjax){
21405
21406             Ext.applyIf(o, this.conn);
21407
21408             
21409             if (this.activeRequest[action]) {
21410                 
21411                 
21412                 
21413                 
21414                 
21415             }
21416             this.activeRequest[action] = Ext.Ajax.request(o);
21417         }else{
21418             this.conn.request(o);
21419         }
21420         
21421         this.conn.url = null;
21422     },
21423
21424     
21425     createCallback : function(action, rs) {
21426         return function(o, success, response) {
21427             this.activeRequest[action] = undefined;
21428             if (!success) {
21429                 if (action === Ext.data.Api.actions.read) {
21430                     
21431                     
21432                     this.fireEvent('loadexception', this, o, response);
21433                 }
21434                 this.fireEvent('exception', this, 'response', action, o, response);
21435                 o.request.callback.call(o.request.scope, null, o.request.arg, false);
21436                 return;
21437             }
21438             if (action === Ext.data.Api.actions.read) {
21439                 this.onRead(action, o, response);
21440             } else {
21441                 this.onWrite(action, o, response, rs);
21442             }
21443         }
21444     },
21445
21446     
21447     onRead : function(action, o, response) {
21448         var result;
21449         try {
21450             result = o.reader.read(response);
21451         }catch(e){
21452             
21453             
21454             this.fireEvent('loadexception', this, o, response, e);
21455
21456             this.fireEvent('exception', this, 'response', action, o, response, e);
21457             o.request.callback.call(o.request.scope, null, o.request.arg, false);
21458             return;
21459         }
21460         if (result.success === false) {
21461             
21462             
21463             this.fireEvent('loadexception', this, o, response);
21464
21465             
21466             var res = o.reader.readResponse(action, response);
21467             this.fireEvent('exception', this, 'remote', action, o, res, null);
21468         }
21469         else {
21470             this.fireEvent('load', this, o, o.request.arg);
21471         }
21472         
21473         
21474         
21475         o.request.callback.call(o.request.scope, result, o.request.arg, result.success);
21476     },
21477     
21478     onWrite : function(action, o, response, rs) {
21479         var reader = o.reader;
21480         var res;
21481         try {
21482             res = reader.readResponse(action, response);
21483         } catch (e) {
21484             this.fireEvent('exception', this, 'response', action, o, response, e);
21485             o.request.callback.call(o.request.scope, null, o.request.arg, false);
21486             return;
21487         }
21488         if (res.success === false) {
21489             this.fireEvent('exception', this, 'remote', action, o, res, rs);
21490         } else {
21491             this.fireEvent('write', this, action, res.data, res, rs, o.request.arg);
21492         }
21493         
21494         
21495         
21496         o.request.callback.call(o.request.scope, res.data, res, res.success);
21497     },
21498
21499     
21500     destroy: function(){
21501         if(!this.useAjax){
21502             this.conn.abort();
21503         }else if(this.activeRequest){
21504             var actions = Ext.data.Api.actions;
21505             for (var verb in actions) {
21506                 if(this.activeRequest[actions[verb]]){
21507                     Ext.Ajax.abort(this.activeRequest[actions[verb]]);
21508                 }
21509             }
21510         }
21511         Ext.data.HttpProxy.superclass.destroy.call(this);
21512     }
21513 });
21514 Ext.data.MemoryProxy = function(data){
21515     
21516     var api = {};
21517     api[Ext.data.Api.actions.read] = true;
21518     Ext.data.MemoryProxy.superclass.constructor.call(this, {
21519         api: api
21520     });
21521     this.data = data;
21522 };
21523
21524 Ext.extend(Ext.data.MemoryProxy, Ext.data.DataProxy, {
21525     
21526
21527        
21528     doRequest : function(action, rs, params, reader, callback, scope, arg) {
21529         
21530         params = params || {};
21531         var result;
21532         try {
21533             result = reader.readRecords(this.data);
21534         }catch(e){
21535             
21536             this.fireEvent("loadexception", this, null, arg, e);
21537
21538             this.fireEvent('exception', this, 'response', action, arg, null, e);
21539             callback.call(scope, null, arg, false);
21540             return;
21541         }
21542         callback.call(scope, result, arg, true);
21543     }
21544 });
21545 Ext.data.JsonWriter = function(config) {
21546     Ext.data.JsonWriter.superclass.constructor.call(this, config);
21547
21548     
21549     
21550     if (this.returnJson != undefined) {
21551         this.encode = this.returnJson;
21552     }
21553 }
21554 Ext.extend(Ext.data.JsonWriter, Ext.data.DataWriter, {
21555     
21556     returnJson : undefined,
21557     
21558     encode : true,
21559
21560     
21561     render : function(params, baseParams, data) {
21562         if (this.encode === true) {
21563             
21564             Ext.apply(params, baseParams);
21565             params[this.meta.root] = Ext.encode(data);
21566         } else {
21567             
21568             var jdata = Ext.apply({}, baseParams);
21569             jdata[this.meta.root] = data;
21570             params.jsonData = jdata;
21571         }
21572     },
21573     
21574     createRecord : function(rec) {
21575        return this.toHash(rec);
21576     },
21577     
21578     updateRecord : function(rec) {
21579         return this.toHash(rec);
21580
21581     },
21582     
21583     destroyRecord : function(rec) {
21584         return rec.id;
21585     }
21586 });
21587 Ext.data.JsonReader = function(meta, recordType){
21588     meta = meta || {};
21589     
21590     
21591     
21592     
21593     Ext.applyIf(meta, {
21594         idProperty: 'id',
21595         successProperty: 'success',
21596         totalProperty: 'total'
21597     });
21598
21599     Ext.data.JsonReader.superclass.constructor.call(this, meta, recordType || meta.fields);
21600 };
21601 Ext.extend(Ext.data.JsonReader, Ext.data.DataReader, {
21602     
21603     
21604     read : function(response){
21605         var json = response.responseText;
21606         var o = Ext.decode(json);
21607         if(!o) {
21608             throw {message: 'JsonReader.read: Json object not found'};
21609         }
21610         return this.readRecords(o);
21611     },
21612
21613     
21614     readResponse : function(action, response) {
21615         var o = (response.responseText !== undefined) ? Ext.decode(response.responseText) : response;
21616         if(!o) {
21617             throw new Ext.data.JsonReader.Error('response');
21618         }
21619
21620         var root = this.getRoot(o);
21621         if (action === Ext.data.Api.actions.create) {
21622             var def = Ext.isDefined(root);
21623             if (def && Ext.isEmpty(root)) {
21624                 throw new Ext.data.JsonReader.Error('root-empty', this.meta.root);
21625             }
21626             else if (!def) {
21627                 throw new Ext.data.JsonReader.Error('root-undefined-response', this.meta.root);
21628             }
21629         }
21630
21631         
21632         var res = new Ext.data.Response({
21633             action: action,
21634             success: this.getSuccess(o),
21635             data: (root) ? this.extractData(root, false) : [],
21636             message: this.getMessage(o),
21637             raw: o
21638         });
21639
21640         
21641         if (Ext.isEmpty(res.success)) {
21642             throw new Ext.data.JsonReader.Error('successProperty-response', this.meta.successProperty);
21643         }
21644         return res;
21645     },
21646
21647     
21648     readRecords : function(o){
21649         
21650         this.jsonData = o;
21651         if(o.metaData){
21652             this.onMetaChange(o.metaData);
21653         }
21654         var s = this.meta, Record = this.recordType,
21655             f = Record.prototype.fields, fi = f.items, fl = f.length, v;
21656
21657         var root = this.getRoot(o), c = root.length, totalRecords = c, success = true;
21658         if(s.totalProperty){
21659             v = parseInt(this.getTotal(o), 10);
21660             if(!isNaN(v)){
21661                 totalRecords = v;
21662             }
21663         }
21664         if(s.successProperty){
21665             v = this.getSuccess(o);
21666             if(v === false || v === 'false'){
21667                 success = false;
21668             }
21669         }
21670
21671         
21672         return {
21673             success : success,
21674             records : this.extractData(root, true), 
21675             totalRecords : totalRecords
21676         };
21677     },
21678
21679     
21680     buildExtractors : function() {
21681         if(this.ef){
21682             return;
21683         }
21684         var s = this.meta, Record = this.recordType,
21685             f = Record.prototype.fields, fi = f.items, fl = f.length;
21686
21687         if(s.totalProperty) {
21688             this.getTotal = this.createAccessor(s.totalProperty);
21689         }
21690         if(s.successProperty) {
21691             this.getSuccess = this.createAccessor(s.successProperty);
21692         }
21693         if (s.messageProperty) {
21694             this.getMessage = this.createAccessor(s.messageProperty);
21695         }
21696         this.getRoot = s.root ? this.createAccessor(s.root) : function(p){return p;};
21697         if (s.id || s.idProperty) {
21698             var g = this.createAccessor(s.id || s.idProperty);
21699             this.getId = function(rec) {
21700                 var r = g(rec);
21701                 return (r === undefined || r === '') ? null : r;
21702             };
21703         } else {
21704             this.getId = function(){return null;};
21705         }
21706         var ef = [];
21707         for(var i = 0; i < fl; i++){
21708             f = fi[i];
21709             var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;
21710             ef.push(this.createAccessor(map));
21711         }
21712         this.ef = ef;
21713     },
21714
21715     
21716     simpleAccess : function(obj, subsc) {
21717         return obj[subsc];
21718     },
21719
21720     
21721     createAccessor : function(){
21722         var re = /[\[\.]/;
21723         return function(expr) {
21724             try {
21725                 return(re.test(expr)) ?
21726                 new Function('obj', 'return obj.' + expr) :
21727                 function(obj){
21728                     return obj[expr];
21729                 };
21730             } catch(e){}
21731             return Ext.emptyFn;
21732         };
21733     }(),
21734
21735     
21736     extractValues : function(data, items, len) {
21737         var f, values = {};
21738         for(var j = 0; j < len; j++){
21739             f = items[j];
21740             var v = this.ef[j](data);
21741             values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue, data);
21742         }
21743         return values;
21744     }
21745 });
21746
21747
21748 Ext.data.JsonReader.Error = Ext.extend(Ext.Error, {
21749     constructor : function(message, arg) {
21750         this.arg = arg;
21751         Ext.Error.call(this, message);
21752     },
21753     name : 'Ext.data.JsonReader'
21754 });
21755 Ext.apply(Ext.data.JsonReader.Error.prototype, {
21756     lang: {
21757         'response': 'An error occurred while json-decoding your server response',
21758         '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.',
21759         '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.',
21760         '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.',
21761         '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.'
21762     }
21763 });
21764
21765 Ext.data.ArrayReader = Ext.extend(Ext.data.JsonReader, {
21766     
21767     
21768     
21769     
21770     readRecords : function(o){
21771         this.arrayData = o;
21772         var s = this.meta,
21773             sid = s ? Ext.num(s.idIndex, s.id) : null,
21774             recordType = this.recordType,
21775             fields = recordType.prototype.fields,
21776             records = [],
21777             v;
21778
21779         var root = this.getRoot(o);
21780
21781         for(var i = 0, len = root.length; i < len; i++) {
21782             var n = root[i],
21783                 values = {},
21784                 id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null);
21785             for(var j = 0, jlen = fields.length; j < jlen; j++) {
21786                 var f = fields.items[j],
21787                     k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j;
21788                 v = n[k] !== undefined ? n[k] : f.defaultValue;
21789                 v = f.convert(v, n);
21790                 values[f.name] = v;
21791             }
21792             var record = new recordType(values, id);
21793             record.json = n;
21794             records[records.length] = record;
21795         }
21796
21797         var totalRecords = records.length;
21798
21799         if(s.totalProperty) {
21800             v = parseInt(this.getTotal(o), 10);
21801             if(!isNaN(v)) {
21802                 totalRecords = v;
21803             }
21804         }
21805
21806         return {
21807             records : records,
21808             totalRecords : totalRecords
21809         };
21810     }
21811 });
21812 Ext.data.ArrayStore = Ext.extend(Ext.data.Store, {
21813     
21814     constructor: function(config){
21815         Ext.data.ArrayStore.superclass.constructor.call(this, Ext.apply(config, {
21816             reader: new Ext.data.ArrayReader(config)
21817         }));
21818     },
21819
21820     loadData : function(data, append){
21821         if(this.expandData === true){
21822             var r = [];
21823             for(var i = 0, len = data.length; i < len; i++){
21824                 r[r.length] = [data[i]];
21825             }
21826             data = r;
21827         }
21828         Ext.data.ArrayStore.superclass.loadData.call(this, data, append);
21829     }
21830 });
21831 Ext.reg('arraystore', Ext.data.ArrayStore);
21832
21833
21834 Ext.data.SimpleStore = Ext.data.ArrayStore;
21835 Ext.reg('simplestore', Ext.data.SimpleStore);
21836 Ext.data.JsonStore = Ext.extend(Ext.data.Store, {
21837     
21838     constructor: function(config){
21839         Ext.data.JsonStore.superclass.constructor.call(this, Ext.apply(config, {
21840             reader: new Ext.data.JsonReader(config)
21841         }));
21842     }
21843 });
21844 Ext.reg('jsonstore', Ext.data.JsonStore);
21845 Ext.data.XmlWriter = function(params) {
21846     Ext.data.XmlWriter.superclass.constructor.apply(this, arguments);
21847     
21848     this.tpl = (typeof(this.tpl) === 'string') ? new Ext.XTemplate(this.tpl).compile() : this.tpl.compile();
21849 };
21850 Ext.extend(Ext.data.XmlWriter, Ext.data.DataWriter, {
21851     
21852     documentRoot: 'xrequest',
21853     
21854     forceDocumentRoot: false,
21855     
21856     root: 'records',
21857     
21858     xmlVersion : '1.0',
21859     
21860     xmlEncoding: 'ISO-8859-15',
21861     
21862     
21863     tpl: '<tpl for="."><' + '?xml version="{version}" encoding="{encoding}"?' + '><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>',
21864
21865     
21866     render : function(params, baseParams, data) {
21867         baseParams = this.toArray(baseParams);
21868         params.xmlData = this.tpl.applyTemplate({
21869             version: this.xmlVersion,
21870             encoding: this.xmlEncoding,
21871             documentRoot: (baseParams.length > 0 || this.forceDocumentRoot === true) ? this.documentRoot : false,
21872             record: this.meta.record,
21873             root: this.root,
21874             baseParams: baseParams,
21875             records: (Ext.isArray(data[0])) ? data : [data]
21876         });
21877     },
21878
21879     
21880     createRecord : function(rec) {
21881         return this.toArray(this.toHash(rec));
21882     },
21883
21884     
21885     updateRecord : function(rec) {
21886         return this.toArray(this.toHash(rec));
21887
21888     },
21889     
21890     destroyRecord : function(rec) {
21891         var data = {};
21892         data[this.meta.idProperty] = rec.id;
21893         return this.toArray(data);
21894     }
21895 });
21896
21897
21898 Ext.data.XmlReader = function(meta, recordType){
21899     meta = meta || {};
21900
21901     
21902     Ext.applyIf(meta, {
21903         idProperty: meta.idProperty || meta.idPath || meta.id,
21904         successProperty: meta.successProperty || meta.success
21905     });
21906
21907     Ext.data.XmlReader.superclass.constructor.call(this, meta, recordType || meta.fields);
21908 };
21909 Ext.extend(Ext.data.XmlReader, Ext.data.DataReader, {
21910     
21911     read : function(response){
21912         var doc = response.responseXML;
21913         if(!doc) {
21914             throw {message: "XmlReader.read: XML Document not available"};
21915         }
21916         return this.readRecords(doc);
21917     },
21918
21919     
21920     readRecords : function(doc){
21921         
21922         this.xmlData = doc;
21923
21924         var root    = doc.documentElement || doc,
21925             q       = Ext.DomQuery,
21926             totalRecords = 0,
21927             success = true;
21928
21929         if(this.meta.totalProperty){
21930             totalRecords = this.getTotal(root, 0);
21931         }
21932         if(this.meta.successProperty){
21933             success = this.getSuccess(root);
21934         }
21935
21936         var records = this.extractData(q.select(this.meta.record, root), true); 
21937
21938         
21939         return {
21940             success : success,
21941             records : records,
21942             totalRecords : totalRecords || records.length
21943         };
21944     },
21945
21946     
21947     readResponse : function(action, response) {
21948         var q   = Ext.DomQuery,
21949         doc     = response.responseXML;
21950
21951         
21952         var res = new Ext.data.Response({
21953             action: action,
21954             success : this.getSuccess(doc),
21955             message: this.getMessage(doc),
21956             data: this.extractData(q.select(this.meta.record, doc) || q.select(this.meta.root, doc), false),
21957             raw: doc
21958         });
21959
21960         if (Ext.isEmpty(res.success)) {
21961             throw new Ext.data.DataReader.Error('successProperty-response', this.meta.successProperty);
21962         }
21963
21964         
21965         if (action === Ext.data.Api.actions.create) {
21966             var def = Ext.isDefined(res.data);
21967             if (def && Ext.isEmpty(res.data)) {
21968                 throw new Ext.data.JsonReader.Error('root-empty', this.meta.root);
21969             }
21970             else if (!def) {
21971                 throw new Ext.data.JsonReader.Error('root-undefined-response', this.meta.root);
21972             }
21973         }
21974         return res;
21975     },
21976
21977     getSuccess : function() {
21978         return true;
21979     },
21980
21981     
21982     buildExtractors : function() {
21983         if(this.ef){
21984             return;
21985         }
21986         var s       = this.meta,
21987             Record  = this.recordType,
21988             f       = Record.prototype.fields,
21989             fi      = f.items,
21990             fl      = f.length;
21991
21992         if(s.totalProperty) {
21993             this.getTotal = this.createAccessor(s.totalProperty);
21994         }
21995         if(s.successProperty) {
21996             this.getSuccess = this.createAccessor(s.successProperty);
21997         }
21998         if (s.messageProperty) {
21999             this.getMessage = this.createAccessor(s.messageProperty);
22000         }
22001         this.getRoot = function(res) {
22002             return (!Ext.isEmpty(res[this.meta.record])) ? res[this.meta.record] : res[this.meta.root];
22003         }
22004         if (s.idPath || s.idProperty) {
22005             var g = this.createAccessor(s.idPath || s.idProperty);
22006             this.getId = function(rec) {
22007                 var id = g(rec) || rec.id;
22008                 return (id === undefined || id === '') ? null : id;
22009             };
22010         } else {
22011             this.getId = function(){return null;};
22012         }
22013         var ef = [];
22014         for(var i = 0; i < fl; i++){
22015             f = fi[i];
22016             var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;
22017             ef.push(this.createAccessor(map));
22018         }
22019         this.ef = ef;
22020     },
22021
22022     
22023     createAccessor : function(){
22024         var q = Ext.DomQuery;
22025         return function(key) {
22026             switch(key) {
22027                 case this.meta.totalProperty:
22028                     return function(root, def){
22029                         return q.selectNumber(key, root, def);
22030                     }
22031                     break;
22032                 case this.meta.successProperty:
22033                     return function(root, def) {
22034                         var sv = q.selectValue(key, root, true);
22035                         var success = sv !== false && sv !== 'false';
22036                         return success;
22037                     }
22038                     break;
22039                 default:
22040                     return function(root, def) {
22041                         return q.selectValue(key, root, def);
22042                     }
22043                     break;
22044             }
22045         };
22046     }(),
22047
22048     
22049     extractValues : function(data, items, len) {
22050         var f, values = {};
22051         for(var j = 0; j < len; j++){
22052             f = items[j];
22053             var v = this.ef[j](data);
22054             values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue, data);
22055         }
22056         return values;
22057     }
22058 });
22059 Ext.data.XmlStore = Ext.extend(Ext.data.Store, {
22060     
22061     constructor: function(config){
22062         Ext.data.XmlStore.superclass.constructor.call(this, Ext.apply(config, {
22063             reader: new Ext.data.XmlReader(config)
22064         }));
22065     }
22066 });
22067 Ext.reg('xmlstore', Ext.data.XmlStore);
22068 Ext.data.GroupingStore = Ext.extend(Ext.data.Store, {
22069     
22070     
22071     constructor: function(config){
22072         Ext.data.GroupingStore.superclass.constructor.call(this, config);
22073         this.applyGroupField();
22074     },
22075     
22076     
22077     
22078     remoteGroup : false,
22079     
22080     groupOnSort:false,
22081
22082         groupDir : 'ASC',
22083         
22084     
22085     clearGrouping : function(){
22086         this.groupField = false;
22087         if(this.remoteGroup){
22088             if(this.baseParams){
22089                 delete this.baseParams.groupBy;
22090             }
22091             var lo = this.lastOptions;
22092             if(lo && lo.params){
22093                 delete lo.params.groupBy;
22094             }
22095             this.reload();
22096         }else{
22097             this.applySort();
22098             this.fireEvent('datachanged', this);
22099         }
22100     },
22101
22102     
22103     groupBy : function(field, forceRegroup, direction){
22104                 direction = direction ? (String(direction).toUpperCase() == 'DESC' ? 'DESC' : 'ASC') : this.groupDir;
22105         if(this.groupField == field && this.groupDir == direction && !forceRegroup){
22106             return; 
22107         }
22108         this.groupField = field;
22109                 this.groupDir = direction;
22110         this.applyGroupField();
22111         if(this.groupOnSort){
22112             this.sort(field, direction);
22113             return;
22114         }
22115         if(this.remoteGroup){
22116             this.reload();
22117         }else{
22118             var si = this.sortInfo || {};
22119             if(si.field != field || si.direction != direction){
22120                 this.applySort();
22121             }else{
22122                 this.sortData(field, direction);
22123             }
22124             this.fireEvent('datachanged', this);
22125         }
22126     },
22127     
22128     
22129     applyGroupField: function(){
22130         if(this.remoteGroup){
22131             if(!this.baseParams){
22132                 this.baseParams = {};
22133             }
22134             this.baseParams.groupBy = this.groupField;
22135             this.baseParams.groupDir = this.groupDir;
22136         }
22137     },
22138
22139     
22140     applySort : function(){
22141         Ext.data.GroupingStore.superclass.applySort.call(this);
22142         if(!this.groupOnSort && !this.remoteGroup){
22143             var gs = this.getGroupState();
22144             if(gs && (gs != this.sortInfo.field || this.groupDir != this.sortInfo.direction)){
22145                 this.sortData(this.groupField, this.groupDir);
22146             }
22147         }
22148     },
22149
22150     
22151     applyGrouping : function(alwaysFireChange){
22152         if(this.groupField !== false){
22153             this.groupBy(this.groupField, true, this.groupDir);
22154             return true;
22155         }else{
22156             if(alwaysFireChange === true){
22157                 this.fireEvent('datachanged', this);
22158             }
22159             return false;
22160         }
22161     },
22162
22163     
22164     getGroupState : function(){
22165         return this.groupOnSort && this.groupField !== false ?
22166                (this.sortInfo ? this.sortInfo.field : undefined) : this.groupField;
22167     }
22168 });
22169 Ext.reg('groupingstore', Ext.data.GroupingStore);
22170 Ext.data.DirectProxy = function(config){
22171     Ext.apply(this, config);
22172     if(typeof this.paramOrder == 'string'){
22173         this.paramOrder = this.paramOrder.split(/[\s,|]/);
22174     }
22175     Ext.data.DirectProxy.superclass.constructor.call(this, config);
22176 };
22177
22178 Ext.extend(Ext.data.DirectProxy, Ext.data.DataProxy, {
22179     
22180     paramOrder: undefined,
22181
22182     
22183     paramsAsHash: true,
22184
22185     
22186     directFn : undefined,
22187
22188     
22189     doRequest : function(action, rs, params, reader, callback, scope, options) {
22190         var args = [],
22191             directFn = this.api[action] || this.directFn;
22192
22193         switch (action) {
22194             case Ext.data.Api.actions.create:
22195                 args.push(params.jsonData);             
22196                 break;
22197             case Ext.data.Api.actions.read:
22198                 
22199                 if(directFn.directCfg.method.len > 0){
22200                     if(this.paramOrder){
22201                         for(var i = 0, len = this.paramOrder.length; i < len; i++){
22202                             args.push(params[this.paramOrder[i]]);
22203                         }
22204                     }else if(this.paramsAsHash){
22205                         args.push(params);
22206                     }
22207                 }
22208                 break;
22209             case Ext.data.Api.actions.update:
22210                 args.push(params.jsonData);        
22211                 break;
22212             case Ext.data.Api.actions.destroy:
22213                 args.push(params.jsonData);        
22214                 break;
22215         }
22216
22217         var trans = {
22218             params : params || {},
22219             request: {
22220                 callback : callback,
22221                 scope : scope,
22222                 arg : options
22223             },
22224             reader: reader
22225         };
22226
22227         args.push(this.createCallback(action, rs, trans), this);
22228         directFn.apply(window, args);
22229     },
22230
22231     
22232     createCallback : function(action, rs, trans) {
22233         return function(result, res) {
22234             if (!res.status) {
22235                 
22236                 if (action === Ext.data.Api.actions.read) {
22237                     this.fireEvent("loadexception", this, trans, res, null);
22238                 }
22239                 this.fireEvent('exception', this, 'remote', action, trans, res, null);
22240                 trans.request.callback.call(trans.request.scope, null, trans.request.arg, false);
22241                 return;
22242             }
22243             if (action === Ext.data.Api.actions.read) {
22244                 this.onRead(action, trans, result, res);
22245             } else {
22246                 this.onWrite(action, trans, result, res, rs);
22247             }
22248         };
22249     },
22250     
22251     onRead : function(action, trans, result, res) {
22252         var records;
22253         try {
22254             records = trans.reader.readRecords(result);
22255         }
22256         catch (ex) {
22257             
22258             this.fireEvent("loadexception", this, trans, res, ex);
22259
22260             this.fireEvent('exception', this, 'response', action, trans, res, ex);
22261             trans.request.callback.call(trans.request.scope, null, trans.request.arg, false);
22262             return;
22263         }
22264         this.fireEvent("load", this, res, trans.request.arg);
22265         trans.request.callback.call(trans.request.scope, records, trans.request.arg, true);
22266     },
22267     
22268     onWrite : function(action, trans, result, res, rs) {
22269         var data = trans.reader.extractData(result, false);
22270         this.fireEvent("write", this, action, data, res, rs, trans.request.arg);
22271         trans.request.callback.call(trans.request.scope, data, res, true);
22272     }
22273 });
22274
22275
22276 Ext.data.DirectStore = function(c){
22277     
22278     c.batchTransactions = false;
22279
22280     Ext.data.DirectStore.superclass.constructor.call(this, Ext.apply(c, {
22281         proxy: (typeof(c.proxy) == 'undefined') ? new Ext.data.DirectProxy(Ext.copyTo({}, c, 'paramOrder,paramsAsHash,directFn,api')) : c.proxy,
22282         reader: (typeof(c.reader) == 'undefined' && typeof(c.fields) == 'object') ? new Ext.data.JsonReader(Ext.copyTo({}, c, 'totalProperty,root,idProperty'), c.fields) : c.reader
22283     }));
22284 };
22285 Ext.extend(Ext.data.DirectStore, Ext.data.Store, {});
22286 Ext.reg('directstore', Ext.data.DirectStore);
22287
22288 Ext.Direct = Ext.extend(Ext.util.Observable, {
22289     
22290
22291     
22292     exceptions: {
22293         TRANSPORT: 'xhr',
22294         PARSE: 'parse',
22295         LOGIN: 'login',
22296         SERVER: 'exception'
22297     },
22298     
22299     
22300     constructor: function(){
22301         this.addEvents(
22302             
22303             'event',
22304             
22305             'exception'
22306         );
22307         this.transactions = {};
22308         this.providers = {};
22309     },
22310
22311     
22312     addProvider : function(provider){        
22313         var a = arguments;
22314         if(a.length > 1){
22315             for(var i = 0, len = a.length; i < len; i++){
22316                 this.addProvider(a[i]);
22317             }
22318             return;
22319         }
22320         
22321         
22322         if(!provider.events){
22323             provider = new Ext.Direct.PROVIDERS[provider.type](provider);
22324         }
22325         provider.id = provider.id || Ext.id();
22326         this.providers[provider.id] = provider;
22327
22328         provider.on('data', this.onProviderData, this);
22329         provider.on('exception', this.onProviderException, this);
22330
22331
22332         if(!provider.isConnected()){
22333             provider.connect();
22334         }
22335
22336         return provider;
22337     },
22338
22339     
22340     getProvider : function(id){
22341         return this.providers[id];
22342     },
22343
22344     removeProvider : function(id){
22345         var provider = id.id ? id : this.providers[id.id];
22346         provider.un('data', this.onProviderData, this);
22347         provider.un('exception', this.onProviderException, this);
22348         delete this.providers[provider.id];
22349         return provider;
22350     },
22351
22352     addTransaction: function(t){
22353         this.transactions[t.tid] = t;
22354         return t;
22355     },
22356
22357     removeTransaction: function(t){
22358         delete this.transactions[t.tid || t];
22359         return t;
22360     },
22361
22362     getTransaction: function(tid){
22363         return this.transactions[tid.tid || tid];
22364     },
22365
22366     onProviderData : function(provider, e){
22367         if(Ext.isArray(e)){
22368             for(var i = 0, len = e.length; i < len; i++){
22369                 this.onProviderData(provider, e[i]);
22370             }
22371             return;
22372         }
22373         if(e.name && e.name != 'event' && e.name != 'exception'){
22374             this.fireEvent(e.name, e);
22375         }else if(e.type == 'exception'){
22376             this.fireEvent('exception', e);
22377         }
22378         this.fireEvent('event', e, provider);
22379     },
22380
22381     createEvent : function(response, extraProps){
22382         return new Ext.Direct.eventTypes[response.type](Ext.apply(response, extraProps));
22383     }
22384 });
22385
22386 Ext.Direct = new Ext.Direct();
22387
22388 Ext.Direct.TID = 1;
22389 Ext.Direct.PROVIDERS = {};
22390 Ext.Direct.Transaction = function(config){
22391     Ext.apply(this, config);
22392     this.tid = ++Ext.Direct.TID;
22393     this.retryCount = 0;
22394 };
22395 Ext.Direct.Transaction.prototype = {
22396     send: function(){
22397         this.provider.queueTransaction(this);
22398     },
22399
22400     retry: function(){
22401         this.retryCount++;
22402         this.send();
22403     },
22404
22405     getProvider: function(){
22406         return this.provider;
22407     }
22408 };Ext.Direct.Event = function(config){
22409     Ext.apply(this, config);
22410 }
22411 Ext.Direct.Event.prototype = {
22412     status: true,
22413     getData: function(){
22414         return this.data;
22415     }
22416 };
22417
22418 Ext.Direct.RemotingEvent = Ext.extend(Ext.Direct.Event, {
22419     type: 'rpc',
22420     getTransaction: function(){
22421         return this.transaction || Ext.Direct.getTransaction(this.tid);
22422     }
22423 });
22424
22425 Ext.Direct.ExceptionEvent = Ext.extend(Ext.Direct.RemotingEvent, {
22426     status: false,
22427     type: 'exception'
22428 });
22429
22430 Ext.Direct.eventTypes = {
22431     'rpc':  Ext.Direct.RemotingEvent,
22432     'event':  Ext.Direct.Event,
22433     'exception':  Ext.Direct.ExceptionEvent
22434 };
22435
22436
22437 Ext.direct.Provider = Ext.extend(Ext.util.Observable, {    
22438     
22439         
22440         
22441     priority: 1,
22442
22443         
22444  
22445     
22446     constructor : function(config){
22447         Ext.apply(this, config);
22448         this.addEvents(
22449                         
22450             'connect',
22451                         
22452             'disconnect',
22453                         
22454             'data',
22455                                     
22456             'exception'
22457         );
22458         Ext.direct.Provider.superclass.constructor.call(this, config);
22459     },
22460
22461     
22462     isConnected: function(){
22463         return false;
22464     },
22465
22466     
22467     connect: Ext.emptyFn,
22468     
22469     
22470     disconnect: Ext.emptyFn
22471 });
22472
22473 Ext.direct.JsonProvider = Ext.extend(Ext.direct.Provider, {
22474     parseResponse: function(xhr){
22475         if(!Ext.isEmpty(xhr.responseText)){
22476             if(typeof xhr.responseText == 'object'){
22477                 return xhr.responseText;
22478             }
22479             return Ext.decode(xhr.responseText);
22480         }
22481         return null;
22482     },
22483
22484     getEvents: function(xhr){
22485         var data = null;
22486         try{
22487             data = this.parseResponse(xhr);
22488         }catch(e){
22489             var event = new Ext.Direct.ExceptionEvent({
22490                 data: e,
22491                 xhr: xhr,
22492                 code: Ext.Direct.exceptions.PARSE,
22493                 message: 'Error parsing json response: \n\n ' + data
22494             })
22495             return [event];
22496         }
22497         var events = [];
22498         if(Ext.isArray(data)){
22499             for(var i = 0, len = data.length; i < len; i++){
22500                 events.push(Ext.Direct.createEvent(data[i]));
22501             }
22502         }else{
22503             events.push(Ext.Direct.createEvent(data));
22504         }
22505         return events;
22506     }
22507 });
22508 Ext.direct.PollingProvider = Ext.extend(Ext.direct.JsonProvider, {
22509     
22510     
22511     priority: 3,
22512     
22513     
22514     interval: 3000,
22515
22516     
22517     
22518     
22519
22520     
22521     constructor : function(config){
22522         Ext.direct.PollingProvider.superclass.constructor.call(this, config);
22523         this.addEvents(
22524             
22525             'beforepoll',            
22526             
22527             'poll'
22528         );
22529     },
22530
22531     
22532     isConnected: function(){
22533         return !!this.pollTask;
22534     },
22535
22536     
22537     connect: function(){
22538         if(this.url && !this.pollTask){
22539             this.pollTask = Ext.TaskMgr.start({
22540                 run: function(){
22541                     if(this.fireEvent('beforepoll', this) !== false){
22542                         if(typeof this.url == 'function'){
22543                             this.url(this.baseParams);
22544                         }else{
22545                             Ext.Ajax.request({
22546                                 url: this.url,
22547                                 callback: this.onData,
22548                                 scope: this,
22549                                 params: this.baseParams
22550                             });
22551                         }
22552                     }
22553                 },
22554                 interval: this.interval,
22555                 scope: this
22556             });
22557             this.fireEvent('connect', this);
22558         }else if(!this.url){
22559             throw 'Error initializing PollingProvider, no url configured.';
22560         }
22561     },
22562
22563     
22564     disconnect: function(){
22565         if(this.pollTask){
22566             Ext.TaskMgr.stop(this.pollTask);
22567             delete this.pollTask;
22568             this.fireEvent('disconnect', this);
22569         }
22570     },
22571
22572     
22573     onData: function(opt, success, xhr){
22574         if(success){
22575             var events = this.getEvents(xhr);
22576             for(var i = 0, len = events.length; i < len; i++){
22577                 var e = events[i];
22578                 this.fireEvent('data', this, e);
22579             }
22580         }else{
22581             var e = new Ext.Direct.ExceptionEvent({
22582                 data: e,
22583                 code: Ext.Direct.exceptions.TRANSPORT,
22584                 message: 'Unable to connect to the server.',
22585                 xhr: xhr
22586             });
22587             this.fireEvent('data', this, e);
22588         }
22589     }
22590 });
22591
22592 Ext.Direct.PROVIDERS['polling'] = Ext.direct.PollingProvider;
22593 Ext.direct.RemotingProvider = Ext.extend(Ext.direct.JsonProvider, {       
22594     
22595     
22596     
22597     
22598     
22599     
22600     
22601     
22602     
22603     enableBuffer: 10,
22604     
22605     
22606     maxRetries: 1,
22607     
22608     
22609     timeout: undefined,
22610
22611     constructor : function(config){
22612         Ext.direct.RemotingProvider.superclass.constructor.call(this, config);
22613         this.addEvents(
22614                         
22615             'beforecall',            
22616                         
22617             'call'
22618         );
22619         this.namespace = (Ext.isString(this.namespace)) ? Ext.ns(this.namespace) : this.namespace || window;
22620         this.transactions = {};
22621         this.callBuffer = [];
22622     },
22623
22624     
22625     initAPI : function(){
22626         var o = this.actions;
22627         for(var c in o){
22628             var cls = this.namespace[c] || (this.namespace[c] = {}),
22629                 ms = o[c];
22630             for(var i = 0, len = ms.length; i < len; i++){
22631                 var m = ms[i];
22632                 cls[m.name] = this.createMethod(c, m);
22633             }
22634         }
22635     },
22636
22637     
22638     isConnected: function(){
22639         return !!this.connected;
22640     },
22641
22642     connect: function(){
22643         if(this.url){
22644             this.initAPI();
22645             this.connected = true;
22646             this.fireEvent('connect', this);
22647         }else if(!this.url){
22648             throw 'Error initializing RemotingProvider, no url configured.';
22649         }
22650     },
22651
22652     disconnect: function(){
22653         if(this.connected){
22654             this.connected = false;
22655             this.fireEvent('disconnect', this);
22656         }
22657     },
22658
22659     onData: function(opt, success, xhr){
22660         if(success){
22661             var events = this.getEvents(xhr);
22662             for(var i = 0, len = events.length; i < len; i++){
22663                 var e = events[i],
22664                     t = this.getTransaction(e);
22665                 this.fireEvent('data', this, e);
22666                 if(t){
22667                     this.doCallback(t, e, true);
22668                     Ext.Direct.removeTransaction(t);
22669                 }
22670             }
22671         }else{
22672             var ts = [].concat(opt.ts);
22673             for(var i = 0, len = ts.length; i < len; i++){
22674                 var t = this.getTransaction(ts[i]);
22675                 if(t && t.retryCount < this.maxRetries){
22676                     t.retry();
22677                 }else{
22678                     var e = new Ext.Direct.ExceptionEvent({
22679                         data: e,
22680                         transaction: t,
22681                         code: Ext.Direct.exceptions.TRANSPORT,
22682                         message: 'Unable to connect to the server.',
22683                         xhr: xhr
22684                     });
22685                     this.fireEvent('data', this, e);
22686                     if(t){
22687                         this.doCallback(t, e, false);
22688                         Ext.Direct.removeTransaction(t);
22689                     }
22690                 }
22691             }
22692         }
22693     },
22694
22695     getCallData: function(t){
22696         return {
22697             action: t.action,
22698             method: t.method,
22699             data: t.data,
22700             type: 'rpc',
22701             tid: t.tid
22702         };
22703     },
22704
22705     doSend : function(data){
22706         var o = {
22707             url: this.url,
22708             callback: this.onData,
22709             scope: this,
22710             ts: data,
22711             timeout: this.timeout
22712         }, callData;
22713
22714         if(Ext.isArray(data)){
22715             callData = [];
22716             for(var i = 0, len = data.length; i < len; i++){
22717                 callData.push(this.getCallData(data[i]));
22718             }
22719         }else{
22720             callData = this.getCallData(data);
22721         }
22722
22723         if(this.enableUrlEncode){
22724             var params = {};
22725             params[Ext.isString(this.enableUrlEncode) ? this.enableUrlEncode : 'data'] = Ext.encode(callData);
22726             o.params = params;
22727         }else{
22728             o.jsonData = callData;
22729         }
22730         Ext.Ajax.request(o);
22731     },
22732
22733     combineAndSend : function(){
22734         var len = this.callBuffer.length;
22735         if(len > 0){
22736             this.doSend(len == 1 ? this.callBuffer[0] : this.callBuffer);
22737             this.callBuffer = [];
22738         }
22739     },
22740
22741     queueTransaction: function(t){
22742         if(t.form){
22743             this.processForm(t);
22744             return;
22745         }
22746         this.callBuffer.push(t);
22747         if(this.enableBuffer){
22748             if(!this.callTask){
22749                 this.callTask = new Ext.util.DelayedTask(this.combineAndSend, this);
22750             }
22751             this.callTask.delay(Ext.isNumber(this.enableBuffer) ? this.enableBuffer : 10);
22752         }else{
22753             this.combineAndSend();
22754         }
22755     },
22756
22757     doCall : function(c, m, args){
22758         var data = null, hs = args[m.len], scope = args[m.len+1];
22759
22760         if(m.len !== 0){
22761             data = args.slice(0, m.len);
22762         }
22763
22764         var t = new Ext.Direct.Transaction({
22765             provider: this,
22766             args: args,
22767             action: c,
22768             method: m.name,
22769             data: data,
22770             cb: scope && Ext.isFunction(hs) ? hs.createDelegate(scope) : hs
22771         });
22772
22773         if(this.fireEvent('beforecall', this, t) !== false){
22774             Ext.Direct.addTransaction(t);
22775             this.queueTransaction(t);
22776             this.fireEvent('call', this, t);
22777         }
22778     },
22779
22780     doForm : function(c, m, form, callback, scope){
22781         var t = new Ext.Direct.Transaction({
22782             provider: this,
22783             action: c,
22784             method: m.name,
22785             args:[form, callback, scope],
22786             cb: scope && Ext.isFunction(callback) ? callback.createDelegate(scope) : callback,
22787             isForm: true
22788         });
22789
22790         if(this.fireEvent('beforecall', this, t) !== false){
22791             Ext.Direct.addTransaction(t);
22792             var isUpload = String(form.getAttribute("enctype")).toLowerCase() == 'multipart/form-data',
22793                 params = {
22794                     extTID: t.tid,
22795                     extAction: c,
22796                     extMethod: m.name,
22797                     extType: 'rpc',
22798                     extUpload: String(isUpload)
22799                 };
22800             
22801             
22802             
22803             Ext.apply(t, {
22804                 form: Ext.getDom(form),
22805                 isUpload: isUpload,
22806                 params: callback && Ext.isObject(callback.params) ? Ext.apply(params, callback.params) : params
22807             });
22808             this.fireEvent('call', this, t);
22809             this.processForm(t);
22810         }
22811     },
22812     
22813     processForm: function(t){
22814         Ext.Ajax.request({
22815             url: this.url,
22816             params: t.params,
22817             callback: this.onData,
22818             scope: this,
22819             form: t.form,
22820             isUpload: t.isUpload,
22821             ts: t
22822         });
22823     },
22824
22825     createMethod : function(c, m){
22826         var f;
22827         if(!m.formHandler){
22828             f = function(){
22829                 this.doCall(c, m, Array.prototype.slice.call(arguments, 0));
22830             }.createDelegate(this);
22831         }else{
22832             f = function(form, callback, scope){
22833                 this.doForm(c, m, form, callback, scope);
22834             }.createDelegate(this);
22835         }
22836         f.directCfg = {
22837             action: c,
22838             method: m
22839         };
22840         return f;
22841     },
22842
22843     getTransaction: function(opt){
22844         return opt && opt.tid ? Ext.Direct.getTransaction(opt.tid) : null;
22845     },
22846
22847     doCallback: function(t, e){
22848         var fn = e.status ? 'success' : 'failure';
22849         if(t && t.cb){
22850             var hs = t.cb,
22851                 result = Ext.isDefined(e.result) ? e.result : e.data;
22852             if(Ext.isFunction(hs)){
22853                 hs(result, e);
22854             } else{
22855                 Ext.callback(hs[fn], hs.scope, [result, e]);
22856                 Ext.callback(hs.callback, hs.scope, [result, e]);
22857             }
22858         }
22859     }
22860 });
22861 Ext.Direct.PROVIDERS['remoting'] = Ext.direct.RemotingProvider;
22862 Ext.Resizable = function(el, config){
22863     this.el = Ext.get(el);
22864     
22865     if(config && config.wrap){
22866         config.resizeChild = this.el;
22867         this.el = this.el.wrap(typeof config.wrap == 'object' ? config.wrap : {cls:'xresizable-wrap'});
22868         this.el.id = this.el.dom.id = config.resizeChild.id + '-rzwrap';
22869         this.el.setStyle('overflow', 'hidden');
22870         this.el.setPositioning(config.resizeChild.getPositioning());
22871         config.resizeChild.clearPositioning();
22872         if(!config.width || !config.height){
22873             var csize = config.resizeChild.getSize();
22874             this.el.setSize(csize.width, csize.height);
22875         }
22876         if(config.pinned && !config.adjustments){
22877             config.adjustments = 'auto';
22878         }
22879     }
22880
22881     
22882     this.proxy = this.el.createProxy({tag: 'div', cls: 'x-resizable-proxy', id: this.el.id + '-rzproxy'}, Ext.getBody());
22883     this.proxy.unselectable();
22884     this.proxy.enableDisplayMode('block');
22885
22886     Ext.apply(this, config);
22887     
22888     if(this.pinned){
22889         this.disableTrackOver = true;
22890         this.el.addClass('x-resizable-pinned');
22891     }
22892     
22893     var position = this.el.getStyle('position');
22894     if(position != 'absolute' && position != 'fixed'){
22895         this.el.setStyle('position', 'relative');
22896     }
22897     if(!this.handles){ 
22898         this.handles = 's,e,se';
22899         if(this.multiDirectional){
22900             this.handles += ',n,w';
22901         }
22902     }
22903     if(this.handles == 'all'){
22904         this.handles = 'n s e w ne nw se sw';
22905     }
22906     var hs = this.handles.split(/\s*?[,;]\s*?| /);
22907     var ps = Ext.Resizable.positions;
22908     for(var i = 0, len = hs.length; i < len; i++){
22909         if(hs[i] && ps[hs[i]]){
22910             var pos = ps[hs[i]];
22911             this[pos] = new Ext.Resizable.Handle(this, pos, this.disableTrackOver, this.transparent);
22912         }
22913     }
22914     
22915     this.corner = this.southeast;
22916     
22917     if(this.handles.indexOf('n') != -1 || this.handles.indexOf('w') != -1){
22918         this.updateBox = true;
22919     }   
22920    
22921     this.activeHandle = null;
22922     
22923     if(this.resizeChild){
22924         if(typeof this.resizeChild == 'boolean'){
22925             this.resizeChild = Ext.get(this.el.dom.firstChild, true);
22926         }else{
22927             this.resizeChild = Ext.get(this.resizeChild, true);
22928         }
22929     }
22930     
22931     if(this.adjustments == 'auto'){
22932         var rc = this.resizeChild;
22933         var hw = this.west, he = this.east, hn = this.north, hs = this.south;
22934         if(rc && (hw || hn)){
22935             rc.position('relative');
22936             rc.setLeft(hw ? hw.el.getWidth() : 0);
22937             rc.setTop(hn ? hn.el.getHeight() : 0);
22938         }
22939         this.adjustments = [
22940             (he ? -he.el.getWidth() : 0) + (hw ? -hw.el.getWidth() : 0),
22941             (hn ? -hn.el.getHeight() : 0) + (hs ? -hs.el.getHeight() : 0) -1 
22942         ];
22943     }
22944     
22945     if(this.draggable){
22946         this.dd = this.dynamic ? 
22947             this.el.initDD(null) : this.el.initDDProxy(null, {dragElId: this.proxy.id});
22948         this.dd.setHandleElId(this.resizeChild ? this.resizeChild.id : this.el.id);
22949         if(this.constrainTo){
22950             this.dd.constrainTo(this.constrainTo);
22951         }
22952     }
22953     
22954     this.addEvents(
22955         
22956         'beforeresize',
22957         
22958         'resize'
22959     );
22960     
22961     if(this.width !== null && this.height !== null){
22962         this.resizeTo(this.width, this.height);
22963     }else{
22964         this.updateChildSize();
22965     }
22966     if(Ext.isIE){
22967         this.el.dom.style.zoom = 1;
22968     }
22969     Ext.Resizable.superclass.constructor.call(this);
22970 };
22971
22972 Ext.extend(Ext.Resizable, Ext.util.Observable, {
22973
22974     
22975     adjustments : [0, 0],
22976     
22977     animate : false,
22978     
22979     
22980     disableTrackOver : false,
22981     
22982     draggable: false,
22983     
22984     duration : 0.35,
22985     
22986     dynamic : false,
22987     
22988     easing : 'easeOutStrong',
22989     
22990     enabled : true,
22991     
22992     
22993     handles : false,
22994     
22995     multiDirectional : false,
22996     
22997     height : null,
22998     
22999     width : null,
23000     
23001     heightIncrement : 0,
23002     
23003     widthIncrement : 0,
23004     
23005     minHeight : 5,
23006     
23007     minWidth : 5,
23008     
23009     maxHeight : 10000,
23010     
23011     maxWidth : 10000,
23012     
23013     minX: 0,
23014     
23015     minY: 0,
23016     
23017     pinned : false,
23018     
23019     preserveRatio : false,
23020      
23021     resizeChild : false,
23022     
23023     transparent: false,
23024     
23025     
23026
23027     
23028     
23029     resizeTo : function(width, height){
23030         this.el.setSize(width, height);
23031         this.updateChildSize();
23032         this.fireEvent('resize', this, width, height, null);
23033     },
23034
23035     
23036     startSizing : function(e, handle){
23037         this.fireEvent('beforeresize', this, e);
23038         if(this.enabled){ 
23039
23040             if(!this.overlay){
23041                 this.overlay = this.el.createProxy({tag: 'div', cls: 'x-resizable-overlay', html: '&#160;'}, Ext.getBody());
23042                 this.overlay.unselectable();
23043                 this.overlay.enableDisplayMode('block');
23044                 this.overlay.on({
23045                     scope: this,
23046                     mousemove: this.onMouseMove,
23047                     mouseup: this.onMouseUp
23048                 });
23049             }
23050             this.overlay.setStyle('cursor', handle.el.getStyle('cursor'));
23051
23052             this.resizing = true;
23053             this.startBox = this.el.getBox();
23054             this.startPoint = e.getXY();
23055             this.offsets = [(this.startBox.x + this.startBox.width) - this.startPoint[0],
23056                             (this.startBox.y + this.startBox.height) - this.startPoint[1]];
23057
23058             this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
23059             this.overlay.show();
23060
23061             if(this.constrainTo) {
23062                 var ct = Ext.get(this.constrainTo);
23063                 this.resizeRegion = ct.getRegion().adjust(
23064                     ct.getFrameWidth('t'),
23065                     ct.getFrameWidth('l'),
23066                     -ct.getFrameWidth('b'),
23067                     -ct.getFrameWidth('r')
23068                 );
23069             }
23070
23071             this.proxy.setStyle('visibility', 'hidden'); 
23072             this.proxy.show();
23073             this.proxy.setBox(this.startBox);
23074             if(!this.dynamic){
23075                 this.proxy.setStyle('visibility', 'visible');
23076             }
23077         }
23078     },
23079
23080     
23081     onMouseDown : function(handle, e){
23082         if(this.enabled){
23083             e.stopEvent();
23084             this.activeHandle = handle;
23085             this.startSizing(e, handle);
23086         }          
23087     },
23088
23089     
23090     onMouseUp : function(e){
23091         this.activeHandle = null;
23092         var size = this.resizeElement();
23093         this.resizing = false;
23094         this.handleOut();
23095         this.overlay.hide();
23096         this.proxy.hide();
23097         this.fireEvent('resize', this, size.width, size.height, e);
23098     },
23099
23100     
23101     updateChildSize : function(){
23102         if(this.resizeChild){
23103             var el = this.el;
23104             var child = this.resizeChild;
23105             var adj = this.adjustments;
23106             if(el.dom.offsetWidth){
23107                 var b = el.getSize(true);
23108                 child.setSize(b.width+adj[0], b.height+adj[1]);
23109             }
23110             
23111             
23112             
23113             
23114             if(Ext.isIE){
23115                 setTimeout(function(){
23116                     if(el.dom.offsetWidth){
23117                         var b = el.getSize(true);
23118                         child.setSize(b.width+adj[0], b.height+adj[1]);
23119                     }
23120                 }, 10);
23121             }
23122         }
23123     },
23124
23125     
23126     snap : function(value, inc, min){
23127         if(!inc || !value){
23128             return value;
23129         }
23130         var newValue = value;
23131         var m = value % inc;
23132         if(m > 0){
23133             if(m > (inc/2)){
23134                 newValue = value + (inc-m);
23135             }else{
23136                 newValue = value - m;
23137             }
23138         }
23139         return Math.max(min, newValue);
23140     },
23141
23142     
23143     resizeElement : function(){
23144         var box = this.proxy.getBox();
23145         if(this.updateBox){
23146             this.el.setBox(box, false, this.animate, this.duration, null, this.easing);
23147         }else{
23148             this.el.setSize(box.width, box.height, this.animate, this.duration, null, this.easing);
23149         }
23150         this.updateChildSize();
23151         if(!this.dynamic){
23152             this.proxy.hide();
23153         }
23154         if(this.draggable && this.constrainTo){
23155             this.dd.resetConstraints();
23156             this.dd.constrainTo(this.constrainTo);
23157         }
23158         return box;
23159     },
23160
23161     
23162     constrain : function(v, diff, m, mx){
23163         if(v - diff < m){
23164             diff = v - m;    
23165         }else if(v - diff > mx){
23166             diff = v - mx; 
23167         }
23168         return diff;                
23169     },
23170
23171     
23172     onMouseMove : function(e){
23173         if(this.enabled && this.activeHandle){
23174             try{
23175
23176             if(this.resizeRegion && !this.resizeRegion.contains(e.getPoint())) {
23177                 return;
23178             }
23179
23180             
23181             var curSize = this.curSize || this.startBox,
23182                 x = this.startBox.x, y = this.startBox.y,
23183                 ox = x, 
23184                 oy = y,
23185                 w = curSize.width, 
23186                 h = curSize.height,
23187                 ow = w, 
23188                 oh = h,
23189                 mw = this.minWidth, 
23190                 mh = this.minHeight,
23191                 mxw = this.maxWidth, 
23192                 mxh = this.maxHeight,
23193                 wi = this.widthIncrement,
23194                 hi = this.heightIncrement,
23195                 eventXY = e.getXY(),
23196                 diffX = -(this.startPoint[0] - Math.max(this.minX, eventXY[0])),
23197                 diffY = -(this.startPoint[1] - Math.max(this.minY, eventXY[1])),
23198                 pos = this.activeHandle.position,
23199                 tw,
23200                 th;
23201             
23202             switch(pos){
23203                 case 'east':
23204                     w += diffX; 
23205                     w = Math.min(Math.max(mw, w), mxw);
23206                     break;
23207                 case 'south':
23208                     h += diffY;
23209                     h = Math.min(Math.max(mh, h), mxh);
23210                     break;
23211                 case 'southeast':
23212                     w += diffX; 
23213                     h += diffY;
23214                     w = Math.min(Math.max(mw, w), mxw);
23215                     h = Math.min(Math.max(mh, h), mxh);
23216                     break;
23217                 case 'north':
23218                     diffY = this.constrain(h, diffY, mh, mxh);
23219                     y += diffY;
23220                     h -= diffY;
23221                     break;
23222                 case 'west':
23223                     diffX = this.constrain(w, diffX, mw, mxw);
23224                     x += diffX;
23225                     w -= diffX;
23226                     break;
23227                 case 'northeast':
23228                     w += diffX; 
23229                     w = Math.min(Math.max(mw, w), mxw);
23230                     diffY = this.constrain(h, diffY, mh, mxh);
23231                     y += diffY;
23232                     h -= diffY;
23233                     break;
23234                 case 'northwest':
23235                     diffX = this.constrain(w, diffX, mw, mxw);
23236                     diffY = this.constrain(h, diffY, mh, mxh);
23237                     y += diffY;
23238                     h -= diffY;
23239                     x += diffX;
23240                     w -= diffX;
23241                     break;
23242                case 'southwest':
23243                     diffX = this.constrain(w, diffX, mw, mxw);
23244                     h += diffY;
23245                     h = Math.min(Math.max(mh, h), mxh);
23246                     x += diffX;
23247                     w -= diffX;
23248                     break;
23249             }
23250             
23251             var sw = this.snap(w, wi, mw);
23252             var sh = this.snap(h, hi, mh);
23253             if(sw != w || sh != h){
23254                 switch(pos){
23255                     case 'northeast':
23256                         y -= sh - h;
23257                     break;
23258                     case 'north':
23259                         y -= sh - h;
23260                         break;
23261                     case 'southwest':
23262                         x -= sw - w;
23263                     break;
23264                     case 'west':
23265                         x -= sw - w;
23266                         break;
23267                     case 'northwest':
23268                         x -= sw - w;
23269                         y -= sh - h;
23270                     break;
23271                 }
23272                 w = sw;
23273                 h = sh;
23274             }
23275             
23276             if(this.preserveRatio){
23277                 switch(pos){
23278                     case 'southeast':
23279                     case 'east':
23280                         h = oh * (w/ow);
23281                         h = Math.min(Math.max(mh, h), mxh);
23282                         w = ow * (h/oh);
23283                        break;
23284                     case 'south':
23285                         w = ow * (h/oh);
23286                         w = Math.min(Math.max(mw, w), mxw);
23287                         h = oh * (w/ow);
23288                         break;
23289                     case 'northeast':
23290                         w = ow * (h/oh);
23291                         w = Math.min(Math.max(mw, w), mxw);
23292                         h = oh * (w/ow);
23293                     break;
23294                     case 'north':
23295                         tw = w;
23296                         w = ow * (h/oh);
23297                         w = Math.min(Math.max(mw, w), mxw);
23298                         h = oh * (w/ow);
23299                         x += (tw - w) / 2;
23300                         break;
23301                     case 'southwest':
23302                         h = oh * (w/ow);
23303                         h = Math.min(Math.max(mh, h), mxh);
23304                         tw = w;
23305                         w = ow * (h/oh);
23306                         x += tw - w;
23307                         break;
23308                     case 'west':
23309                         th = h;
23310                         h = oh * (w/ow);
23311                         h = Math.min(Math.max(mh, h), mxh);
23312                         y += (th - h) / 2;
23313                         tw = w;
23314                         w = ow * (h/oh);
23315                         x += tw - w;
23316                        break;
23317                     case 'northwest':
23318                         tw = w;
23319                         th = h;
23320                         h = oh * (w/ow);
23321                         h = Math.min(Math.max(mh, h), mxh);
23322                         w = ow * (h/oh);
23323                         y += th - h;
23324                         x += tw - w;
23325                         break;
23326                         
23327                 }
23328             }
23329             this.proxy.setBounds(x, y, w, h);
23330             if(this.dynamic){
23331                 this.resizeElement();
23332             }
23333             }catch(ex){}
23334         }
23335     },
23336
23337     
23338     handleOver : function(){
23339         if(this.enabled){
23340             this.el.addClass('x-resizable-over');
23341         }
23342     },
23343
23344     
23345     handleOut : function(){
23346         if(!this.resizing){
23347             this.el.removeClass('x-resizable-over');
23348         }
23349     },
23350     
23351     
23352     getEl : function(){
23353         return this.el;
23354     },
23355     
23356     
23357     getResizeChild : function(){
23358         return this.resizeChild;
23359     },
23360     
23361     
23362     destroy : function(removeEl){
23363         Ext.destroy(this.dd, this.overlay, this.proxy);
23364         this.overlay = null;
23365         this.proxy = null;
23366         
23367         var ps = Ext.Resizable.positions;
23368         for(var k in ps){
23369             if(typeof ps[k] != 'function' && this[ps[k]]){
23370                 this[ps[k]].destroy();
23371             }
23372         }
23373         if(removeEl){
23374             this.el.update('');
23375             Ext.destroy(this.el);
23376             this.el = null;
23377         }
23378         this.purgeListeners();
23379     },
23380
23381     syncHandleHeight : function(){
23382         var h = this.el.getHeight(true);
23383         if(this.west){
23384             this.west.el.setHeight(h);
23385         }
23386         if(this.east){
23387             this.east.el.setHeight(h);
23388         }
23389     }
23390 });
23391
23392
23393
23394 Ext.Resizable.positions = {
23395     n: 'north', s: 'south', e: 'east', w: 'west', se: 'southeast', sw: 'southwest', nw: 'northwest', ne: 'northeast'
23396 };
23397
23398
23399 Ext.Resizable.Handle = function(rz, pos, disableTrackOver, transparent){
23400     if(!this.tpl){
23401         
23402         var tpl = Ext.DomHelper.createTemplate(
23403             {tag: 'div', cls: 'x-resizable-handle x-resizable-handle-{0}'}
23404         );
23405         tpl.compile();
23406         Ext.Resizable.Handle.prototype.tpl = tpl;
23407     }
23408     this.position = pos;
23409     this.rz = rz;
23410     this.el = this.tpl.append(rz.el.dom, [this.position], true);
23411     this.el.unselectable();
23412     if(transparent){
23413         this.el.setOpacity(0);
23414     }
23415     this.el.on('mousedown', this.onMouseDown, this);
23416     if(!disableTrackOver){
23417         this.el.on({
23418             scope: this,
23419             mouseover: this.onMouseOver,
23420             mouseout: this.onMouseOut
23421         });
23422     }
23423 };
23424
23425
23426 Ext.Resizable.Handle.prototype = {
23427     
23428     afterResize : function(rz){
23429         
23430     },
23431     
23432     onMouseDown : function(e){
23433         this.rz.onMouseDown(this, e);
23434     },
23435     
23436     onMouseOver : function(e){
23437         this.rz.handleOver(this, e);
23438     },
23439     
23440     onMouseOut : function(e){
23441         this.rz.handleOut(this, e);
23442     },
23443     
23444     destroy : function(){
23445         Ext.destroy(this.el);
23446         this.el = null;
23447     }
23448 };
23449
23450 Ext.Window = Ext.extend(Ext.Panel, {
23451     
23452     
23453     
23454     
23455     
23456     
23457     
23458     
23459     
23460     
23461
23462     
23463     baseCls : 'x-window',
23464     
23465     resizable : true,
23466     
23467     draggable : true,
23468     
23469     closable : true,
23470     
23471     closeAction : 'close',
23472     
23473     constrain : false,
23474     
23475     constrainHeader : false,
23476     
23477     plain : false,
23478     
23479     minimizable : false,
23480     
23481     maximizable : false,
23482     
23483     minHeight : 100,
23484     
23485     minWidth : 200,
23486     
23487     expandOnShow : true,
23488
23489     
23490     collapsible : false,
23491
23492     
23493     initHidden : undefined,
23494
23495     
23496     hidden : true,
23497
23498     
23499     monitorResize : true,
23500
23501     
23502     
23503     
23504     
23505     
23506     elements : 'header,body',
23507     
23508     frame : true,
23509     
23510     floating : true,
23511
23512     
23513     initComponent : function(){
23514         this.initTools();
23515         Ext.Window.superclass.initComponent.call(this);
23516         this.addEvents(
23517             
23518             
23519             
23520             'resize',
23521             
23522             'maximize',
23523             
23524             'minimize',
23525             
23526             'restore'
23527         );
23528         
23529         if(Ext.isDefined(this.initHidden)){
23530             this.hidden = this.initHidden;
23531         }
23532         if(this.hidden === false){
23533             this.hidden = true;
23534             this.show();
23535         }
23536     },
23537
23538     
23539     getState : function(){
23540         return Ext.apply(Ext.Window.superclass.getState.call(this) || {}, this.getBox(true));
23541     },
23542
23543     
23544     onRender : function(ct, position){
23545         Ext.Window.superclass.onRender.call(this, ct, position);
23546
23547         if(this.plain){
23548             this.el.addClass('x-window-plain');
23549         }
23550
23551         
23552         this.focusEl = this.el.createChild({
23553                     tag: 'a', href:'#', cls:'x-dlg-focus',
23554                     tabIndex:'-1', html: '&#160;'});
23555         this.focusEl.swallowEvent('click', true);
23556
23557         this.proxy = this.el.createProxy('x-window-proxy');
23558         this.proxy.enableDisplayMode('block');
23559
23560         if(this.modal){
23561             this.mask = this.container.createChild({cls:'ext-el-mask'}, this.el.dom);
23562             this.mask.enableDisplayMode('block');
23563             this.mask.hide();
23564             this.mon(this.mask, 'click', this.focus, this);
23565         }
23566         if(this.maximizable){
23567             this.mon(this.header, 'dblclick', this.toggleMaximize, this);
23568         }
23569     },
23570
23571     
23572     initEvents : function(){
23573         Ext.Window.superclass.initEvents.call(this);
23574         if(this.animateTarget){
23575             this.setAnimateTarget(this.animateTarget);
23576         }
23577
23578         if(this.resizable){
23579             this.resizer = new Ext.Resizable(this.el, {
23580                 minWidth: this.minWidth,
23581                 minHeight:this.minHeight,
23582                 handles: this.resizeHandles || 'all',
23583                 pinned: true,
23584                 resizeElement : this.resizerAction
23585             });
23586             this.resizer.window = this;
23587             this.mon(this.resizer, 'beforeresize', this.beforeResize, this);
23588         }
23589
23590         if(this.draggable){
23591             this.header.addClass('x-window-draggable');
23592         }
23593         this.mon(this.el, 'mousedown', this.toFront, this);
23594         this.manager = this.manager || Ext.WindowMgr;
23595         this.manager.register(this);
23596         if(this.maximized){
23597             this.maximized = false;
23598             this.maximize();
23599         }
23600         if(this.closable){
23601             var km = this.getKeyMap();
23602             km.on(27, this.onEsc, this);
23603             km.disable();
23604         }
23605     },
23606
23607     initDraggable : function(){
23608         
23609         this.dd = new Ext.Window.DD(this);
23610     },
23611
23612    
23613     onEsc : function(){
23614         this[this.closeAction]();
23615     },
23616
23617     
23618     beforeDestroy : function(){
23619         if (this.rendered){
23620             this.hide();
23621           if(this.doAnchor){
23622                 Ext.EventManager.removeResizeListener(this.doAnchor, this);
23623               Ext.EventManager.un(window, 'scroll', this.doAnchor, this);
23624             }
23625             Ext.destroy(
23626                 this.focusEl,
23627                 this.resizer,
23628                 this.dd,
23629                 this.proxy,
23630                 this.mask
23631             );
23632         }
23633         Ext.Window.superclass.beforeDestroy.call(this);
23634     },
23635
23636     
23637     onDestroy : function(){
23638         if(this.manager){
23639             this.manager.unregister(this);
23640         }
23641         Ext.Window.superclass.onDestroy.call(this);
23642     },
23643
23644     
23645     initTools : function(){
23646         if(this.minimizable){
23647             this.addTool({
23648                 id: 'minimize',
23649                 handler: this.minimize.createDelegate(this, [])
23650             });
23651         }
23652         if(this.maximizable){
23653             this.addTool({
23654                 id: 'maximize',
23655                 handler: this.maximize.createDelegate(this, [])
23656             });
23657             this.addTool({
23658                 id: 'restore',
23659                 handler: this.restore.createDelegate(this, []),
23660                 hidden:true
23661             });
23662         }
23663         if(this.closable){
23664             this.addTool({
23665                 id: 'close',
23666                 handler: this[this.closeAction].createDelegate(this, [])
23667             });
23668         }
23669     },
23670
23671     
23672     resizerAction : function(){
23673         var box = this.proxy.getBox();
23674         this.proxy.hide();
23675         this.window.handleResize(box);
23676         return box;
23677     },
23678
23679     
23680     beforeResize : function(){
23681         this.resizer.minHeight = Math.max(this.minHeight, this.getFrameHeight() + 40); 
23682         this.resizer.minWidth = Math.max(this.minWidth, this.getFrameWidth() + 40);
23683         this.resizeBox = this.el.getBox();
23684     },
23685
23686     
23687     updateHandles : function(){
23688         if(Ext.isIE && this.resizer){
23689             this.resizer.syncHandleHeight();
23690             this.el.repaint();
23691         }
23692     },
23693
23694     
23695     handleResize : function(box){
23696         var rz = this.resizeBox;
23697         if(rz.x != box.x || rz.y != box.y){
23698             this.updateBox(box);
23699         }else{
23700             this.setSize(box);
23701         }
23702         this.focus();
23703         this.updateHandles();
23704         this.saveState();
23705     },
23706
23707     
23708     focus : function(){
23709         var f = this.focusEl, db = this.defaultButton, t = typeof db;
23710         if(Ext.isDefined(db)){
23711             if(Ext.isNumber(db) && this.fbar){
23712                 f = this.fbar.items.get(db);
23713             }else if(Ext.isString(db)){
23714                 f = Ext.getCmp(db);
23715             }else{
23716                 f = db;
23717             }
23718         }
23719         f = f || this.focusEl;
23720         f.focus.defer(10, f);
23721     },
23722
23723     
23724     setAnimateTarget : function(el){
23725         el = Ext.get(el);
23726         this.animateTarget = el;
23727     },
23728
23729     
23730     beforeShow : function(){
23731         delete this.el.lastXY;
23732         delete this.el.lastLT;
23733         if(this.x === undefined || this.y === undefined){
23734             var xy = this.el.getAlignToXY(this.container, 'c-c');
23735             var pos = this.el.translatePoints(xy[0], xy[1]);
23736             this.x = this.x === undefined? pos.left : this.x;
23737             this.y = this.y === undefined? pos.top : this.y;
23738         }
23739         this.el.setLeftTop(this.x, this.y);
23740
23741         if(this.expandOnShow){
23742             this.expand(false);
23743         }
23744
23745         if(this.modal){
23746             Ext.getBody().addClass('x-body-masked');
23747             this.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
23748             this.mask.show();
23749         }
23750     },
23751
23752     
23753     show : function(animateTarget, cb, scope){
23754         if(!this.rendered){
23755             this.render(Ext.getBody());
23756         }
23757         if(this.hidden === false){
23758             this.toFront();
23759             return this;
23760         }
23761         if(this.fireEvent('beforeshow', this) === false){
23762             return this;
23763         }
23764         if(cb){
23765             this.on('show', cb, scope, {single:true});
23766         }
23767         this.hidden = false;
23768         if(Ext.isDefined(animateTarget)){
23769             this.setAnimateTarget(animateTarget);
23770         }
23771         this.beforeShow();
23772         if(this.animateTarget){
23773             this.animShow();
23774         }else{
23775             this.afterShow();
23776         }
23777         return this;
23778     },
23779
23780     
23781     afterShow : function(isAnim){
23782         this.proxy.hide();
23783         this.el.setStyle('display', 'block');
23784         this.el.show();
23785         if(this.maximized){
23786             this.fitContainer();
23787         }
23788         if(Ext.isMac && Ext.isGecko2){ 
23789             this.cascade(this.setAutoScroll);
23790         }
23791
23792         if(this.monitorResize || this.modal || this.constrain || this.constrainHeader){
23793             Ext.EventManager.onWindowResize(this.onWindowResize, this);
23794         }
23795         this.doConstrain();
23796         this.doLayout();
23797         if(this.keyMap){
23798             this.keyMap.enable();
23799         }
23800         this.toFront();
23801         this.updateHandles();
23802         if(isAnim && (Ext.isIE || Ext.isWebKit)){
23803             var sz = this.getSize();
23804             this.onResize(sz.width, sz.height);
23805         }
23806         this.onShow();
23807         this.fireEvent('show', this);
23808     },
23809
23810     
23811     animShow : function(){
23812         this.proxy.show();
23813         this.proxy.setBox(this.animateTarget.getBox());
23814         this.proxy.setOpacity(0);
23815         var b = this.getBox();
23816         this.el.setStyle('display', 'none');
23817         this.proxy.shift(Ext.apply(b, {
23818             callback: this.afterShow.createDelegate(this, [true], false),
23819             scope: this,
23820             easing: 'easeNone',
23821             duration: 0.25,
23822             opacity: 0.5
23823         }));
23824     },
23825
23826     
23827     hide : function(animateTarget, cb, scope){
23828         if(this.hidden || this.fireEvent('beforehide', this) === false){
23829             return this;
23830         }
23831         if(cb){
23832             this.on('hide', cb, scope, {single:true});
23833         }
23834         this.hidden = true;
23835         if(animateTarget !== undefined){
23836             this.setAnimateTarget(animateTarget);
23837         }
23838         if(this.modal){
23839             this.mask.hide();
23840             Ext.getBody().removeClass('x-body-masked');
23841         }
23842         if(this.animateTarget){
23843             this.animHide();
23844         }else{
23845             this.el.hide();
23846             this.afterHide();
23847         }
23848         return this;
23849     },
23850
23851     
23852     afterHide : function(){
23853         this.proxy.hide();
23854         if(this.monitorResize || this.modal || this.constrain || this.constrainHeader){
23855             Ext.EventManager.removeResizeListener(this.onWindowResize, this);
23856         }
23857         if(this.keyMap){
23858             this.keyMap.disable();
23859         }
23860         this.onHide();
23861         this.fireEvent('hide', this);
23862     },
23863
23864     
23865     animHide : function(){
23866         this.proxy.setOpacity(0.5);
23867         this.proxy.show();
23868         var tb = this.getBox(false);
23869         this.proxy.setBox(tb);
23870         this.el.hide();
23871         this.proxy.shift(Ext.apply(this.animateTarget.getBox(), {
23872             callback: this.afterHide,
23873             scope: this,
23874             duration: 0.25,
23875             easing: 'easeNone',
23876             opacity: 0
23877         }));
23878     },
23879
23880     
23881     onShow : Ext.emptyFn,
23882
23883     
23884     onHide : Ext.emptyFn,
23885
23886     
23887     onWindowResize : function(){
23888         if(this.maximized){
23889             this.fitContainer();
23890         }
23891         if(this.modal){
23892             this.mask.setSize('100%', '100%');
23893             var force = this.mask.dom.offsetHeight;
23894             this.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
23895         }
23896         this.doConstrain();
23897     },
23898
23899     
23900     doConstrain : function(){
23901         if(this.constrain || this.constrainHeader){
23902             var offsets;
23903             if(this.constrain){
23904                 offsets = {
23905                     right:this.el.shadowOffset,
23906                     left:this.el.shadowOffset,
23907                     bottom:this.el.shadowOffset
23908                 };
23909             }else {
23910                 var s = this.getSize();
23911                 offsets = {
23912                     right:-(s.width - 100),
23913                     bottom:-(s.height - 25)
23914                 };
23915             }
23916
23917             var xy = this.el.getConstrainToXY(this.container, true, offsets);
23918             if(xy){
23919                 this.setPosition(xy[0], xy[1]);
23920             }
23921         }
23922     },
23923
23924     
23925     ghost : function(cls){
23926         var ghost = this.createGhost(cls);
23927         var box = this.getBox(true);
23928         ghost.setLeftTop(box.x, box.y);
23929         ghost.setWidth(box.width);
23930         this.el.hide();
23931         this.activeGhost = ghost;
23932         return ghost;
23933     },
23934
23935     
23936     unghost : function(show, matchPosition){
23937         if(!this.activeGhost) {
23938             return;
23939         }
23940         if(show !== false){
23941             this.el.show();
23942             this.focus();
23943             if(Ext.isMac && Ext.isGecko2){ 
23944                 this.cascade(this.setAutoScroll);
23945             }
23946         }
23947         if(matchPosition !== false){
23948             this.setPosition(this.activeGhost.getLeft(true), this.activeGhost.getTop(true));
23949         }
23950         this.activeGhost.hide();
23951         this.activeGhost.remove();
23952         delete this.activeGhost;
23953     },
23954
23955     
23956     minimize : function(){
23957         this.fireEvent('minimize', this);
23958         return this;
23959     },
23960
23961     
23962     close : function(){
23963         if(this.fireEvent('beforeclose', this) !== false){
23964             if(this.hidden){
23965                 this.doClose();
23966             }else{
23967                 this.hide(null, this.doClose, this);
23968             }
23969         }
23970     },
23971
23972     
23973     doClose : function(){
23974         this.fireEvent('close', this);
23975         this.destroy();
23976     },
23977
23978     
23979     maximize : function(){
23980         if(!this.maximized){
23981             this.expand(false);
23982             this.restoreSize = this.getSize();
23983             this.restorePos = this.getPosition(true);
23984             if (this.maximizable){
23985                 this.tools.maximize.hide();
23986                 this.tools.restore.show();
23987             }
23988             this.maximized = true;
23989             this.el.disableShadow();
23990
23991             if(this.dd){
23992                 this.dd.lock();
23993             }
23994             if(this.collapsible){
23995                 this.tools.toggle.hide();
23996             }
23997             this.el.addClass('x-window-maximized');
23998             this.container.addClass('x-window-maximized-ct');
23999
24000             this.setPosition(0, 0);
24001             this.fitContainer();
24002             this.fireEvent('maximize', this);
24003         }
24004         return this;
24005     },
24006
24007     
24008     restore : function(){
24009         if(this.maximized){
24010             var t = this.tools;
24011             this.el.removeClass('x-window-maximized');
24012             if(t.restore){
24013                 t.restore.hide();
24014             }
24015             if(t.maximize){
24016                 t.maximize.show();
24017             }
24018             this.setPosition(this.restorePos[0], this.restorePos[1]);
24019             this.setSize(this.restoreSize.width, this.restoreSize.height);
24020             delete this.restorePos;
24021             delete this.restoreSize;
24022             this.maximized = false;
24023             this.el.enableShadow(true);
24024
24025             if(this.dd){
24026                 this.dd.unlock();
24027             }
24028             if(this.collapsible && t.toggle){
24029                 t.toggle.show();
24030             }
24031             this.container.removeClass('x-window-maximized-ct');
24032
24033             this.doConstrain();
24034             this.fireEvent('restore', this);
24035         }
24036         return this;
24037     },
24038
24039     
24040     toggleMaximize : function(){
24041         return this[this.maximized ? 'restore' : 'maximize']();
24042     },
24043
24044     
24045     fitContainer : function(){
24046         var vs = this.container.getViewSize(false);
24047         this.setSize(vs.width, vs.height);
24048     },
24049
24050     
24051     
24052     setZIndex : function(index){
24053         if(this.modal){
24054             this.mask.setStyle('z-index', index);
24055         }
24056         this.el.setZIndex(++index);
24057         index += 5;
24058
24059         if(this.resizer){
24060             this.resizer.proxy.setStyle('z-index', ++index);
24061         }
24062
24063         this.lastZIndex = index;
24064     },
24065
24066     
24067     alignTo : function(element, position, offsets){
24068         var xy = this.el.getAlignToXY(element, position, offsets);
24069         this.setPagePosition(xy[0], xy[1]);
24070         return this;
24071     },
24072
24073     
24074     anchorTo : function(el, alignment, offsets, monitorScroll){
24075       if(this.doAnchor){
24076           Ext.EventManager.removeResizeListener(this.doAnchor, this);
24077           Ext.EventManager.un(window, 'scroll', this.doAnchor, this);
24078       }
24079       this.doAnchor = function(){
24080           this.alignTo(el, alignment, offsets);
24081       };
24082       Ext.EventManager.onWindowResize(this.doAnchor, this);
24083
24084       var tm = typeof monitorScroll;
24085       if(tm != 'undefined'){
24086           Ext.EventManager.on(window, 'scroll', this.doAnchor, this,
24087               {buffer: tm == 'number' ? monitorScroll : 50});
24088       }
24089       this.doAnchor();
24090       return this;
24091     },
24092
24093     
24094     toFront : function(e){
24095         if(this.manager.bringToFront(this)){
24096             if(!e || !e.getTarget().focus){
24097                 this.focus();
24098             }
24099         }
24100         return this;
24101     },
24102
24103     
24104     setActive : function(active){
24105         if(active){
24106             if(!this.maximized){
24107                 this.el.enableShadow(true);
24108             }
24109             this.fireEvent('activate', this);
24110         }else{
24111             this.el.disableShadow();
24112             this.fireEvent('deactivate', this);
24113         }
24114     },
24115
24116     
24117     toBack : function(){
24118         this.manager.sendToBack(this);
24119         return this;
24120     },
24121
24122     
24123     center : function(){
24124         var xy = this.el.getAlignToXY(this.container, 'c-c');
24125         this.setPagePosition(xy[0], xy[1]);
24126         return this;
24127     }
24128
24129     
24130 });
24131 Ext.reg('window', Ext.Window);
24132
24133
24134 Ext.Window.DD = function(win){
24135     this.win = win;
24136     Ext.Window.DD.superclass.constructor.call(this, win.el.id, 'WindowDD-'+win.id);
24137     this.setHandleElId(win.header.id);
24138     this.scroll = false;
24139 };
24140
24141 Ext.extend(Ext.Window.DD, Ext.dd.DD, {
24142     moveOnly:true,
24143     headerOffsets:[100, 25],
24144     startDrag : function(){
24145         var w = this.win;
24146         this.proxy = w.ghost();
24147         if(w.constrain !== false){
24148             var so = w.el.shadowOffset;
24149             this.constrainTo(w.container, {right: so, left: so, bottom: so});
24150         }else if(w.constrainHeader !== false){
24151             var s = this.proxy.getSize();
24152             this.constrainTo(w.container, {right: -(s.width-this.headerOffsets[0]), bottom: -(s.height-this.headerOffsets[1])});
24153         }
24154     },
24155     b4Drag : Ext.emptyFn,
24156
24157     onDrag : function(e){
24158         this.alignElWithMouse(this.proxy, e.getPageX(), e.getPageY());
24159     },
24160
24161     endDrag : function(e){
24162         this.win.unghost();
24163         this.win.saveState();
24164     }
24165 });
24166
24167 Ext.WindowGroup = function(){
24168     var list = {};
24169     var accessList = [];
24170     var front = null;
24171
24172     
24173     var sortWindows = function(d1, d2){
24174         return (!d1._lastAccess || d1._lastAccess < d2._lastAccess) ? -1 : 1;
24175     };
24176
24177     
24178     var orderWindows = function(){
24179         var a = accessList, len = a.length;
24180         if(len > 0){
24181             a.sort(sortWindows);
24182             var seed = a[0].manager.zseed;
24183             for(var i = 0; i < len; i++){
24184                 var win = a[i];
24185                 if(win && !win.hidden){
24186                     win.setZIndex(seed + (i*10));
24187                 }
24188             }
24189         }
24190         activateLast();
24191     };
24192
24193     
24194     var setActiveWin = function(win){
24195         if(win != front){
24196             if(front){
24197                 front.setActive(false);
24198             }
24199             front = win;
24200             if(win){
24201                 win.setActive(true);
24202             }
24203         }
24204     };
24205
24206     
24207     var activateLast = function(){
24208         for(var i = accessList.length-1; i >=0; --i) {
24209             if(!accessList[i].hidden){
24210                 setActiveWin(accessList[i]);
24211                 return;
24212             }
24213         }
24214         
24215         setActiveWin(null);
24216     };
24217
24218     return {
24219         
24220         zseed : 9000,
24221
24222         
24223         register : function(win){
24224             if(win.manager){
24225                 win.manager.unregister(win);
24226             }
24227             win.manager = this;
24228
24229             list[win.id] = win;
24230             accessList.push(win);
24231             win.on('hide', activateLast);
24232         },
24233
24234         
24235         unregister : function(win){
24236             delete win.manager;
24237             delete list[win.id];
24238             win.un('hide', activateLast);
24239             accessList.remove(win);
24240         },
24241
24242         
24243         get : function(id){
24244             return typeof id == "object" ? id : list[id];
24245         },
24246
24247         
24248         bringToFront : function(win){
24249             win = this.get(win);
24250             if(win != front){
24251                 win._lastAccess = new Date().getTime();
24252                 orderWindows();
24253                 return true;
24254             }
24255             return false;
24256         },
24257
24258         
24259         sendToBack : function(win){
24260             win = this.get(win);
24261             win._lastAccess = -(new Date().getTime());
24262             orderWindows();
24263             return win;
24264         },
24265
24266         
24267         hideAll : function(){
24268             for(var id in list){
24269                 if(list[id] && typeof list[id] != "function" && list[id].isVisible()){
24270                     list[id].hide();
24271                 }
24272             }
24273         },
24274
24275         
24276         getActive : function(){
24277             return front;
24278         },
24279
24280         
24281         getBy : function(fn, scope){
24282             var r = [];
24283             for(var i = accessList.length-1; i >=0; --i) {
24284                 var win = accessList[i];
24285                 if(fn.call(scope||win, win) !== false){
24286                     r.push(win);
24287                 }
24288             }
24289             return r;
24290         },
24291
24292         
24293         each : function(fn, scope){
24294             for(var id in list){
24295                 if(list[id] && typeof list[id] != "function"){
24296                     if(fn.call(scope || list[id], list[id]) === false){
24297                         return;
24298                     }
24299                 }
24300             }
24301         }
24302     };
24303 };
24304
24305
24306
24307 Ext.WindowMgr = new Ext.WindowGroup();
24308 Ext.MessageBox = function(){
24309     var dlg, opt, mask, waitTimer,
24310         bodyEl, msgEl, textboxEl, textareaEl, progressBar, pp, iconEl, spacerEl,
24311         buttons, activeTextEl, bwidth, bufferIcon = '', iconCls = '',
24312         buttonNames = ['ok', 'yes', 'no', 'cancel'];
24313
24314     
24315     var handleButton = function(button){
24316         buttons[button].blur();
24317         if(dlg.isVisible()){
24318             dlg.hide();
24319             handleHide();
24320             Ext.callback(opt.fn, opt.scope||window, [button, activeTextEl.dom.value, opt], 1);
24321         }
24322     };
24323
24324     
24325     var handleHide = function(){
24326         if(opt && opt.cls){
24327             dlg.el.removeClass(opt.cls);
24328         }
24329         progressBar.reset();        
24330     };
24331
24332     
24333     var handleEsc = function(d, k, e){
24334         if(opt && opt.closable !== false){
24335             dlg.hide();
24336             handleHide();
24337         }
24338         if(e){
24339             e.stopEvent();
24340         }
24341     };
24342
24343     
24344     var updateButtons = function(b){
24345         var width = 0,
24346             cfg;
24347         if(!b){
24348             Ext.each(buttonNames, function(name){
24349                 buttons[name].hide();
24350             });
24351             return width;
24352         }
24353         dlg.footer.dom.style.display = '';
24354         Ext.iterate(buttons, function(name, btn){
24355             cfg = b[name];
24356             if(cfg){
24357                 btn.show();
24358                 btn.setText(Ext.isString(cfg) ? cfg : Ext.MessageBox.buttonText[name]);
24359                 width += btn.getEl().getWidth() + 15;
24360             }else{
24361                 btn.hide();
24362             }
24363         });
24364         return width;
24365     };
24366
24367     return {
24368         
24369         getDialog : function(titleText){
24370            if(!dlg){
24371                 var btns = [];
24372                 
24373                 buttons = {};
24374                 Ext.each(buttonNames, function(name){
24375                     btns.push(buttons[name] = new Ext.Button({
24376                         text: this.buttonText[name],
24377                         handler: handleButton.createCallback(name),
24378                         hideMode: 'offsets'
24379                     }));
24380                 }, this);
24381                 dlg = new Ext.Window({
24382                     autoCreate : true,
24383                     title:titleText,
24384                     resizable:false,
24385                     constrain:true,
24386                     constrainHeader:true,
24387                     minimizable : false,
24388                     maximizable : false,
24389                     stateful: false,
24390                     modal: true,
24391                     shim:true,
24392                     buttonAlign:"center",
24393                     width:400,
24394                     height:100,
24395                     minHeight: 80,
24396                     plain:true,
24397                     footer:true,
24398                     closable:true,
24399                     close : function(){
24400                         if(opt && opt.buttons && opt.buttons.no && !opt.buttons.cancel){
24401                             handleButton("no");
24402                         }else{
24403                             handleButton("cancel");
24404                         }
24405                     },
24406                     fbar: new Ext.Toolbar({
24407                         items: btns,
24408                         enableOverflow: false
24409                     })
24410                 });
24411                 dlg.render(document.body);
24412                 dlg.getEl().addClass('x-window-dlg');
24413                 mask = dlg.mask;
24414                 bodyEl = dlg.body.createChild({
24415                     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>'
24416                 });
24417                 iconEl = Ext.get(bodyEl.dom.firstChild);
24418                 var contentEl = bodyEl.dom.childNodes[1];
24419                 msgEl = Ext.get(contentEl.firstChild);
24420                 textboxEl = Ext.get(contentEl.childNodes[2].firstChild);
24421                 textboxEl.enableDisplayMode();
24422                 textboxEl.addKeyListener([10,13], function(){
24423                     if(dlg.isVisible() && opt && opt.buttons){
24424                         if(opt.buttons.ok){
24425                             handleButton("ok");
24426                         }else if(opt.buttons.yes){
24427                             handleButton("yes");
24428                         }
24429                     }
24430                 });
24431                 textareaEl = Ext.get(contentEl.childNodes[2].childNodes[1]);
24432                 textareaEl.enableDisplayMode();
24433                 progressBar = new Ext.ProgressBar({
24434                     renderTo:bodyEl
24435                 });
24436                bodyEl.createChild({cls:'x-clear'});
24437             }
24438             return dlg;
24439         },
24440
24441         
24442         updateText : function(text){
24443             if(!dlg.isVisible() && !opt.width){
24444                 dlg.setSize(this.maxWidth, 100); 
24445             }
24446             msgEl.update(text || '&#160;');
24447
24448             var iw = iconCls != '' ? (iconEl.getWidth() + iconEl.getMargins('lr')) : 0;
24449             var mw = msgEl.getWidth() + msgEl.getMargins('lr');
24450             var fw = dlg.getFrameWidth('lr');
24451             var bw = dlg.body.getFrameWidth('lr');
24452             if (Ext.isIE && iw > 0){
24453                 
24454                 
24455                 iw += 3;
24456             }
24457             var w = Math.max(Math.min(opt.width || iw+mw+fw+bw, this.maxWidth),
24458                         Math.max(opt.minWidth || this.minWidth, bwidth || 0));
24459
24460             if(opt.prompt === true){
24461                 activeTextEl.setWidth(w-iw-fw-bw);
24462             }
24463             if(opt.progress === true || opt.wait === true){
24464                 progressBar.setSize(w-iw-fw-bw);
24465             }
24466             if(Ext.isIE && w == bwidth){
24467                 w += 4; 
24468             }
24469             dlg.setSize(w, 'auto').center();
24470             return this;
24471         },
24472
24473         
24474         updateProgress : function(value, progressText, msg){
24475             progressBar.updateProgress(value, progressText);
24476             if(msg){
24477                 this.updateText(msg);
24478             }
24479             return this;
24480         },
24481
24482         
24483         isVisible : function(){
24484             return dlg && dlg.isVisible();
24485         },
24486
24487         
24488         hide : function(){
24489             var proxy = dlg ? dlg.activeGhost : null;
24490             if(this.isVisible() || proxy){
24491                 dlg.hide();
24492                 handleHide();
24493                 if (proxy){
24494                     
24495                     
24496                     dlg.unghost(false, false);
24497                 } 
24498             }
24499             return this;
24500         },
24501
24502         
24503         show : function(options){
24504             if(this.isVisible()){
24505                 this.hide();
24506             }
24507             opt = options;
24508             var d = this.getDialog(opt.title || "&#160;");
24509
24510             d.setTitle(opt.title || "&#160;");
24511             var allowClose = (opt.closable !== false && opt.progress !== true && opt.wait !== true);
24512             d.tools.close.setDisplayed(allowClose);
24513             activeTextEl = textboxEl;
24514             opt.prompt = opt.prompt || (opt.multiline ? true : false);
24515             if(opt.prompt){
24516                 if(opt.multiline){
24517                     textboxEl.hide();
24518                     textareaEl.show();
24519                     textareaEl.setHeight(Ext.isNumber(opt.multiline) ? opt.multiline : this.defaultTextHeight);
24520                     activeTextEl = textareaEl;
24521                 }else{
24522                     textboxEl.show();
24523                     textareaEl.hide();
24524                 }
24525             }else{
24526                 textboxEl.hide();
24527                 textareaEl.hide();
24528             }
24529             activeTextEl.dom.value = opt.value || "";
24530             if(opt.prompt){
24531                 d.focusEl = activeTextEl;
24532             }else{
24533                 var bs = opt.buttons;
24534                 var db = null;
24535                 if(bs && bs.ok){
24536                     db = buttons["ok"];
24537                 }else if(bs && bs.yes){
24538                     db = buttons["yes"];
24539                 }
24540                 if (db){
24541                     d.focusEl = db;
24542                 }
24543             }
24544             if(opt.iconCls){
24545               d.setIconClass(opt.iconCls);
24546             }
24547             this.setIcon(Ext.isDefined(opt.icon) ? opt.icon : bufferIcon);
24548             bwidth = updateButtons(opt.buttons);
24549             progressBar.setVisible(opt.progress === true || opt.wait === true);
24550             this.updateProgress(0, opt.progressText);
24551             this.updateText(opt.msg);
24552             if(opt.cls){
24553                 d.el.addClass(opt.cls);
24554             }
24555             d.proxyDrag = opt.proxyDrag === true;
24556             d.modal = opt.modal !== false;
24557             d.mask = opt.modal !== false ? mask : false;
24558             if(!d.isVisible()){
24559                 
24560                 document.body.appendChild(dlg.el.dom);
24561                 d.setAnimateTarget(opt.animEl);
24562                 
24563                 d.on('show', function(){
24564                     if(allowClose === true){
24565                         d.keyMap.enable();
24566                     }else{
24567                         d.keyMap.disable();
24568                     }
24569                 }, this, {single:true});
24570                 d.show(opt.animEl);
24571             }
24572             if(opt.wait === true){
24573                 progressBar.wait(opt.waitConfig);
24574             }
24575             return this;
24576         },
24577
24578         
24579         setIcon : function(icon){
24580             if(!dlg){
24581                 bufferIcon = icon;
24582                 return;
24583             }
24584             bufferIcon = undefined;
24585             if(icon && icon != ''){
24586                 iconEl.removeClass('x-hidden');
24587                 iconEl.replaceClass(iconCls, icon);
24588                 bodyEl.addClass('x-dlg-icon');
24589                 iconCls = icon;
24590             }else{
24591                 iconEl.replaceClass(iconCls, 'x-hidden');
24592                 bodyEl.removeClass('x-dlg-icon');
24593                 iconCls = '';
24594             }
24595             return this;
24596         },
24597
24598         
24599         progress : function(title, msg, progressText){
24600             this.show({
24601                 title : title,
24602                 msg : msg,
24603                 buttons: false,
24604                 progress:true,
24605                 closable:false,
24606                 minWidth: this.minProgressWidth,
24607                 progressText: progressText
24608             });
24609             return this;
24610         },
24611
24612         
24613         wait : function(msg, title, config){
24614             this.show({
24615                 title : title,
24616                 msg : msg,
24617                 buttons: false,
24618                 closable:false,
24619                 wait:true,
24620                 modal:true,
24621                 minWidth: this.minProgressWidth,
24622                 waitConfig: config
24623             });
24624             return this;
24625         },
24626
24627         
24628         alert : function(title, msg, fn, scope){
24629             this.show({
24630                 title : title,
24631                 msg : msg,
24632                 buttons: this.OK,
24633                 fn: fn,
24634                 scope : scope
24635             });
24636             return this;
24637         },
24638
24639         
24640         confirm : function(title, msg, fn, scope){
24641             this.show({
24642                 title : title,
24643                 msg : msg,
24644                 buttons: this.YESNO,
24645                 fn: fn,
24646                 scope : scope,
24647                 icon: this.QUESTION
24648             });
24649             return this;
24650         },
24651
24652         
24653         prompt : function(title, msg, fn, scope, multiline, value){
24654             this.show({
24655                 title : title,
24656                 msg : msg,
24657                 buttons: this.OKCANCEL,
24658                 fn: fn,
24659                 minWidth:250,
24660                 scope : scope,
24661                 prompt:true,
24662                 multiline: multiline,
24663                 value: value
24664             });
24665             return this;
24666         },
24667
24668         
24669         OK : {ok:true},
24670         
24671         CANCEL : {cancel:true},
24672         
24673         OKCANCEL : {ok:true, cancel:true},
24674         
24675         YESNO : {yes:true, no:true},
24676         
24677         YESNOCANCEL : {yes:true, no:true, cancel:true},
24678         
24679         INFO : 'ext-mb-info',
24680         
24681         WARNING : 'ext-mb-warning',
24682         
24683         QUESTION : 'ext-mb-question',
24684         
24685         ERROR : 'ext-mb-error',
24686
24687         
24688         defaultTextHeight : 75,
24689         
24690         maxWidth : 600,
24691         
24692         minWidth : 100,
24693         
24694         minProgressWidth : 250,
24695         
24696         buttonText : {
24697             ok : "OK",
24698             cancel : "Cancel",
24699             yes : "Yes",
24700             no : "No"
24701         }
24702     };
24703 }();
24704
24705
24706 Ext.Msg = Ext.MessageBox;
24707 Ext.dd.PanelProxy = function(panel, config){
24708     this.panel = panel;
24709     this.id = this.panel.id +'-ddproxy';
24710     Ext.apply(this, config);
24711 };
24712
24713 Ext.dd.PanelProxy.prototype = {
24714     
24715     insertProxy : true,
24716
24717     
24718     setStatus : Ext.emptyFn,
24719     reset : Ext.emptyFn,
24720     update : Ext.emptyFn,
24721     stop : Ext.emptyFn,
24722     sync: Ext.emptyFn,
24723
24724     
24725     getEl : function(){
24726         return this.ghost;
24727     },
24728
24729     
24730     getGhost : function(){
24731         return this.ghost;
24732     },
24733
24734     
24735     getProxy : function(){
24736         return this.proxy;
24737     },
24738
24739     
24740     hide : function(){
24741         if(this.ghost){
24742             if(this.proxy){
24743                 this.proxy.remove();
24744                 delete this.proxy;
24745             }
24746             this.panel.el.dom.style.display = '';
24747             this.ghost.remove();
24748             delete this.ghost;
24749         }
24750     },
24751
24752     
24753     show : function(){
24754         if(!this.ghost){
24755             this.ghost = this.panel.createGhost(undefined, undefined, Ext.getBody());
24756             this.ghost.setXY(this.panel.el.getXY())
24757             if(this.insertProxy){
24758                 this.proxy = this.panel.el.insertSibling({cls:'x-panel-dd-spacer'});
24759                 this.proxy.setSize(this.panel.getSize());
24760             }
24761             this.panel.el.dom.style.display = 'none';
24762         }
24763     },
24764
24765     
24766     repair : function(xy, callback, scope){
24767         this.hide();
24768         if(typeof callback == "function"){
24769             callback.call(scope || this);
24770         }
24771     },
24772
24773     
24774     moveProxy : function(parentNode, before){
24775         if(this.proxy){
24776             parentNode.insertBefore(this.proxy.dom, before);
24777         }
24778     }
24779 };
24780
24781
24782 Ext.Panel.DD = function(panel, cfg){
24783     this.panel = panel;
24784     this.dragData = {panel: panel};
24785     this.proxy = new Ext.dd.PanelProxy(panel, cfg);
24786     Ext.Panel.DD.superclass.constructor.call(this, panel.el, cfg);
24787     var h = panel.header;
24788     if(h){
24789         this.setHandleElId(h.id);
24790     }
24791     (h ? h : this.panel.body).setStyle('cursor', 'move');
24792     this.scroll = false;
24793 };
24794
24795 Ext.extend(Ext.Panel.DD, Ext.dd.DragSource, {
24796     showFrame: Ext.emptyFn,
24797     startDrag: Ext.emptyFn,
24798     b4StartDrag: function(x, y) {
24799         this.proxy.show();
24800     },
24801     b4MouseDown: function(e) {
24802         var x = e.getPageX();
24803         var y = e.getPageY();
24804         this.autoOffset(x, y);
24805     },
24806     onInitDrag : function(x, y){
24807         this.onStartDrag(x, y);
24808         return true;
24809     },
24810     createFrame : Ext.emptyFn,
24811     getDragEl : function(e){
24812         return this.proxy.ghost.dom;
24813     },
24814     endDrag : function(e){
24815         this.proxy.hide();
24816         this.panel.saveState();
24817     },
24818
24819     autoOffset : function(x, y) {
24820         x -= this.startPageX;
24821         y -= this.startPageY;
24822         this.setDelta(x, y);
24823     }
24824 });
24825 Ext.state.Provider = function(){
24826     
24827     this.addEvents("statechange");
24828     this.state = {};
24829     Ext.state.Provider.superclass.constructor.call(this);
24830 };
24831 Ext.extend(Ext.state.Provider, Ext.util.Observable, {
24832     
24833     get : function(name, defaultValue){
24834         return typeof this.state[name] == "undefined" ?
24835             defaultValue : this.state[name];
24836     },
24837
24838     
24839     clear : function(name){
24840         delete this.state[name];
24841         this.fireEvent("statechange", this, name, null);
24842     },
24843
24844     
24845     set : function(name, value){
24846         this.state[name] = value;
24847         this.fireEvent("statechange", this, name, value);
24848     },
24849
24850     
24851     decodeValue : function(cookie){
24852         var re = /^(a|n|d|b|s|o)\:(.*)$/;
24853         var matches = re.exec(unescape(cookie));
24854         if(!matches || !matches[1]) return; 
24855         var type = matches[1];
24856         var v = matches[2];
24857         switch(type){
24858             case "n":
24859                 return parseFloat(v);
24860             case "d":
24861                 return new Date(Date.parse(v));
24862             case "b":
24863                 return (v == "1");
24864             case "a":
24865                 var all = [];
24866                 if(v != ''){
24867                     Ext.each(v.split('^'), function(val){
24868                         all.push(this.decodeValue(val));
24869                     }, this);
24870                 }
24871                 return all;
24872            case "o":
24873                 var all = {};
24874                 if(v != ''){
24875                     Ext.each(v.split('^'), function(val){
24876                         var kv = val.split('=');
24877                         all[kv[0]] = this.decodeValue(kv[1]);
24878                     }, this);
24879                 }
24880                 return all;
24881            default:
24882                 return v;
24883         }
24884     },
24885
24886     
24887     encodeValue : function(v){
24888         var enc;
24889         if(typeof v == "number"){
24890             enc = "n:" + v;
24891         }else if(typeof v == "boolean"){
24892             enc = "b:" + (v ? "1" : "0");
24893         }else if(Ext.isDate(v)){
24894             enc = "d:" + v.toGMTString();
24895         }else if(Ext.isArray(v)){
24896             var flat = "";
24897             for(var i = 0, len = v.length; i < len; i++){
24898                 flat += this.encodeValue(v[i]);
24899                 if(i != len-1) flat += "^";
24900             }
24901             enc = "a:" + flat;
24902         }else if(typeof v == "object"){
24903             var flat = "";
24904             for(var key in v){
24905                 if(typeof v[key] != "function" && v[key] !== undefined){
24906                     flat += key + "=" + this.encodeValue(v[key]) + "^";
24907                 }
24908             }
24909             enc = "o:" + flat.substring(0, flat.length-1);
24910         }else{
24911             enc = "s:" + v;
24912         }
24913         return escape(enc);
24914     }
24915 });
24916
24917 Ext.state.Manager = function(){
24918     var provider = new Ext.state.Provider();
24919
24920     return {
24921         
24922         setProvider : function(stateProvider){
24923             provider = stateProvider;
24924         },
24925
24926         
24927         get : function(key, defaultValue){
24928             return provider.get(key, defaultValue);
24929         },
24930
24931         
24932          set : function(key, value){
24933             provider.set(key, value);
24934         },
24935
24936         
24937         clear : function(key){
24938             provider.clear(key);
24939         },
24940
24941         
24942         getProvider : function(){
24943             return provider;
24944         }
24945     };
24946 }();
24947
24948 Ext.state.CookieProvider = function(config){
24949     Ext.state.CookieProvider.superclass.constructor.call(this);
24950     this.path = "/";
24951     this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); 
24952     this.domain = null;
24953     this.secure = false;
24954     Ext.apply(this, config);
24955     this.state = this.readCookies();
24956 };
24957
24958 Ext.extend(Ext.state.CookieProvider, Ext.state.Provider, {
24959     
24960     set : function(name, value){
24961         if(typeof value == "undefined" || value === null){
24962             this.clear(name);
24963             return;
24964         }
24965         this.setCookie(name, value);
24966         Ext.state.CookieProvider.superclass.set.call(this, name, value);
24967     },
24968
24969     
24970     clear : function(name){
24971         this.clearCookie(name);
24972         Ext.state.CookieProvider.superclass.clear.call(this, name);
24973     },
24974
24975     
24976     readCookies : function(){
24977         var cookies = {};
24978         var c = document.cookie + ";";
24979         var re = /\s?(.*?)=(.*?);/g;
24980         var matches;
24981         while((matches = re.exec(c)) != null){
24982             var name = matches[1];
24983             var value = matches[2];
24984             if(name && name.substring(0,3) == "ys-"){
24985                 cookies[name.substr(3)] = this.decodeValue(value);
24986             }
24987         }
24988         return cookies;
24989     },
24990
24991     
24992     setCookie : function(name, value){
24993         document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
24994            ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
24995            ((this.path == null) ? "" : ("; path=" + this.path)) +
24996            ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
24997            ((this.secure == true) ? "; secure" : "");
24998     },
24999
25000     
25001     clearCookie : function(name){
25002         document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
25003            ((this.path == null) ? "" : ("; path=" + this.path)) +
25004            ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
25005            ((this.secure == true) ? "; secure" : "");
25006     }
25007 });
25008 Ext.DataView = Ext.extend(Ext.BoxComponent, {
25009     
25010     
25011     
25012     
25013     
25014     
25015     
25016     
25017     
25018     selectedClass : "x-view-selected",
25019     
25020     emptyText : "",
25021
25022     
25023     deferEmptyText: true,
25024     
25025     trackOver: false,
25026
25027     
25028     last: false,
25029
25030     
25031     initComponent : function(){
25032         Ext.DataView.superclass.initComponent.call(this);
25033         if(Ext.isString(this.tpl) || Ext.isArray(this.tpl)){
25034             this.tpl = new Ext.XTemplate(this.tpl);
25035         }
25036
25037         this.addEvents(
25038             
25039             "beforeclick",
25040             
25041             "click",
25042             
25043             "mouseenter",
25044             
25045             "mouseleave",
25046             
25047             "containerclick",
25048             
25049             "dblclick",
25050             
25051             "contextmenu",
25052             
25053             "containercontextmenu",
25054             
25055             "selectionchange",
25056
25057             
25058             "beforeselect"
25059         );
25060
25061         this.store = Ext.StoreMgr.lookup(this.store);
25062         this.all = new Ext.CompositeElementLite();
25063         this.selected = new Ext.CompositeElementLite();
25064     },
25065
25066     
25067     afterRender : function(){
25068         Ext.DataView.superclass.afterRender.call(this);
25069
25070                 this.mon(this.getTemplateTarget(), {
25071             "click": this.onClick,
25072             "dblclick": this.onDblClick,
25073             "contextmenu": this.onContextMenu,
25074             scope:this
25075         });
25076
25077         if(this.overClass || this.trackOver){
25078             this.mon(this.getTemplateTarget(), {
25079                 "mouseover": this.onMouseOver,
25080                 "mouseout": this.onMouseOut,
25081                 scope:this
25082             });
25083         }
25084
25085         if(this.store){
25086             this.bindStore(this.store, true);
25087         }
25088     },
25089
25090     
25091     refresh : function(){
25092         this.clearSelections(false, true);
25093         var el = this.getTemplateTarget();
25094         el.update("");
25095         var records = this.store.getRange();
25096         if(records.length < 1){
25097             if(!this.deferEmptyText || this.hasSkippedEmptyText){
25098                 el.update(this.emptyText);
25099             }
25100             this.all.clear();
25101         }else{
25102             this.tpl.overwrite(el, this.collectData(records, 0));
25103             this.all.fill(Ext.query(this.itemSelector, el.dom));
25104             this.updateIndexes(0);
25105         }
25106         this.hasSkippedEmptyText = true;
25107     },
25108
25109     getTemplateTarget: function(){
25110         return this.el;
25111     },
25112
25113     
25114     prepareData : function(data){
25115         return data;
25116     },
25117
25118     
25119     collectData : function(records, startIndex){
25120         var r = [];
25121         for(var i = 0, len = records.length; i < len; i++){
25122             r[r.length] = this.prepareData(records[i].data, startIndex+i, records[i]);
25123         }
25124         return r;
25125     },
25126
25127     
25128     bufferRender : function(records){
25129         var div = document.createElement('div');
25130         this.tpl.overwrite(div, this.collectData(records));
25131         return Ext.query(this.itemSelector, div);
25132     },
25133
25134     
25135     onUpdate : function(ds, record){
25136         var index = this.store.indexOf(record);
25137         if(index > -1){
25138             var sel = this.isSelected(index);
25139             var original = this.all.elements[index];
25140             var node = this.bufferRender([record], index)[0];
25141
25142             this.all.replaceElement(index, node, true);
25143             if(sel){
25144                 this.selected.replaceElement(original, node);
25145                 this.all.item(index).addClass(this.selectedClass);
25146             }
25147             this.updateIndexes(index, index);
25148         }
25149     },
25150
25151     
25152     onAdd : function(ds, records, index){
25153         if(this.all.getCount() === 0){
25154             this.refresh();
25155             return;
25156         }
25157         var nodes = this.bufferRender(records, index), n, a = this.all.elements;
25158         if(index < this.all.getCount()){
25159             n = this.all.item(index).insertSibling(nodes, 'before', true);
25160             a.splice.apply(a, [index, 0].concat(nodes));
25161         }else{
25162             n = this.all.last().insertSibling(nodes, 'after', true);
25163             a.push.apply(a, nodes);
25164         }
25165         this.updateIndexes(index);
25166     },
25167
25168     
25169     onRemove : function(ds, record, index){
25170         this.deselect(index);
25171         this.all.removeElement(index, true);
25172         this.updateIndexes(index);
25173         if (this.store.getCount() === 0){
25174             this.refresh();
25175         }
25176     },
25177
25178     
25179     refreshNode : function(index){
25180         this.onUpdate(this.store, this.store.getAt(index));
25181     },
25182
25183     
25184     updateIndexes : function(startIndex, endIndex){
25185         var ns = this.all.elements;
25186         startIndex = startIndex || 0;
25187         endIndex = endIndex || ((endIndex === 0) ? 0 : (ns.length - 1));
25188         for(var i = startIndex; i <= endIndex; i++){
25189             ns[i].viewIndex = i;
25190         }
25191     },
25192     
25193     
25194     getStore : function(){
25195         return this.store;
25196     },
25197
25198     
25199     bindStore : function(store, initial){
25200         if(!initial && this.store){
25201             if(store !== this.store && this.store.autoDestroy){
25202                 this.store.destroy();
25203             }else{
25204                 this.store.un("beforeload", this.onBeforeLoad, this);
25205                 this.store.un("datachanged", this.refresh, this);
25206                 this.store.un("add", this.onAdd, this);
25207                 this.store.un("remove", this.onRemove, this);
25208                 this.store.un("update", this.onUpdate, this);
25209                 this.store.un("clear", this.refresh, this);
25210             }
25211             if(!store){
25212                 this.store = null;
25213             }
25214         }
25215         if(store){
25216             store = Ext.StoreMgr.lookup(store);
25217             store.on({
25218                 scope: this,
25219                 beforeload: this.onBeforeLoad,
25220                 datachanged: this.refresh,
25221                 add: this.onAdd,
25222                 remove: this.onRemove,
25223                 update: this.onUpdate,
25224                 clear: this.refresh
25225             });
25226         }
25227         this.store = store;
25228         if(store){
25229             this.refresh();
25230         }
25231     },
25232
25233     
25234     findItemFromChild : function(node){
25235         return Ext.fly(node).findParent(this.itemSelector, this.getTemplateTarget());
25236     },
25237
25238     
25239     onClick : function(e){
25240         var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
25241         if(item){
25242             var index = this.indexOf(item);
25243             if(this.onItemClick(item, index, e) !== false){
25244                 this.fireEvent("click", this, index, item, e);
25245             }
25246         }else{
25247             if(this.fireEvent("containerclick", this, e) !== false){
25248                 this.onContainerClick(e);
25249             }
25250         }
25251     },
25252
25253     onContainerClick : function(e){
25254         this.clearSelections();
25255     },
25256
25257     
25258     onContextMenu : function(e){
25259         var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
25260         if(item){
25261             this.fireEvent("contextmenu", this, this.indexOf(item), item, e);
25262         }else{
25263             this.fireEvent("containercontextmenu", this, e);
25264         }
25265     },
25266
25267     
25268     onDblClick : function(e){
25269         var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
25270         if(item){
25271             this.fireEvent("dblclick", this, this.indexOf(item), item, e);
25272         }
25273     },
25274
25275     
25276     onMouseOver : function(e){
25277         var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
25278         if(item && item !== this.lastItem){
25279             this.lastItem = item;
25280             Ext.fly(item).addClass(this.overClass);
25281             this.fireEvent("mouseenter", this, this.indexOf(item), item, e);
25282         }
25283     },
25284
25285     
25286     onMouseOut : function(e){
25287         if(this.lastItem){
25288             if(!e.within(this.lastItem, true, true)){
25289                 Ext.fly(this.lastItem).removeClass(this.overClass);
25290                 this.fireEvent("mouseleave", this, this.indexOf(this.lastItem), this.lastItem, e);
25291                 delete this.lastItem;
25292             }
25293         }
25294     },
25295
25296     
25297     onItemClick : function(item, index, e){
25298         if(this.fireEvent("beforeclick", this, index, item, e) === false){
25299             return false;
25300         }
25301         if(this.multiSelect){
25302             this.doMultiSelection(item, index, e);
25303             e.preventDefault();
25304         }else if(this.singleSelect){
25305             this.doSingleSelection(item, index, e);
25306             e.preventDefault();
25307         }
25308         return true;
25309     },
25310
25311     
25312     doSingleSelection : function(item, index, e){
25313         if(e.ctrlKey && this.isSelected(index)){
25314             this.deselect(index);
25315         }else{
25316             this.select(index, false);
25317         }
25318     },
25319
25320     
25321     doMultiSelection : function(item, index, e){
25322         if(e.shiftKey && this.last !== false){
25323             var last = this.last;
25324             this.selectRange(last, index, e.ctrlKey);
25325             this.last = last; 
25326         }else{
25327             if((e.ctrlKey||this.simpleSelect) && this.isSelected(index)){
25328                 this.deselect(index);
25329             }else{
25330                 this.select(index, e.ctrlKey || e.shiftKey || this.simpleSelect);
25331             }
25332         }
25333     },
25334
25335     
25336     getSelectionCount : function(){
25337         return this.selected.getCount();
25338     },
25339
25340     
25341     getSelectedNodes : function(){
25342         return this.selected.elements;
25343     },
25344
25345     
25346     getSelectedIndexes : function(){
25347         var indexes = [], s = this.selected.elements;
25348         for(var i = 0, len = s.length; i < len; i++){
25349             indexes.push(s[i].viewIndex);
25350         }
25351         return indexes;
25352     },
25353
25354     
25355     getSelectedRecords : function(){
25356         var r = [], s = this.selected.elements;
25357         for(var i = 0, len = s.length; i < len; i++){
25358             r[r.length] = this.store.getAt(s[i].viewIndex);
25359         }
25360         return r;
25361     },
25362
25363     
25364     getRecords : function(nodes){
25365         var r = [], s = nodes;
25366         for(var i = 0, len = s.length; i < len; i++){
25367             r[r.length] = this.store.getAt(s[i].viewIndex);
25368         }
25369         return r;
25370     },
25371
25372     
25373     getRecord : function(node){
25374         return this.store.getAt(node.viewIndex);
25375     },
25376
25377     
25378     clearSelections : function(suppressEvent, skipUpdate){
25379         if((this.multiSelect || this.singleSelect) && this.selected.getCount() > 0){
25380             if(!skipUpdate){
25381                 this.selected.removeClass(this.selectedClass);
25382             }
25383             this.selected.clear();
25384             this.last = false;
25385             if(!suppressEvent){
25386                 this.fireEvent("selectionchange", this, this.selected.elements);
25387             }
25388         }
25389     },
25390
25391     
25392     isSelected : function(node){
25393         return this.selected.contains(this.getNode(node));
25394     },
25395
25396     
25397     deselect : function(node){
25398         if(this.isSelected(node)){
25399             node = this.getNode(node);
25400             this.selected.removeElement(node);
25401             if(this.last == node.viewIndex){
25402                 this.last = false;
25403             }
25404             Ext.fly(node).removeClass(this.selectedClass);
25405             this.fireEvent("selectionchange", this, this.selected.elements);
25406         }
25407     },
25408
25409     
25410     select : function(nodeInfo, keepExisting, suppressEvent){
25411         if(Ext.isArray(nodeInfo)){
25412             if(!keepExisting){
25413                 this.clearSelections(true);
25414             }
25415             for(var i = 0, len = nodeInfo.length; i < len; i++){
25416                 this.select(nodeInfo[i], true, true);
25417             }
25418             if(!suppressEvent){
25419                 this.fireEvent("selectionchange", this, this.selected.elements);
25420             }
25421         } else{
25422             var node = this.getNode(nodeInfo);
25423             if(!keepExisting){
25424                 this.clearSelections(true);
25425             }
25426             if(node && !this.isSelected(node)){
25427                 if(this.fireEvent("beforeselect", this, node, this.selected.elements) !== false){
25428                     Ext.fly(node).addClass(this.selectedClass);
25429                     this.selected.add(node);
25430                     this.last = node.viewIndex;
25431                     if(!suppressEvent){
25432                         this.fireEvent("selectionchange", this, this.selected.elements);
25433                     }
25434                 }
25435             }
25436         }
25437     },
25438
25439     
25440     selectRange : function(start, end, keepExisting){
25441         if(!keepExisting){
25442             this.clearSelections(true);
25443         }
25444         this.select(this.getNodes(start, end), true);
25445     },
25446
25447     
25448     getNode : function(nodeInfo){
25449         if(Ext.isString(nodeInfo)){
25450             return document.getElementById(nodeInfo);
25451         }else if(Ext.isNumber(nodeInfo)){
25452             return this.all.elements[nodeInfo];
25453         }
25454         return nodeInfo;
25455     },
25456
25457     
25458     getNodes : function(start, end){
25459         var ns = this.all.elements;
25460         start = start || 0;
25461         end = !Ext.isDefined(end) ? Math.max(ns.length - 1, 0) : end;
25462         var nodes = [], i;
25463         if(start <= end){
25464             for(i = start; i <= end && ns[i]; i++){
25465                 nodes.push(ns[i]);
25466             }
25467         } else{
25468             for(i = start; i >= end && ns[i]; i--){
25469                 nodes.push(ns[i]);
25470             }
25471         }
25472         return nodes;
25473     },
25474
25475     
25476     indexOf : function(node){
25477         node = this.getNode(node);
25478         if(Ext.isNumber(node.viewIndex)){
25479             return node.viewIndex;
25480         }
25481         return this.all.indexOf(node);
25482     },
25483
25484     
25485     onBeforeLoad : function(){
25486         if(this.loadingText){
25487             this.clearSelections(false, true);
25488             this.getTemplateTarget().update('<div class="loading-indicator">'+this.loadingText+'</div>');
25489             this.all.clear();
25490         }
25491     },
25492
25493     onDestroy : function(){
25494         this.all.clear();
25495         this.selected.clear();
25496         Ext.DataView.superclass.onDestroy.call(this);
25497         this.bindStore(null);
25498     }
25499 });
25500
25501
25502 Ext.DataView.prototype.setStore = Ext.DataView.prototype.bindStore;
25503
25504 Ext.reg('dataview', Ext.DataView);
25505
25506 Ext.list.ListView = Ext.extend(Ext.DataView, {
25507     
25508     
25509     
25510     itemSelector: 'dl',
25511     
25512     selectedClass:'x-list-selected',
25513     
25514     overClass:'x-list-over',
25515     
25516     
25517     scrollOffset : undefined,
25518     
25519     columnResize: true,
25520     
25521     
25522     columnSort: true,
25523     
25524
25525     
25526     maxWidth: Ext.isIE ? 99 : 100,
25527     
25528     initComponent : function(){
25529         if(this.columnResize){
25530             this.colResizer = new Ext.list.ColumnResizer(this.colResizer);
25531             this.colResizer.init(this);
25532         }
25533         if(this.columnSort){
25534             this.colSorter = new Ext.list.Sorter(this.columnSort);
25535             this.colSorter.init(this);
25536         }
25537         if(!this.internalTpl){
25538             this.internalTpl = new Ext.XTemplate(
25539                 '<div class="x-list-header"><div class="x-list-header-inner">',
25540                     '<tpl for="columns">',
25541                     '<div style="width:{[values.width*100]}%;text-align:{align};"><em unselectable="on" id="',this.id, '-xlhd-{#}">',
25542                         '{header}',
25543                     '</em></div>',
25544                     '</tpl>',
25545                     '<div class="x-clear"></div>',
25546                 '</div></div>',
25547                 '<div class="x-list-body"><div class="x-list-body-inner">',
25548                 '</div></div>'
25549             );
25550         }
25551         if(!this.tpl){
25552             this.tpl = new Ext.XTemplate(
25553                 '<tpl for="rows">',
25554                     '<dl>',
25555                         '<tpl for="parent.columns">',
25556                         '<dt style="width:{[values.width*100]}%;text-align:{align};">',
25557                         '<em unselectable="on"<tpl if="cls"> class="{cls}</tpl>">',
25558                             '{[values.tpl.apply(parent)]}',
25559                         '</em></dt>',
25560                         '</tpl>',
25561                         '<div class="x-clear"></div>',
25562                     '</dl>',
25563                 '</tpl>'
25564             );
25565         };
25566         
25567         var cs = this.columns, 
25568             allocatedWidth = 0, 
25569             colsWithWidth = 0, 
25570             len = cs.length, 
25571             columns = [];
25572             
25573         for(var i = 0; i < len; i++){
25574             var c = cs[i];
25575             if(!c.isColumn) {
25576                 c.xtype = c.xtype ? (/^lv/.test(c.xtype) ? c.xtype : 'lv' + c.xtype) : 'lvcolumn';
25577                 c = Ext.create(c);
25578             }
25579             if(c.width) {
25580                 allocatedWidth += c.width*100;
25581                 colsWithWidth++;
25582             }
25583             columns.push(c);
25584         }
25585         
25586         cs = this.columns = columns;
25587         
25588         
25589         if(colsWithWidth < len){
25590             var remaining = len - colsWithWidth;
25591             if(allocatedWidth < this.maxWidth){
25592                 var perCol = ((this.maxWidth-allocatedWidth) / remaining)/100;
25593                 for(var j = 0; j < len; j++){
25594                     var c = cs[j];
25595                     if(!c.width){
25596                         c.width = perCol;
25597                     }
25598                 }
25599             }
25600         }
25601         Ext.list.ListView.superclass.initComponent.call(this);
25602     },
25603
25604     onRender : function(){
25605         this.autoEl = {
25606             cls: 'x-list-wrap'  
25607         };
25608         Ext.list.ListView.superclass.onRender.apply(this, arguments);
25609
25610         this.internalTpl.overwrite(this.el, {columns: this.columns});
25611         
25612         this.innerBody = Ext.get(this.el.dom.childNodes[1].firstChild);
25613         this.innerHd = Ext.get(this.el.dom.firstChild.firstChild);
25614
25615         if(this.hideHeaders){
25616             this.el.dom.firstChild.style.display = 'none';
25617         }
25618     },
25619
25620     getTemplateTarget : function(){
25621         return this.innerBody;
25622     },
25623
25624     
25625     collectData : function(){
25626         var rs = Ext.list.ListView.superclass.collectData.apply(this, arguments);
25627         return {
25628             columns: this.columns,
25629             rows: rs
25630         }
25631     },
25632
25633     verifyInternalSize : function(){
25634         if(this.lastSize){
25635             this.onResize(this.lastSize.width, this.lastSize.height);
25636         }
25637     },
25638
25639     
25640     onResize : function(w, h){
25641         var bd = this.innerBody.dom;
25642         var hd = this.innerHd.dom
25643         if(!bd){
25644             return;
25645         }
25646         var bdp = bd.parentNode;
25647         if(Ext.isNumber(w)){
25648             var sw = w - Ext.num(this.scrollOffset, Ext.getScrollBarWidth());
25649             if(this.reserveScrollOffset || ((bdp.offsetWidth - bdp.clientWidth) > 10)){
25650                 bd.style.width = sw + 'px';
25651                 hd.style.width = sw + 'px';
25652             }else{
25653                 bd.style.width = w + 'px';
25654                 hd.style.width = w + 'px';
25655                 setTimeout(function(){
25656                     if((bdp.offsetWidth - bdp.clientWidth) > 10){
25657                         bd.style.width = sw + 'px';
25658                         hd.style.width = sw + 'px';
25659                     }
25660                 }, 10);
25661             }
25662         }
25663         if(Ext.isNumber(h)){
25664             bdp.style.height = (h - hd.parentNode.offsetHeight) + 'px';
25665         }
25666     },
25667
25668     updateIndexes : function(){
25669         Ext.list.ListView.superclass.updateIndexes.apply(this, arguments);
25670         this.verifyInternalSize();
25671     },
25672
25673     findHeaderIndex : function(hd){
25674         hd = hd.dom || hd;
25675         var pn = hd.parentNode, cs = pn.parentNode.childNodes;
25676         for(var i = 0, c; c = cs[i]; i++){
25677             if(c == pn){
25678                 return i;
25679             }
25680         }
25681         return -1;
25682     },
25683
25684     setHdWidths : function(){
25685         var els = this.innerHd.dom.getElementsByTagName('div');
25686         for(var i = 0, cs = this.columns, len = cs.length; i < len; i++){
25687             els[i].style.width = (cs[i].width*100) + '%';
25688         }
25689     }
25690 });
25691
25692 Ext.reg('listview', Ext.list.ListView);
25693
25694
25695 Ext.ListView = Ext.list.ListView;
25696 Ext.list.Column = Ext.extend(Object, {
25697     
25698     isColumn: true,
25699     
25700             
25701     align: 'left',
25702         
25703     header: '',
25704     
25705         
25706     width: null,
25707
25708     
25709     cls: '',
25710     
25711     
25712
25713     
25714     
25715     constructor : function(c){
25716         if(!c.tpl){
25717             c.tpl = new Ext.XTemplate('{' + c.dataIndex + '}');
25718         }
25719         else if(Ext.isString(c.tpl)){
25720             c.tpl = new Ext.XTemplate(c.tpl);
25721         }
25722         
25723         Ext.apply(this, c);
25724     }
25725 });
25726
25727 Ext.reg('lvcolumn', Ext.list.Column);
25728
25729
25730 Ext.list.NumberColumn = Ext.extend(Ext.list.Column, {
25731         
25732     format: '0,000.00',
25733     
25734     constructor : function(c) {
25735         c.tpl = c.tpl || new Ext.XTemplate('{' + c.dataIndex + ':number("' + (c.format || this.format) + '")}');       
25736         Ext.list.NumberColumn.superclass.constructor.call(this, c);
25737     }
25738 });
25739
25740 Ext.reg('lvnumbercolumn', Ext.list.NumberColumn);
25741
25742
25743 Ext.list.DateColumn = Ext.extend(Ext.list.Column, {
25744     format: 'm/d/Y',
25745     constructor : function(c) {
25746         c.tpl = c.tpl || new Ext.XTemplate('{' + c.dataIndex + ':date("' + (c.format || this.format) + '")}');      
25747         Ext.list.DateColumn.superclass.constructor.call(this, c);
25748     }
25749 });
25750 Ext.reg('lvdatecolumn', Ext.list.DateColumn);
25751
25752
25753 Ext.list.BooleanColumn = Ext.extend(Ext.list.Column, {
25754     
25755     trueText: 'true',
25756     
25757     falseText: 'false',
25758     
25759     undefinedText: '&#160;',
25760     
25761     constructor : function(c) {
25762         c.tpl = c.tpl || new Ext.XTemplate('{' + c.dataIndex + ':this.format}');
25763         
25764         var t = this.trueText, f = this.falseText, u = this.undefinedText;
25765         c.tpl.format = function(v){
25766             if(v === undefined){
25767                 return u;
25768             }
25769             if(!v || v === 'false'){
25770                 return f;
25771             }
25772             return t;
25773         };
25774         
25775         Ext.list.DateColumn.superclass.constructor.call(this, c);
25776     }
25777 });
25778
25779 Ext.reg('lvbooleancolumn', Ext.list.BooleanColumn);
25780 Ext.list.ColumnResizer = Ext.extend(Ext.util.Observable, {
25781     
25782     minPct: .05,
25783
25784     constructor: function(config){
25785         Ext.apply(this, config);
25786         Ext.list.ColumnResizer.superclass.constructor.call(this);
25787     },
25788     init : function(listView){
25789         this.view = listView;
25790         listView.on('render', this.initEvents, this);
25791     },
25792
25793     initEvents : function(view){
25794         view.mon(view.innerHd, 'mousemove', this.handleHdMove, this);
25795         this.tracker = new Ext.dd.DragTracker({
25796             onBeforeStart: this.onBeforeStart.createDelegate(this),
25797             onStart: this.onStart.createDelegate(this),
25798             onDrag: this.onDrag.createDelegate(this),
25799             onEnd: this.onEnd.createDelegate(this),
25800             tolerance: 3,
25801             autoStart: 300
25802         });
25803         this.tracker.initEl(view.innerHd);
25804         view.on('beforedestroy', this.tracker.destroy, this.tracker);
25805     },
25806
25807     handleHdMove : function(e, t){
25808         var hw = 5,
25809             x = e.getPageX(),
25810             hd = e.getTarget('em', 3, true);
25811         if(hd){
25812             var r = hd.getRegion(),
25813                 ss = hd.dom.style,
25814                 pn = hd.dom.parentNode;
25815
25816             if(x - r.left <= hw && pn != pn.parentNode.firstChild){
25817                 this.activeHd = Ext.get(pn.previousSibling.firstChild);
25818                 ss.cursor = Ext.isWebKit ? 'e-resize' : 'col-resize';
25819             } else if(r.right - x <= hw && pn != pn.parentNode.lastChild.previousSibling){
25820                 this.activeHd = hd;
25821                 ss.cursor = Ext.isWebKit ? 'w-resize' : 'col-resize';
25822             } else{
25823                 delete this.activeHd;
25824                 ss.cursor = '';
25825             }
25826         }
25827     },
25828
25829     onBeforeStart : function(e){
25830         this.dragHd = this.activeHd;
25831         return !!this.dragHd;
25832     },
25833
25834     onStart: function(e){
25835         this.view.disableHeaders = true;
25836         this.proxy = this.view.el.createChild({cls:'x-list-resizer'});
25837         this.proxy.setHeight(this.view.el.getHeight());
25838
25839         var x = this.tracker.getXY()[0],
25840             w = this.view.innerHd.getWidth();
25841
25842         this.hdX = this.dragHd.getX();
25843         this.hdIndex = this.view.findHeaderIndex(this.dragHd);
25844
25845         this.proxy.setX(this.hdX);
25846         this.proxy.setWidth(x-this.hdX);
25847
25848         this.minWidth = w*this.minPct;
25849         this.maxWidth = w - (this.minWidth*(this.view.columns.length-1-this.hdIndex));
25850     },
25851
25852     onDrag: function(e){
25853         var cursorX = this.tracker.getXY()[0];
25854         this.proxy.setWidth((cursorX-this.hdX).constrain(this.minWidth, this.maxWidth));
25855     },
25856
25857     onEnd: function(e){
25858         
25859         var nw = this.proxy.getWidth();
25860         this.proxy.remove();
25861
25862         var index = this.hdIndex,
25863             vw = this.view,
25864             cs = vw.columns,
25865             len = cs.length,
25866             w = this.view.innerHd.getWidth(),
25867             minPct = this.minPct * 100,
25868             pct = Math.ceil((nw * vw.maxWidth) / w),
25869             diff = (cs[index].width * 100) - pct,
25870             each = Math.floor(diff / (len-1-index)),
25871             mod = diff - (each * (len-1-index));
25872
25873         for(var i = index+1; i < len; i++){
25874             var cw = (cs[i].width * 100) + each,
25875                 ncw = Math.max(minPct, cw);
25876             if(cw != ncw){
25877                 mod += cw - ncw;
25878             }
25879             cs[i].width = ncw / 100;
25880         }
25881         cs[index].width = pct / 100;
25882         cs[index+1].width += (mod / 100);
25883         delete this.dragHd;
25884         vw.setHdWidths();
25885         vw.refresh();
25886         setTimeout(function(){
25887             vw.disableHeaders = false;
25888         }, 100);
25889     }
25890 });
25891
25892
25893 Ext.ListView.ColumnResizer = Ext.list.ColumnResizer;
25894 Ext.list.Sorter = Ext.extend(Ext.util.Observable, {
25895     
25896     sortClasses : ["sort-asc", "sort-desc"],
25897
25898     constructor: function(config){
25899         Ext.apply(this, config);
25900         Ext.list.Sorter.superclass.constructor.call(this);
25901     },
25902
25903     init : function(listView){
25904         this.view = listView;
25905         listView.on('render', this.initEvents, this);
25906     },
25907
25908     initEvents : function(view){
25909         view.mon(view.innerHd, 'click', this.onHdClick, this);
25910         view.innerHd.setStyle('cursor', 'pointer');
25911         view.mon(view.store, 'datachanged', this.updateSortState, this);
25912         this.updateSortState.defer(10, this, [view.store]);
25913     },
25914
25915     updateSortState : function(store){
25916         var state = store.getSortState();
25917         if(!state){
25918             return;
25919         }
25920         this.sortState = state;
25921         var cs = this.view.columns, sortColumn = -1;
25922         for(var i = 0, len = cs.length; i < len; i++){
25923             if(cs[i].dataIndex == state.field){
25924                 sortColumn = i;
25925                 break;
25926             }
25927         }
25928         if(sortColumn != -1){
25929             var sortDir = state.direction;
25930             this.updateSortIcon(sortColumn, sortDir);
25931         }
25932     },
25933
25934     updateSortIcon : function(col, dir){
25935         var sc = this.sortClasses;
25936         var hds = this.view.innerHd.select('em').removeClass(sc);
25937         hds.item(col).addClass(sc[dir == "DESC" ? 1 : 0]);
25938     },
25939
25940     onHdClick : function(e){
25941         var hd = e.getTarget('em', 3);
25942         if(hd && !this.view.disableHeaders){
25943             var index = this.view.findHeaderIndex(hd);
25944             this.view.store.sort(this.view.columns[index].dataIndex);
25945         }
25946     }
25947 });
25948
25949
25950 Ext.ListView.Sorter = Ext.list.Sorter;
25951 Ext.TabPanel = Ext.extend(Ext.Panel,  {
25952     
25953     
25954     
25955     monitorResize : true,
25956     
25957     deferredRender : true,
25958     
25959     tabWidth : 120,
25960     
25961     minTabWidth : 30,
25962     
25963     resizeTabs : false,
25964     
25965     enableTabScroll : false,
25966     
25967     scrollIncrement : 0,
25968     
25969     scrollRepeatInterval : 400,
25970     
25971     scrollDuration : 0.35,
25972     
25973     animScroll : true,
25974     
25975     tabPosition : 'top',
25976     
25977     baseCls : 'x-tab-panel',
25978     
25979     autoTabs : false,
25980     
25981     autoTabSelector : 'div.x-tab',
25982     
25983     activeTab : undefined,
25984     
25985     tabMargin : 2,
25986     
25987     plain : false,
25988     
25989     wheelIncrement : 20,
25990
25991     
25992     idDelimiter : '__',
25993
25994     
25995     itemCls : 'x-tab-item',
25996
25997     
25998     elements : 'body',
25999     headerAsText : false,
26000     frame : false,
26001     hideBorders :true,
26002
26003     
26004     initComponent : function(){
26005         this.frame = false;
26006         Ext.TabPanel.superclass.initComponent.call(this);
26007         this.addEvents(
26008             
26009             'beforetabchange',
26010             
26011             'tabchange',
26012             
26013             'contextmenu'
26014         );
26015         
26016         this.setLayout(new Ext.layout.CardLayout(Ext.apply({
26017             layoutOnCardChange: this.layoutOnTabChange,
26018             deferredRender: this.deferredRender
26019         }, this.layoutConfig)));
26020
26021         if(this.tabPosition == 'top'){
26022             this.elements += ',header';
26023             this.stripTarget = 'header';
26024         }else {
26025             this.elements += ',footer';
26026             this.stripTarget = 'footer';
26027         }
26028         if(!this.stack){
26029             this.stack = Ext.TabPanel.AccessStack();
26030         }
26031         this.initItems();
26032     },
26033
26034     
26035     onRender : function(ct, position){
26036         Ext.TabPanel.superclass.onRender.call(this, ct, position);
26037
26038         if(this.plain){
26039             var pos = this.tabPosition == 'top' ? 'header' : 'footer';
26040             this[pos].addClass('x-tab-panel-'+pos+'-plain');
26041         }
26042
26043         var st = this[this.stripTarget];
26044
26045         this.stripWrap = st.createChild({cls:'x-tab-strip-wrap', cn:{
26046             tag:'ul', cls:'x-tab-strip x-tab-strip-'+this.tabPosition}});
26047
26048         var beforeEl = (this.tabPosition=='bottom' ? this.stripWrap : null);
26049         st.createChild({cls:'x-tab-strip-spacer'}, beforeEl);
26050         this.strip = new Ext.Element(this.stripWrap.dom.firstChild);
26051
26052         
26053         this.edge = this.strip.createChild({tag:'li', cls:'x-tab-edge', cn: [{tag: 'span', cls: 'x-tab-strip-text', cn: '&#160;'}]});
26054         this.strip.createChild({cls:'x-clear'});
26055
26056         this.body.addClass('x-tab-panel-body-'+this.tabPosition);
26057
26058         
26059         if(!this.itemTpl){
26060             var tt = new Ext.Template(
26061                  '<li class="{cls}" id="{id}"><a class="x-tab-strip-close"></a>',
26062                  '<a class="x-tab-right" href="#"><em class="x-tab-left">',
26063                  '<span class="x-tab-strip-inner"><span class="x-tab-strip-text {iconCls}">{text}</span></span>',
26064                  '</em></a></li>'
26065             );
26066             tt.disableFormats = true;
26067             tt.compile();
26068             Ext.TabPanel.prototype.itemTpl = tt;
26069         }
26070
26071         this.items.each(this.initTab, this);
26072     },
26073
26074     
26075     afterRender : function(){
26076         Ext.TabPanel.superclass.afterRender.call(this);
26077         if(this.autoTabs){
26078             this.readTabs(false);
26079         }
26080         if(this.activeTab !== undefined){
26081             var item = Ext.isObject(this.activeTab) ? this.activeTab : this.items.get(this.activeTab);
26082             delete this.activeTab;
26083             this.setActiveTab(item);
26084         }
26085     },
26086
26087     
26088     initEvents : function(){
26089         Ext.TabPanel.superclass.initEvents.call(this);
26090         this.mon(this.strip, {
26091             scope: this,
26092             mousedown: this.onStripMouseDown,
26093             contextmenu: this.onStripContextMenu
26094         });
26095         if(this.enableTabScroll){
26096             this.mon(this.strip, 'mousewheel', this.onWheel, this);
26097         }
26098     },
26099
26100     
26101     findTargets : function(e){
26102         var item = null;
26103         var itemEl = e.getTarget('li', this.strip);
26104         if(itemEl){
26105             item = this.getComponent(itemEl.id.split(this.idDelimiter)[1]);
26106             if(item.disabled){
26107                 return {
26108                     close : null,
26109                     item : null,
26110                     el : null
26111                 };
26112             }
26113         }
26114         return {
26115             close : e.getTarget('.x-tab-strip-close', this.strip),
26116             item : item,
26117             el : itemEl
26118         };
26119     },
26120
26121     
26122     onStripMouseDown : function(e){
26123         if(e.button !== 0){
26124             return;
26125         }
26126         e.preventDefault();
26127         var t = this.findTargets(e);
26128         if(t.close){
26129             if (t.item.fireEvent('beforeclose', t.item) !== false) {
26130                 t.item.fireEvent('close', t.item);
26131                 this.remove(t.item);
26132             }
26133             return;
26134         }
26135         if(t.item && t.item != this.activeTab){
26136             this.setActiveTab(t.item);
26137         }
26138     },
26139
26140     
26141     onStripContextMenu : function(e){
26142         e.preventDefault();
26143         var t = this.findTargets(e);
26144         if(t.item){
26145             this.fireEvent('contextmenu', this, t.item, e);
26146         }
26147     },
26148
26149     
26150     readTabs : function(removeExisting){
26151         if(removeExisting === true){
26152             this.items.each(function(item){
26153                 this.remove(item);
26154             }, this);
26155         }
26156         var tabs = this.el.query(this.autoTabSelector);
26157         for(var i = 0, len = tabs.length; i < len; i++){
26158             var tab = tabs[i],
26159                 title = tab.getAttribute('title');
26160             tab.removeAttribute('title');
26161             this.add({
26162                 title: title,
26163                 contentEl: tab
26164             });
26165         }
26166     },
26167
26168     
26169     initTab : function(item, index){
26170         var before = this.strip.dom.childNodes[index],
26171             p = this.getTemplateArgs(item),
26172             el = before ?
26173                  this.itemTpl.insertBefore(before, p) :
26174                  this.itemTpl.append(this.strip, p),
26175             cls = 'x-tab-strip-over',
26176             tabEl = Ext.get(el);
26177
26178         tabEl.hover(function(){
26179             if(!item.disabled){
26180                 tabEl.addClass(cls);
26181             }
26182         }, function(){
26183             tabEl.removeClass(cls);
26184         });
26185
26186         if(item.tabTip){
26187             tabEl.child('span.x-tab-strip-text', true).qtip = item.tabTip;
26188         }
26189         item.tabEl = el;
26190
26191         
26192         tabEl.select('a').on('click', function(e){
26193             if(!e.getPageX()){
26194                 this.onStripMouseDown(e);
26195             }
26196         }, this, {preventDefault: true});
26197
26198         item.on({
26199             scope: this,
26200             disable: this.onItemDisabled,
26201             enable: this.onItemEnabled,
26202             titlechange: this.onItemTitleChanged,
26203             iconchange: this.onItemIconChanged,
26204             beforeshow: this.onBeforeShowItem
26205         });
26206     },
26207     
26208     
26209
26210     
26211     getTemplateArgs : function(item) {
26212         var cls = item.closable ? 'x-tab-strip-closable' : '';
26213         if(item.disabled){
26214             cls += ' x-item-disabled';
26215         }
26216         if(item.iconCls){
26217             cls += ' x-tab-with-icon';
26218         }
26219         if(item.tabCls){
26220             cls += ' ' + item.tabCls;
26221         }
26222
26223         return {
26224             id: this.id + this.idDelimiter + item.getItemId(),
26225             text: item.title,
26226             cls: cls,
26227             iconCls: item.iconCls || ''
26228         };
26229     },
26230
26231     
26232     onAdd : function(c){
26233         Ext.TabPanel.superclass.onAdd.call(this, c);
26234         if(this.rendered){
26235             var items = this.items;
26236             this.initTab(c, items.indexOf(c));
26237             if(items.getCount() == 1){
26238                 this.syncSize();
26239             }
26240             this.delegateUpdates();
26241         }
26242     },
26243
26244     
26245     onBeforeAdd : function(item){
26246         var existing = item.events ? (this.items.containsKey(item.getItemId()) ? item : null) : this.items.get(item);
26247         if(existing){
26248             this.setActiveTab(item);
26249             return false;
26250         }
26251         Ext.TabPanel.superclass.onBeforeAdd.apply(this, arguments);
26252         var es = item.elements;
26253         item.elements = es ? es.replace(',header', '') : es;
26254         item.border = (item.border === true);
26255     },
26256
26257     
26258     onRemove : function(c){
26259         var te = Ext.get(c.tabEl);
26260         
26261         if(te){
26262             te.select('a').removeAllListeners();
26263             Ext.destroy(te);
26264         }
26265         Ext.TabPanel.superclass.onRemove.call(this, c);
26266         this.stack.remove(c);
26267         delete c.tabEl;
26268         c.un('disable', this.onItemDisabled, this);
26269         c.un('enable', this.onItemEnabled, this);
26270         c.un('titlechange', this.onItemTitleChanged, this);
26271         c.un('iconchange', this.onItemIconChanged, this);
26272         c.un('beforeshow', this.onBeforeShowItem, this);
26273         if(c == this.activeTab){
26274             var next = this.stack.next();
26275             if(next){
26276                 this.setActiveTab(next);
26277             }else if(this.items.getCount() > 0){
26278                 this.setActiveTab(0);
26279             }else{
26280                 this.setActiveTab(null);
26281             }
26282         }
26283         if(!this.destroying){
26284             this.delegateUpdates();
26285         }
26286     },
26287
26288     
26289     onBeforeShowItem : function(item){
26290         if(item != this.activeTab){
26291             this.setActiveTab(item);
26292             return false;
26293         }
26294     },
26295
26296     
26297     onItemDisabled : function(item){
26298         var el = this.getTabEl(item);
26299         if(el){
26300             Ext.fly(el).addClass('x-item-disabled');
26301         }
26302         this.stack.remove(item);
26303     },
26304
26305     
26306     onItemEnabled : function(item){
26307         var el = this.getTabEl(item);
26308         if(el){
26309             Ext.fly(el).removeClass('x-item-disabled');
26310         }
26311     },
26312
26313     
26314     onItemTitleChanged : function(item){
26315         var el = this.getTabEl(item);
26316         if(el){
26317             Ext.fly(el).child('span.x-tab-strip-text', true).innerHTML = item.title;
26318         }
26319     },
26320
26321     
26322     onItemIconChanged : function(item, iconCls, oldCls){
26323         var el = this.getTabEl(item);
26324         if(el){
26325             el = Ext.get(el);
26326             el.child('span.x-tab-strip-text').replaceClass(oldCls, iconCls);
26327             el[Ext.isEmpty(iconCls) ? 'removeClass' : 'addClass']('x-tab-with-icon');
26328         }
26329     },
26330
26331     
26332     getTabEl : function(item){
26333         var c = this.getComponent(item);
26334         return c ? c.tabEl : null;
26335     },
26336
26337     
26338     onResize : function(){
26339         Ext.TabPanel.superclass.onResize.apply(this, arguments);
26340         this.delegateUpdates();
26341     },
26342
26343     
26344     beginUpdate : function(){
26345         this.suspendUpdates = true;
26346     },
26347
26348     
26349     endUpdate : function(){
26350         this.suspendUpdates = false;
26351         this.delegateUpdates();
26352     },
26353
26354     
26355     hideTabStripItem : function(item){
26356         item = this.getComponent(item);
26357         var el = this.getTabEl(item);
26358         if(el){
26359             el.style.display = 'none';
26360             this.delegateUpdates();
26361         }
26362         this.stack.remove(item);
26363     },
26364
26365     
26366     unhideTabStripItem : function(item){
26367         item = this.getComponent(item);
26368         var el = this.getTabEl(item);
26369         if(el){
26370             el.style.display = '';
26371             this.delegateUpdates();
26372         }
26373     },
26374
26375     
26376     delegateUpdates : function(){
26377         if(this.suspendUpdates){
26378             return;
26379         }
26380         if(this.resizeTabs && this.rendered){
26381             this.autoSizeTabs();
26382         }
26383         if(this.enableTabScroll && this.rendered){
26384             this.autoScrollTabs();
26385         }
26386     },
26387
26388     
26389     autoSizeTabs : function(){
26390         var count = this.items.length,
26391             ce = this.tabPosition != 'bottom' ? 'header' : 'footer',
26392             ow = this[ce].dom.offsetWidth,
26393             aw = this[ce].dom.clientWidth;
26394
26395         if(!this.resizeTabs || count < 1 || !aw){ 
26396             return;
26397         }
26398
26399         var each = Math.max(Math.min(Math.floor((aw-4) / count) - this.tabMargin, this.tabWidth), this.minTabWidth); 
26400         this.lastTabWidth = each;
26401         var lis = this.strip.query("li:not([className^=x-tab-edge])");
26402         for(var i = 0, len = lis.length; i < len; i++) {
26403             var li = lis[i],
26404                 inner = Ext.fly(li).child('.x-tab-strip-inner', true),
26405                 tw = li.offsetWidth,
26406                 iw = inner.offsetWidth;
26407             inner.style.width = (each - (tw-iw)) + 'px';
26408         }
26409     },
26410
26411     
26412     adjustBodyWidth : function(w){
26413         if(this.header){
26414             this.header.setWidth(w);
26415         }
26416         if(this.footer){
26417             this.footer.setWidth(w);
26418         }
26419         return w;
26420     },
26421
26422     
26423     setActiveTab : function(item){
26424         item = this.getComponent(item);
26425         if(this.fireEvent('beforetabchange', this, item, this.activeTab) === false){
26426             return;
26427         }
26428         if(!this.rendered){
26429             this.activeTab = item;
26430             return;
26431         }
26432         if(this.activeTab != item){
26433             if(this.activeTab){
26434                 var oldEl = this.getTabEl(this.activeTab);
26435                 if(oldEl){
26436                     Ext.fly(oldEl).removeClass('x-tab-strip-active');
26437                 }
26438             }
26439             if(item){
26440                 var el = this.getTabEl(item);
26441                 Ext.fly(el).addClass('x-tab-strip-active');
26442                 this.activeTab = item;
26443                 this.stack.add(item);
26444
26445                 this.layout.setActiveItem(item);
26446                 if(this.scrolling){
26447                     this.scrollToTab(item, this.animScroll);
26448                 }
26449             }
26450             this.fireEvent('tabchange', this, item);
26451         }
26452     },
26453
26454     
26455     getActiveTab : function(){
26456         return this.activeTab || null;
26457     },
26458
26459     
26460     getItem : function(item){
26461         return this.getComponent(item);
26462     },
26463
26464     
26465     autoScrollTabs : function(){
26466         this.pos = this.tabPosition=='bottom' ? this.footer : this.header;
26467         var count = this.items.length,
26468             ow = this.pos.dom.offsetWidth,
26469             tw = this.pos.dom.clientWidth,
26470             wrap = this.stripWrap,
26471             wd = wrap.dom,
26472             cw = wd.offsetWidth,
26473             pos = this.getScrollPos(),
26474             l = this.edge.getOffsetsTo(this.stripWrap)[0] + pos;
26475
26476         if(!this.enableTabScroll || count < 1 || cw < 20){ 
26477             return;
26478         }
26479         if(l <= tw){
26480             wd.scrollLeft = 0;
26481             wrap.setWidth(tw);
26482             if(this.scrolling){
26483                 this.scrolling = false;
26484                 this.pos.removeClass('x-tab-scrolling');
26485                 this.scrollLeft.hide();
26486                 this.scrollRight.hide();
26487                 
26488                 if(Ext.isAir || Ext.isWebKit){
26489                     wd.style.marginLeft = '';
26490                     wd.style.marginRight = '';
26491                 }
26492             }
26493         }else{
26494             if(!this.scrolling){
26495                 this.pos.addClass('x-tab-scrolling');
26496                 
26497                 if(Ext.isAir || Ext.isWebKit){
26498                     wd.style.marginLeft = '18px';
26499                     wd.style.marginRight = '18px';
26500                 }
26501             }
26502             tw -= wrap.getMargins('lr');
26503             wrap.setWidth(tw > 20 ? tw : 20);
26504             if(!this.scrolling){
26505                 if(!this.scrollLeft){
26506                     this.createScrollers();
26507                 }else{
26508                     this.scrollLeft.show();
26509                     this.scrollRight.show();
26510                 }
26511             }
26512             this.scrolling = true;
26513             if(pos > (l-tw)){ 
26514                 wd.scrollLeft = l-tw;
26515             }else{ 
26516                 this.scrollToTab(this.activeTab, false);
26517             }
26518             this.updateScrollButtons();
26519         }
26520     },
26521
26522     
26523     createScrollers : function(){
26524         this.pos.addClass('x-tab-scrolling-' + this.tabPosition);
26525         var h = this.stripWrap.dom.offsetHeight;
26526
26527         
26528         var sl = this.pos.insertFirst({
26529             cls:'x-tab-scroller-left'
26530         });
26531         sl.setHeight(h);
26532         sl.addClassOnOver('x-tab-scroller-left-over');
26533         this.leftRepeater = new Ext.util.ClickRepeater(sl, {
26534             interval : this.scrollRepeatInterval,
26535             handler: this.onScrollLeft,
26536             scope: this
26537         });
26538         this.scrollLeft = sl;
26539
26540         
26541         var sr = this.pos.insertFirst({
26542             cls:'x-tab-scroller-right'
26543         });
26544         sr.setHeight(h);
26545         sr.addClassOnOver('x-tab-scroller-right-over');
26546         this.rightRepeater = new Ext.util.ClickRepeater(sr, {
26547             interval : this.scrollRepeatInterval,
26548             handler: this.onScrollRight,
26549             scope: this
26550         });
26551         this.scrollRight = sr;
26552     },
26553
26554     
26555     getScrollWidth : function(){
26556         return this.edge.getOffsetsTo(this.stripWrap)[0] + this.getScrollPos();
26557     },
26558
26559     
26560     getScrollPos : function(){
26561         return parseInt(this.stripWrap.dom.scrollLeft, 10) || 0;
26562     },
26563
26564     
26565     getScrollArea : function(){
26566         return parseInt(this.stripWrap.dom.clientWidth, 10) || 0;
26567     },
26568
26569     
26570     getScrollAnim : function(){
26571         return {duration:this.scrollDuration, callback: this.updateScrollButtons, scope: this};
26572     },
26573
26574     
26575     getScrollIncrement : function(){
26576         return this.scrollIncrement || (this.resizeTabs ? this.lastTabWidth+2 : 100);
26577     },
26578
26579     
26580
26581     scrollToTab : function(item, animate){
26582         if(!item){ 
26583             return; 
26584         }
26585         var el = this.getTabEl(item),
26586             pos = this.getScrollPos(), 
26587             area = this.getScrollArea(),
26588             left = Ext.fly(el).getOffsetsTo(this.stripWrap)[0] + pos,
26589             right = left + el.offsetWidth;
26590         if(left < pos){
26591             this.scrollTo(left, animate);
26592         }else if(right > (pos + area)){
26593             this.scrollTo(right - area, animate);
26594         }
26595     },
26596
26597     
26598     scrollTo : function(pos, animate){
26599         this.stripWrap.scrollTo('left', pos, animate ? this.getScrollAnim() : false);
26600         if(!animate){
26601             this.updateScrollButtons();
26602         }
26603     },
26604
26605     onWheel : function(e){
26606         var d = e.getWheelDelta()*this.wheelIncrement*-1;
26607         e.stopEvent();
26608
26609         var pos = this.getScrollPos(),
26610             newpos = pos + d,
26611             sw = this.getScrollWidth()-this.getScrollArea();
26612
26613         var s = Math.max(0, Math.min(sw, newpos));
26614         if(s != pos){
26615             this.scrollTo(s, false);
26616         }
26617     },
26618
26619     
26620     onScrollRight : function(){
26621         var sw = this.getScrollWidth()-this.getScrollArea(),
26622             pos = this.getScrollPos(),
26623             s = Math.min(sw, pos + this.getScrollIncrement());
26624         if(s != pos){
26625             this.scrollTo(s, this.animScroll);
26626         }
26627     },
26628
26629     
26630     onScrollLeft : function(){
26631         var pos = this.getScrollPos(),
26632             s = Math.max(0, pos - this.getScrollIncrement());
26633         if(s != pos){
26634             this.scrollTo(s, this.animScroll);
26635         }
26636     },
26637
26638     
26639     updateScrollButtons : function(){
26640         var pos = this.getScrollPos();
26641         this.scrollLeft[pos === 0 ? 'addClass' : 'removeClass']('x-tab-scroller-left-disabled');
26642         this.scrollRight[pos >= (this.getScrollWidth()-this.getScrollArea()) ? 'addClass' : 'removeClass']('x-tab-scroller-right-disabled');
26643     },
26644
26645     
26646     beforeDestroy : function() {
26647         Ext.destroy(this.leftRepeater, this.rightRepeater);
26648         this.deleteMembers('strip', 'edge', 'scrollLeft', 'scrollRight', 'stripWrap');
26649         this.activeTab = null;
26650         Ext.TabPanel.superclass.beforeDestroy.apply(this);
26651     }
26652
26653     
26654     
26655     
26656     
26657     
26658     
26659     
26660     
26661     
26662     
26663     
26664     
26665 });
26666 Ext.reg('tabpanel', Ext.TabPanel);
26667
26668
26669 Ext.TabPanel.prototype.activate = Ext.TabPanel.prototype.setActiveTab;
26670
26671
26672 Ext.TabPanel.AccessStack = function(){
26673     var items = [];
26674     return {
26675         add : function(item){
26676             items.push(item);
26677             if(items.length > 10){
26678                 items.shift();
26679             }
26680         },
26681
26682         remove : function(item){
26683             var s = [];
26684             for(var i = 0, len = items.length; i < len; i++) {
26685                 if(items[i] != item){
26686                     s.push(items[i]);
26687                 }
26688             }
26689             items = s;
26690         },
26691
26692         next : function(){
26693             return items.pop();
26694         }
26695     };
26696 };
26697
26698 Ext.Button = Ext.extend(Ext.BoxComponent, {
26699     
26700     hidden : false,
26701     
26702     disabled : false,
26703     
26704     pressed : false,
26705
26706     
26707
26708     
26709
26710     
26711     enableToggle : false,
26712     
26713     
26714     
26715     menuAlign : 'tl-bl?',
26716
26717     
26718     
26719     
26720     type : 'button',
26721
26722     
26723     menuClassTarget : 'tr:nth(2)',
26724
26725     
26726     clickEvent : 'click',
26727
26728     
26729     handleMouseEvents : true,
26730
26731     
26732     tooltipType : 'qtip',
26733
26734     
26735     buttonSelector : 'button:first-child',
26736
26737     
26738     scale : 'small',
26739
26740     
26741
26742     
26743     iconAlign : 'left',
26744
26745     
26746     arrowAlign : 'right',
26747
26748     
26749     
26750     
26751
26752     initComponent : function(){
26753         Ext.Button.superclass.initComponent.call(this);
26754
26755         this.addEvents(
26756             
26757             'click',
26758             
26759             'toggle',
26760             
26761             'mouseover',
26762             
26763             'mouseout',
26764             
26765             'menushow',
26766             
26767             'menuhide',
26768             
26769             'menutriggerover',
26770             
26771             'menutriggerout'
26772         );
26773         if(this.menu){
26774             this.menu = Ext.menu.MenuMgr.get(this.menu);
26775         }
26776         if(Ext.isString(this.toggleGroup)){
26777             this.enableToggle = true;
26778         }
26779     },
26780
26781
26782     getTemplateArgs : function(){
26783         return [this.type, 'x-btn-' + this.scale + ' x-btn-icon-' + this.scale + '-' + this.iconAlign, this.getMenuClass(), this.cls, this.id];
26784     },
26785
26786     
26787     setButtonClass : function(){
26788         if(this.useSetClass){
26789             if(!Ext.isEmpty(this.oldCls)){
26790                 this.el.removeClass([this.oldCls, 'x-btn-pressed']);
26791             }
26792             this.oldCls = (this.iconCls || this.icon) ? (this.text ? ' x-btn-text-icon' : ' x-btn-icon') : ' x-btn-noicon';
26793             this.el.addClass([this.oldCls, this.pressed ? 'x-btn-pressed' : null]);
26794         }
26795     },
26796
26797     
26798     getMenuClass : function(){
26799         return this.menu ? (this.arrowAlign != 'bottom' ? 'x-btn-arrow' : 'x-btn-arrow-bottom') : '';
26800     },
26801
26802     
26803     onRender : function(ct, position){
26804         if(!this.template){
26805             if(!Ext.Button.buttonTemplate){
26806                 
26807                 Ext.Button.buttonTemplate = new Ext.Template(
26808                     '<table id="{4}" cellspacing="0" class="x-btn {3}"><tbody class="{1}">',
26809                     '<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>',
26810                     '<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>',
26811                     '<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>',
26812                     '</tbody></table>');
26813                 Ext.Button.buttonTemplate.compile();
26814             }
26815             this.template = Ext.Button.buttonTemplate;
26816         }
26817
26818         var btn, targs = this.getTemplateArgs();
26819
26820         if(position){
26821             btn = this.template.insertBefore(position, targs, true);
26822         }else{
26823             btn = this.template.append(ct, targs, true);
26824         }
26825         
26826         this.btnEl = btn.child(this.buttonSelector);
26827         this.mon(this.btnEl, {
26828             scope: this,
26829             focus: this.onFocus,
26830             blur: this.onBlur
26831         });
26832
26833         this.initButtonEl(btn, this.btnEl);
26834
26835         Ext.ButtonToggleMgr.register(this);
26836     },
26837
26838     
26839     initButtonEl : function(btn, btnEl){
26840         this.el = btn;
26841         this.setIcon(this.icon);
26842         this.setText(this.text);
26843         this.setIconClass(this.iconCls);
26844         if(Ext.isDefined(this.tabIndex)){
26845             btnEl.dom.tabIndex = this.tabIndex;
26846         }
26847         if(this.tooltip){
26848             this.setTooltip(this.tooltip, true);
26849         }
26850
26851         if(this.handleMouseEvents){
26852             this.mon(btn, {
26853                 scope: this,
26854                 mouseover: this.onMouseOver,
26855                 mousedown: this.onMouseDown
26856             });
26857
26858             
26859             
26860         }
26861
26862         if(this.menu){
26863             this.mon(this.menu, {
26864                 scope: this,
26865                 show: this.onMenuShow,
26866                 hide: this.onMenuHide
26867             });
26868         }
26869
26870         if(this.repeat){
26871             var repeater = new Ext.util.ClickRepeater(btn, Ext.isObject(this.repeat) ? this.repeat : {});
26872             this.mon(repeater, 'click', this.onClick, this);
26873         }
26874         this.mon(btn, this.clickEvent, this.onClick, this);
26875     },
26876
26877     
26878     afterRender : function(){
26879         Ext.Button.superclass.afterRender.call(this);
26880         this.useSetClass = true;
26881         this.setButtonClass();
26882         this.doc = Ext.getDoc();
26883         this.doAutoWidth();
26884     },
26885
26886     
26887     setIconClass : function(cls){
26888         this.iconCls = cls;
26889         if(this.el){
26890             this.btnEl.dom.className = '';
26891             this.btnEl.addClass(['x-btn-text', cls || '']);
26892             this.setButtonClass();
26893         }
26894         return this;
26895     },
26896
26897     
26898     setTooltip : function(tooltip,  initial){
26899         if(this.rendered){
26900             if(!initial){
26901                 this.clearTip();
26902             }
26903             if(Ext.isObject(tooltip)){
26904                 Ext.QuickTips.register(Ext.apply({
26905                       target: this.btnEl.id
26906                 }, tooltip));
26907                 this.tooltip = tooltip;
26908             }else{
26909                 this.btnEl.dom[this.tooltipType] = tooltip;
26910             }
26911         }else{
26912             this.tooltip = tooltip;
26913         }
26914         return this;
26915     },
26916
26917     
26918     clearTip : function(){
26919         if(Ext.isObject(this.tooltip)){
26920             Ext.QuickTips.unregister(this.btnEl);
26921         }
26922     },
26923
26924     
26925     beforeDestroy : function(){
26926         if(this.rendered){
26927             this.clearTip();
26928         }
26929         if(this.menu && this.menu.autoDestroy) {
26930             Ext.destroy(this.menu);
26931         }
26932         Ext.destroy(this.repeater);
26933     },
26934
26935     
26936     onDestroy : function(){
26937         if(this.rendered){
26938             this.doc.un('mouseover', this.monitorMouseOver, this);
26939             this.doc.un('mouseup', this.onMouseUp, this);
26940             delete this.doc;
26941             delete this.btnEl;
26942             Ext.ButtonToggleMgr.unregister(this);
26943         }
26944     },
26945
26946     
26947     doAutoWidth : function(){
26948         if(this.el && this.text && this.width === undefined){
26949             this.el.setWidth('auto');
26950             if(Ext.isIE7 && Ext.isStrict){
26951                 var ib = this.btnEl;
26952                 if(ib && ib.getWidth() > 20){
26953                     ib.clip();
26954                     ib.setWidth(Ext.util.TextMetrics.measure(ib, this.text).width+ib.getFrameWidth('lr'));
26955                 }
26956             }
26957             if(this.minWidth){
26958                 if(this.el.getWidth() < this.minWidth){
26959                     this.el.setWidth(this.minWidth);
26960                 }
26961             }
26962         }
26963     },
26964
26965     
26966     setHandler : function(handler, scope){
26967         this.handler = handler;
26968         this.scope = scope;
26969         return this;
26970     },
26971
26972     
26973     setText : function(text){
26974         this.text = text;
26975         if(this.el){
26976             this.btnEl.update(text || '&#160;');
26977             this.setButtonClass();
26978         }
26979         this.doAutoWidth();
26980         return this;
26981     },
26982
26983     
26984     setIcon : function(icon){
26985         this.icon = icon;
26986         if(this.el){
26987             this.btnEl.setStyle('background-image', icon ? 'url(' + icon + ')' : '');
26988             this.setButtonClass();
26989         }
26990         return this;
26991     },
26992
26993     
26994     getText : function(){
26995         return this.text;
26996     },
26997
26998     
26999     toggle : function(state, suppressEvent){
27000         state = state === undefined ? !this.pressed : !!state;
27001         if(state != this.pressed){
27002             if(this.rendered){
27003                 this.el[state ? 'addClass' : 'removeClass']('x-btn-pressed');
27004             }
27005             this.pressed = state;
27006             if(!suppressEvent){
27007                 this.fireEvent('toggle', this, state);
27008                 if(this.toggleHandler){
27009                     this.toggleHandler.call(this.scope || this, this, state);
27010                 }
27011             }
27012         }
27013         return this;
27014     },
27015
27016     
27017     focus : function(){
27018         this.btnEl.focus();
27019     },
27020
27021     
27022     onDisable : function(){
27023         this.onDisableChange(true);
27024     },
27025
27026     
27027     onEnable : function(){
27028         this.onDisableChange(false);
27029     },
27030
27031     onDisableChange : function(disabled){
27032         if(this.el){
27033             if(!Ext.isIE6 || !this.text){
27034                 this.el[disabled ? 'addClass' : 'removeClass'](this.disabledClass);
27035             }
27036             this.el.dom.disabled = disabled;
27037         }
27038         this.disabled = disabled;
27039     },
27040
27041     
27042     showMenu : function(){
27043         if(this.rendered && this.menu){
27044             if(this.tooltip){
27045                 Ext.QuickTips.getQuickTip().cancelShow(this.btnEl);
27046             }
27047             this.menu.show(this.el, this.menuAlign);
27048         }
27049         return this;
27050     },
27051
27052     
27053     hideMenu : function(){
27054         if(this.menu){
27055             this.menu.hide();
27056         }
27057         return this;
27058     },
27059
27060     
27061     hasVisibleMenu : function(){
27062         return this.menu && this.menu.isVisible();
27063     },
27064
27065     
27066     onClick : function(e){
27067         if(e){
27068             e.preventDefault();
27069         }
27070         if(e.button !== 0){
27071             return;
27072         }
27073         if(!this.disabled){
27074             if(this.enableToggle && (this.allowDepress !== false || !this.pressed)){
27075                 this.toggle();
27076             }
27077             if(this.menu && !this.menu.isVisible() && !this.ignoreNextClick){
27078                 this.showMenu();
27079             }
27080             this.fireEvent('click', this, e);
27081             if(this.handler){
27082                 
27083                 this.handler.call(this.scope || this, this, e);
27084             }
27085         }
27086     },
27087
27088     
27089     isMenuTriggerOver : function(e, internal){
27090         return this.menu && !internal;
27091     },
27092
27093     
27094     isMenuTriggerOut : function(e, internal){
27095         return this.menu && !internal;
27096     },
27097
27098     
27099     onMouseOver : function(e){
27100         if(!this.disabled){
27101             var internal = e.within(this.el,  true);
27102             if(!internal){
27103                 this.el.addClass('x-btn-over');
27104                 if(!this.monitoringMouseOver){
27105                     this.doc.on('mouseover', this.monitorMouseOver, this);
27106                     this.monitoringMouseOver = true;
27107                 }
27108                 this.fireEvent('mouseover', this, e);
27109             }
27110             if(this.isMenuTriggerOver(e, internal)){
27111                 this.fireEvent('menutriggerover', this, this.menu, e);
27112             }
27113         }
27114     },
27115
27116     
27117     monitorMouseOver : function(e){
27118         if(e.target != this.el.dom && !e.within(this.el)){
27119             if(this.monitoringMouseOver){
27120                 this.doc.un('mouseover', this.monitorMouseOver, this);
27121                 this.monitoringMouseOver = false;
27122             }
27123             this.onMouseOut(e);
27124         }
27125     },
27126
27127     
27128     onMouseOut : function(e){
27129         var internal = e.within(this.el) && e.target != this.el.dom;
27130         this.el.removeClass('x-btn-over');
27131         this.fireEvent('mouseout', this, e);
27132         if(this.isMenuTriggerOut(e, internal)){
27133             this.fireEvent('menutriggerout', this, this.menu, e);
27134         }
27135     },
27136
27137     focus : function() {
27138         this.btnEl.focus();
27139     },
27140
27141     blur : function() {
27142         this.btnEl.blur();
27143     },
27144
27145     
27146     onFocus : function(e){
27147         if(!this.disabled){
27148             this.el.addClass('x-btn-focus');
27149         }
27150     },
27151     
27152     onBlur : function(e){
27153         this.el.removeClass('x-btn-focus');
27154     },
27155
27156     
27157     getClickEl : function(e, isUp){
27158        return this.el;
27159     },
27160
27161     
27162     onMouseDown : function(e){
27163         if(!this.disabled && e.button === 0){
27164             this.getClickEl(e).addClass('x-btn-click');
27165             this.doc.on('mouseup', this.onMouseUp, this);
27166         }
27167     },
27168     
27169     onMouseUp : function(e){
27170         if(e.button === 0){
27171             this.getClickEl(e, true).removeClass('x-btn-click');
27172             this.doc.un('mouseup', this.onMouseUp, this);
27173         }
27174     },
27175     
27176     onMenuShow : function(e){
27177         this.menu.ownerCt = this;
27178         this.ignoreNextClick = 0;
27179         this.el.addClass('x-btn-menu-active');
27180         this.fireEvent('menushow', this, this.menu);
27181     },
27182     
27183     onMenuHide : function(e){
27184         this.el.removeClass('x-btn-menu-active');
27185         this.ignoreNextClick = this.restoreClick.defer(250, this);
27186         this.fireEvent('menuhide', this, this.menu);
27187         delete this.menu.ownerCt;
27188     },
27189
27190     
27191     restoreClick : function(){
27192         this.ignoreNextClick = 0;
27193     }
27194
27195     
27196 });
27197 Ext.reg('button', Ext.Button);
27198
27199
27200 Ext.ButtonToggleMgr = function(){
27201    var groups = {};
27202
27203    function toggleGroup(btn, state){
27204        if(state){
27205            var g = groups[btn.toggleGroup];
27206            for(var i = 0, l = g.length; i < l; i++){
27207                if(g[i] != btn){
27208                    g[i].toggle(false);
27209                }
27210            }
27211        }
27212    }
27213
27214    return {
27215        register : function(btn){
27216            if(!btn.toggleGroup){
27217                return;
27218            }
27219            var g = groups[btn.toggleGroup];
27220            if(!g){
27221                g = groups[btn.toggleGroup] = [];
27222            }
27223            g.push(btn);
27224            btn.on('toggle', toggleGroup);
27225        },
27226
27227        unregister : function(btn){
27228            if(!btn.toggleGroup){
27229                return;
27230            }
27231            var g = groups[btn.toggleGroup];
27232            if(g){
27233                g.remove(btn);
27234                btn.un('toggle', toggleGroup);
27235            }
27236        },
27237
27238        
27239        getPressed : function(group){
27240            var g = groups[group];
27241            if(g){
27242                for(var i = 0, len = g.length; i < len; i++){
27243                    if(g[i].pressed === true){
27244                        return g[i];
27245                    }
27246                }
27247            }
27248            return null;
27249        }
27250    };
27251 }();
27252
27253 Ext.SplitButton = Ext.extend(Ext.Button, {
27254         
27255     arrowSelector : 'em',
27256     split: true,
27257
27258     
27259     initComponent : function(){
27260         Ext.SplitButton.superclass.initComponent.call(this);
27261         
27262         this.addEvents("arrowclick");
27263     },
27264
27265     
27266     onRender : function(){
27267         Ext.SplitButton.superclass.onRender.apply(this, arguments);
27268         if(this.arrowTooltip){
27269             this.el.child(this.arrowSelector).dom[this.tooltipType] = this.arrowTooltip;
27270         }
27271     },
27272
27273     
27274     setArrowHandler : function(handler, scope){
27275         this.arrowHandler = handler;
27276         this.scope = scope;
27277     },
27278
27279     getMenuClass : function(){
27280         return 'x-btn-split' + (this.arrowAlign == 'bottom' ? '-bottom' : '');
27281     },
27282
27283     isClickOnArrow : function(e){
27284         if (this.arrowAlign != 'bottom') {
27285             var visBtn = this.el.child('em.x-btn-split');
27286             var right = visBtn.getRegion().right - visBtn.getPadding('r');
27287             return e.getPageX() > right;
27288         } else {
27289             return e.getPageY() > this.btnEl.getRegion().bottom;
27290         }
27291     },
27292
27293     
27294     onClick : function(e, t){
27295         e.preventDefault();
27296         if(!this.disabled){
27297             if(this.isClickOnArrow(e)){
27298                 if(this.menu && !this.menu.isVisible() && !this.ignoreNextClick){
27299                     this.showMenu();
27300                 }
27301                 this.fireEvent("arrowclick", this, e);
27302                 if(this.arrowHandler){
27303                     this.arrowHandler.call(this.scope || this, this, e);
27304                 }
27305             }else{
27306                 if(this.enableToggle){
27307                     this.toggle();
27308                 }
27309                 this.fireEvent("click", this, e);
27310                 if(this.handler){
27311                     this.handler.call(this.scope || this, this, e);
27312                 }
27313             }
27314         }
27315     },
27316
27317     
27318     isMenuTriggerOver : function(e){
27319         return this.menu && e.target.tagName == this.arrowSelector;
27320     },
27321
27322     
27323     isMenuTriggerOut : function(e, internal){
27324         return this.menu && e.target.tagName != this.arrowSelector;
27325     }
27326 });
27327
27328 Ext.reg('splitbutton', Ext.SplitButton);
27329 Ext.CycleButton = Ext.extend(Ext.SplitButton, {
27330     
27331     
27332     
27333     
27334     
27335     
27336
27337     
27338     getItemText : function(item){
27339         if(item && this.showText === true){
27340             var text = '';
27341             if(this.prependText){
27342                 text += this.prependText;
27343             }
27344             text += item.text;
27345             return text;
27346         }
27347         return undefined;
27348     },
27349
27350     
27351     setActiveItem : function(item, suppressEvent){
27352         if(!Ext.isObject(item)){
27353             item = this.menu.getComponent(item);
27354         }
27355         if(item){
27356             if(!this.rendered){
27357                 this.text = this.getItemText(item);
27358                 this.iconCls = item.iconCls;
27359             }else{
27360                 var t = this.getItemText(item);
27361                 if(t){
27362                     this.setText(t);
27363                 }
27364                 this.setIconClass(item.iconCls);
27365             }
27366             this.activeItem = item;
27367             if(!item.checked){
27368                 item.setChecked(true, true);
27369             }
27370             if(this.forceIcon){
27371                 this.setIconClass(this.forceIcon);
27372             }
27373             if(!suppressEvent){
27374                 this.fireEvent('change', this, item);
27375             }
27376         }
27377     },
27378
27379     
27380     getActiveItem : function(){
27381         return this.activeItem;
27382     },
27383
27384     
27385     initComponent : function(){
27386         this.addEvents(
27387             
27388             "change"
27389         );
27390
27391         if(this.changeHandler){
27392             this.on('change', this.changeHandler, this.scope||this);
27393             delete this.changeHandler;
27394         }
27395
27396         this.itemCount = this.items.length;
27397
27398         this.menu = {cls:'x-cycle-menu', items:[]};
27399         var checked;
27400         Ext.each(this.items, function(item, i){
27401             Ext.apply(item, {
27402                 group: item.group || this.id,
27403                 itemIndex: i,
27404                 checkHandler: this.checkHandler,
27405                 scope: this,
27406                 checked: item.checked || false
27407             });
27408             this.menu.items.push(item);
27409             if(item.checked){
27410                 checked = item;
27411             }
27412         }, this);
27413         this.setActiveItem(checked, true);
27414         Ext.CycleButton.superclass.initComponent.call(this);
27415
27416         this.on('click', this.toggleSelected, this);
27417     },
27418
27419     
27420     checkHandler : function(item, pressed){
27421         if(pressed){
27422             this.setActiveItem(item);
27423         }
27424     },
27425
27426     
27427     toggleSelected : function(){
27428         var m = this.menu;
27429         m.render();
27430         
27431         if(!m.hasLayout){
27432             m.doLayout();
27433         }
27434         
27435         var nextIdx, checkItem;
27436         for (var i = 1; i < this.itemCount; i++) {
27437             nextIdx = (this.activeItem.itemIndex + i) % this.itemCount;
27438             
27439             checkItem = m.items.itemAt(nextIdx);
27440             
27441             if (!checkItem.disabled) {
27442                 checkItem.setChecked(true);
27443                 break;
27444             }
27445         }
27446     }
27447 });
27448 Ext.reg('cycle', Ext.CycleButton);
27449 Ext.layout.ToolbarLayout = Ext.extend(Ext.layout.ContainerLayout, {
27450     monitorResize : true,
27451     triggerWidth : 18,
27452     lastOverflow : false,
27453     forceLayout: true,
27454
27455     noItemsMenuText : '<div class="x-toolbar-no-items">(None)</div>',
27456     
27457     onLayout : function(ct, target){
27458         if(!this.leftTr){
27459             var align = ct.buttonAlign == 'center' ? 'center' : 'left';
27460             target.addClass('x-toolbar-layout-ct');
27461             target.insertHtml('beforeEnd',
27462                  '<table cellspacing="0" class="x-toolbar-ct"><tbody><tr><td class="x-toolbar-left" align="' + align + '"><table cellspacing="0"><tbody><tr class="x-toolbar-left-row"></tr></tbody></table></td><td class="x-toolbar-right" align="right"><table cellspacing="0" class="x-toolbar-right-ct"><tbody><tr><td><table cellspacing="0"><tbody><tr class="x-toolbar-right-row"></tr></tbody></table></td><td><table cellspacing="0"><tbody><tr class="x-toolbar-extras-row"></tr></tbody></table></td></tr></tbody></table></td></tr></tbody></table>');
27463             this.leftTr = target.child('tr.x-toolbar-left-row', true);
27464             this.rightTr = target.child('tr.x-toolbar-right-row', true);
27465             this.extrasTr = target.child('tr.x-toolbar-extras-row', true);
27466         }
27467         var side = ct.buttonAlign == 'right' ? this.rightTr : this.leftTr,
27468             pos = 0,
27469             items = ct.items.items;
27470
27471         for(var i = 0, len = items.length, c; i < len; i++, pos++) {
27472             c = items[i];
27473             if(c.isFill){
27474                 side = this.rightTr;
27475                 pos = -1;
27476             }else if(!c.rendered){
27477                 c.render(this.insertCell(c, side, pos));
27478             }else{
27479                 if(!c.xtbHidden && !this.isValidParent(c, side.childNodes[pos])){
27480                     var td = this.insertCell(c, side, pos);
27481                     td.appendChild(c.getPositionEl().dom);
27482                     c.container = Ext.get(td);
27483                 }
27484             }
27485         }
27486         
27487         this.cleanup(this.leftTr);
27488         this.cleanup(this.rightTr);
27489         this.cleanup(this.extrasTr);
27490         this.fitToSize(target);
27491     },
27492
27493     cleanup : function(row){
27494         var cn = row.childNodes;
27495         for(var i = cn.length-1, c; i >= 0 && (c = cn[i]); i--){
27496             if(!c.firstChild){
27497                 row.removeChild(c);
27498             }
27499         }
27500     },
27501
27502     insertCell : function(c, side, pos){
27503         var td = document.createElement('td');
27504         td.className='x-toolbar-cell';
27505         side.insertBefore(td, side.childNodes[pos]||null);
27506         return td;
27507     },
27508
27509     hideItem : function(item){
27510         var h = (this.hiddens = this.hiddens || []);
27511         h.push(item);
27512         item.xtbHidden = true;
27513         item.xtbWidth = item.getPositionEl().dom.parentNode.offsetWidth;
27514         item.hide();
27515     },
27516
27517     unhideItem : function(item){
27518         item.show();
27519         item.xtbHidden = false;
27520         this.hiddens.remove(item);
27521         if(this.hiddens.length < 1){
27522             delete this.hiddens;
27523         }
27524     },
27525
27526     getItemWidth : function(c){
27527         return c.hidden ? (c.xtbWidth || 0) : c.getPositionEl().dom.parentNode.offsetWidth;
27528     },
27529
27530     fitToSize : function(t){
27531         if(this.container.enableOverflow === false){
27532             return;
27533         }
27534         var w = t.dom.clientWidth,
27535             lw = this.lastWidth || 0,
27536             iw = t.dom.firstChild.offsetWidth,
27537             clipWidth = w - this.triggerWidth,
27538             hideIndex = -1;
27539
27540         this.lastWidth = w;
27541
27542         if(iw > w || (this.hiddens && w >= lw)){
27543             var i, items = this.container.items.items,
27544                 len = items.length, c,
27545                 loopWidth = 0;
27546
27547             for(i = 0; i < len; i++) {
27548                 c = items[i];
27549                 if(!c.isFill){
27550                     loopWidth += this.getItemWidth(c);
27551                     if(loopWidth > clipWidth){
27552                         if(!(c.hidden || c.xtbHidden)){
27553                             this.hideItem(c);
27554                         }
27555                     }else if(c.xtbHidden){
27556                         this.unhideItem(c);
27557                     }
27558                 }
27559             }
27560         }
27561         if(this.hiddens){
27562             this.initMore();
27563             if(!this.lastOverflow){
27564                 this.container.fireEvent('overflowchange', this.container, true);
27565                 this.lastOverflow = true;
27566             }
27567         }else if(this.more){
27568             this.clearMenu();
27569             this.more.destroy();
27570             delete this.more;
27571             if(this.lastOverflow){
27572                 this.container.fireEvent('overflowchange', this.container, false);
27573                 this.lastOverflow = false;
27574             }
27575         }
27576     },
27577
27578     createMenuConfig : function(c, hideOnClick){
27579         var cfg = Ext.apply({}, c.initialConfig),
27580             group = c.toggleGroup;
27581
27582         Ext.apply(cfg, {
27583             text: c.overflowText || c.text,
27584             iconCls: c.iconCls,
27585             icon: c.icon,
27586             itemId: c.itemId,
27587             disabled: c.disabled,
27588             handler: c.handler,
27589             scope: c.scope,
27590             menu: c.menu,
27591             hideOnClick: hideOnClick
27592         });
27593         if(group || c.enableToggle){
27594             Ext.apply(cfg, {
27595                 group: group,
27596                 checked: c.pressed,
27597                 listeners: {
27598                     checkchange: function(item, checked){
27599                         c.toggle(checked);
27600                     }
27601                 }
27602             });
27603         }
27604         delete cfg.ownerCt;
27605         delete cfg.xtype;
27606         delete cfg.id;
27607         return cfg;
27608     },
27609
27610     
27611     addComponentToMenu : function(m, c){
27612         if(c instanceof Ext.Toolbar.Separator){
27613             m.add('-');
27614         }else if(Ext.isFunction(c.isXType)){
27615             if(c.isXType('splitbutton')){
27616                 m.add(this.createMenuConfig(c, true));
27617             }else if(c.isXType('button')){
27618                 m.add(this.createMenuConfig(c, !c.menu));
27619             }else if(c.isXType('buttongroup')){
27620                 c.items.each(function(item){
27621                      this.addComponentToMenu(m, item);
27622                 }, this);
27623             }
27624         }
27625     },
27626
27627     clearMenu : function(){
27628         var m = this.moreMenu;
27629         if(m && m.items){
27630             m.items.each(function(item){
27631                 delete item.menu;
27632             });
27633         }
27634     },
27635
27636     
27637     beforeMoreShow : function(m){
27638         var h = this.container.items.items,
27639             len = h.length,
27640             c,
27641             prev,
27642             needsSep = function(group, item){
27643                 return group.isXType('buttongroup') && !(item instanceof Ext.Toolbar.Separator);
27644             };
27645
27646         this.clearMenu();
27647         m.removeAll();
27648         for(var i = 0; i < len; i++){
27649             c = h[i];
27650             if(c.xtbHidden){
27651                 if(prev && (needsSep(c, prev) || needsSep(prev, c))){
27652                     m.add('-');
27653                 }
27654                 this.addComponentToMenu(m, c);
27655                 prev = c;
27656             }
27657         }
27658         
27659         
27660         if(m.items.length < 1){
27661             m.add(this.noItemsMenuText);
27662         }
27663     },
27664
27665     initMore : function(){
27666         if(!this.more){
27667             this.moreMenu = new Ext.menu.Menu({
27668                 listeners: {
27669                     beforeshow: this.beforeMoreShow,
27670                     scope: this
27671                 }
27672             });
27673             this.moreMenu.ownerCt = this.container;
27674             this.more = new Ext.Button({
27675                 iconCls: 'x-toolbar-more-icon',
27676                 cls: 'x-toolbar-more',
27677                 menu: this.moreMenu
27678             });
27679             var td = this.insertCell(this.more, this.extrasTr, 100);
27680             this.more.render(td);
27681         }
27682     },
27683
27684     onRemove : function(c){
27685         delete this.leftTr;
27686         delete this.rightTr;
27687         delete this.extrasTr;
27688         Ext.layout.ToolbarLayout.superclass.onRemove.call(this, c);
27689     },
27690
27691     destroy : function(){
27692         Ext.destroy(this.more, this.moreMenu);
27693         delete this.leftTr;
27694         delete this.rightTr;
27695         delete this.extrasTr;
27696         Ext.layout.ToolbarLayout.superclass.destroy.call(this);
27697     }
27698     
27699 });
27700
27701 Ext.Container.LAYOUTS.toolbar = Ext.layout.ToolbarLayout;
27702
27703
27704 Ext.Toolbar = function(config){
27705     if(Ext.isArray(config)){
27706         config = {items: config, layout: 'toolbar'};
27707     } else {
27708         config = Ext.apply({
27709             layout: 'toolbar'
27710         }, config);
27711         if(config.buttons) {
27712             config.items = config.buttons;
27713         }
27714     }
27715     Ext.Toolbar.superclass.constructor.call(this, config);
27716 };
27717
27718 (function(){
27719
27720 var T = Ext.Toolbar;
27721
27722 Ext.extend(T, Ext.Container, {
27723
27724     defaultType: 'button',
27725
27726     
27727     
27728
27729     trackMenus : true,
27730     internalDefaults: {removeMode: 'container', hideParent: true},
27731     toolbarCls: 'x-toolbar',
27732
27733     initComponent : function(){
27734         T.superclass.initComponent.call(this);
27735
27736         
27737         this.addEvents('overflowchange');
27738     },
27739
27740     
27741     onRender : function(ct, position){
27742         if(!this.el){
27743             if(!this.autoCreate){
27744                 this.autoCreate = {
27745                     cls: this.toolbarCls + ' x-small-editor'
27746                 };
27747             }
27748             this.el = ct.createChild(Ext.apply({ id: this.id },this.autoCreate), position);
27749             Ext.Toolbar.superclass.onRender.apply(this, arguments);
27750         }
27751     },
27752
27753     
27754
27755     
27756     lookupComponent : function(c){
27757         if(Ext.isString(c)){
27758             if(c == '-'){
27759                 c = new T.Separator();
27760             }else if(c == ' '){
27761                 c = new T.Spacer();
27762             }else if(c == '->'){
27763                 c = new T.Fill();
27764             }else{
27765                 c = new T.TextItem(c);
27766             }
27767             this.applyDefaults(c);
27768         }else{
27769             if(c.isFormField || c.render){ 
27770                 c = this.createComponent(c);
27771             }else if(c.tag){ 
27772                 c = new T.Item({autoEl: c});
27773             }else if(c.tagName){ 
27774                 c = new T.Item({el:c});
27775             }else if(Ext.isObject(c)){ 
27776                 c = c.xtype ? this.createComponent(c) : this.constructButton(c);
27777             }
27778         }
27779         return c;
27780     },
27781
27782     
27783     applyDefaults : function(c){
27784         if(!Ext.isString(c)){
27785             c = Ext.Toolbar.superclass.applyDefaults.call(this, c);
27786             var d = this.internalDefaults;
27787             if(c.events){
27788                 Ext.applyIf(c.initialConfig, d);
27789                 Ext.apply(c, d);
27790             }else{
27791                 Ext.applyIf(c, d);
27792             }
27793         }
27794         return c;
27795     },
27796
27797     
27798     addSeparator : function(){
27799         return this.add(new T.Separator());
27800     },
27801
27802     
27803     addSpacer : function(){
27804         return this.add(new T.Spacer());
27805     },
27806
27807     
27808     addFill : function(){
27809         this.add(new T.Fill());
27810     },
27811
27812     
27813     addElement : function(el){
27814         return this.addItem(new T.Item({el:el}));
27815     },
27816
27817     
27818     addItem : function(item){
27819         return this.add.apply(this, arguments);
27820     },
27821
27822     
27823     addButton : function(config){
27824         if(Ext.isArray(config)){
27825             var buttons = [];
27826             for(var i = 0, len = config.length; i < len; i++) {
27827                 buttons.push(this.addButton(config[i]));
27828             }
27829             return buttons;
27830         }
27831         return this.add(this.constructButton(config));
27832     },
27833
27834     
27835     addText : function(text){
27836         return this.addItem(new T.TextItem(text));
27837     },
27838
27839     
27840     addDom : function(config){
27841         return this.add(new T.Item({autoEl: config}));
27842     },
27843
27844     
27845     addField : function(field){
27846         return this.add(field);
27847     },
27848
27849     
27850     insertButton : function(index, item){
27851         if(Ext.isArray(item)){
27852             var buttons = [];
27853             for(var i = 0, len = item.length; i < len; i++) {
27854                buttons.push(this.insertButton(index + i, item[i]));
27855             }
27856             return buttons;
27857         }
27858         return Ext.Toolbar.superclass.insert.call(this, index, item);
27859     },
27860
27861     
27862     trackMenu : function(item, remove){
27863         if(this.trackMenus && item.menu){
27864             var method = remove ? 'mun' : 'mon';
27865             this[method](item, 'menutriggerover', this.onButtonTriggerOver, this);
27866             this[method](item, 'menushow', this.onButtonMenuShow, this);
27867             this[method](item, 'menuhide', this.onButtonMenuHide, this);
27868         }
27869     },
27870
27871     
27872     constructButton : function(item){
27873         var b = item.events ? item : this.createComponent(item, item.split ? 'splitbutton' : this.defaultType);
27874         return b;
27875     },
27876
27877     
27878     onAdd : function(c){
27879         Ext.Toolbar.superclass.onAdd.call(this);
27880         this.trackMenu(c);
27881     },
27882
27883     
27884     onRemove : function(c){
27885         Ext.Toolbar.superclass.onRemove.call(this);
27886         this.trackMenu(c, true);
27887     },
27888
27889     
27890     onDisable : function(){
27891         this.items.each(function(item){
27892              if(item.disable){
27893                  item.disable();
27894              }
27895         });
27896     },
27897
27898     
27899     onEnable : function(){
27900         this.items.each(function(item){
27901              if(item.enable){
27902                  item.enable();
27903              }
27904         });
27905     },
27906
27907     
27908     onButtonTriggerOver : function(btn){
27909         if(this.activeMenuBtn && this.activeMenuBtn != btn){
27910             this.activeMenuBtn.hideMenu();
27911             btn.showMenu();
27912             this.activeMenuBtn = btn;
27913         }
27914     },
27915
27916     
27917     onButtonMenuShow : function(btn){
27918         this.activeMenuBtn = btn;
27919     },
27920
27921     
27922     onButtonMenuHide : function(btn){
27923         delete this.activeMenuBtn;
27924     }
27925 });
27926 Ext.reg('toolbar', Ext.Toolbar);
27927
27928
27929 T.Item = Ext.extend(Ext.BoxComponent, {
27930     hideParent: true, 
27931     enable:Ext.emptyFn,
27932     disable:Ext.emptyFn,
27933     focus:Ext.emptyFn
27934     
27935 });
27936 Ext.reg('tbitem', T.Item);
27937
27938
27939 T.Separator = Ext.extend(T.Item, {
27940     onRender : function(ct, position){
27941         this.el = ct.createChild({tag:'span', cls:'xtb-sep'}, position);
27942     }
27943 });
27944 Ext.reg('tbseparator', T.Separator);
27945
27946
27947 T.Spacer = Ext.extend(T.Item, {
27948     
27949
27950     onRender : function(ct, position){
27951         this.el = ct.createChild({tag:'div', cls:'xtb-spacer', style: this.width?'width:'+this.width+'px':''}, position);
27952     }
27953 });
27954 Ext.reg('tbspacer', T.Spacer);
27955
27956
27957 T.Fill = Ext.extend(T.Item, {
27958     
27959     render : Ext.emptyFn,
27960     isFill : true
27961 });
27962 Ext.reg('tbfill', T.Fill);
27963
27964
27965 T.TextItem = Ext.extend(T.Item, {
27966     
27967
27968     constructor: function(config){
27969         T.TextItem.superclass.constructor.call(this, Ext.isString(config) ? {text: config} : config);
27970     },
27971
27972     
27973     onRender : function(ct, position) {
27974         this.autoEl = {cls: 'xtb-text', html: this.text || ''};
27975         T.TextItem.superclass.onRender.call(this, ct, position);
27976     },
27977
27978     
27979     setText : function(t) {
27980         if(this.rendered){
27981             this.el.update(t);
27982         }else{
27983             this.text = t;
27984         }
27985     }
27986 });
27987 Ext.reg('tbtext', T.TextItem);
27988
27989
27990 T.Button = Ext.extend(Ext.Button, {});
27991 T.SplitButton = Ext.extend(Ext.SplitButton, {});
27992 Ext.reg('tbbutton', T.Button);
27993 Ext.reg('tbsplit', T.SplitButton);
27994
27995 })();
27996
27997 Ext.ButtonGroup = Ext.extend(Ext.Panel, {
27998     
27999     
28000     baseCls: 'x-btn-group',
28001     
28002     layout:'table',
28003     defaultType: 'button',
28004     
28005     frame: true,
28006     internalDefaults: {removeMode: 'container', hideParent: true},
28007
28008     initComponent : function(){
28009         this.layoutConfig = this.layoutConfig || {};
28010         Ext.applyIf(this.layoutConfig, {
28011             columns : this.columns
28012         });
28013         if(!this.title){
28014             this.addClass('x-btn-group-notitle');
28015         }
28016         this.on('afterlayout', this.onAfterLayout, this);
28017         Ext.ButtonGroup.superclass.initComponent.call(this);
28018     },
28019
28020     applyDefaults : function(c){
28021         c = Ext.ButtonGroup.superclass.applyDefaults.call(this, c);
28022         var d = this.internalDefaults;
28023         if(c.events){
28024             Ext.applyIf(c.initialConfig, d);
28025             Ext.apply(c, d);
28026         }else{
28027             Ext.applyIf(c, d);
28028         }
28029         return c;
28030     },
28031
28032     onAfterLayout : function(){
28033         var bodyWidth = this.body.getFrameWidth('lr') + this.body.dom.firstChild.offsetWidth;
28034         this.body.setWidth(bodyWidth);
28035         this.el.setWidth(bodyWidth + this.getFrameWidth());
28036     }
28037     
28038 });
28039
28040 Ext.reg('buttongroup', Ext.ButtonGroup);
28041
28042 (function() {
28043
28044 var T = Ext.Toolbar;
28045
28046 Ext.PagingToolbar = Ext.extend(Ext.Toolbar, {
28047     
28048     
28049     
28050     pageSize : 20,
28051     
28052     
28053     displayMsg : 'Displaying {0} - {1} of {2}',
28054     
28055     emptyMsg : 'No data to display',
28056     
28057     beforePageText : 'Page',
28058     
28059     afterPageText : 'of {0}',
28060     
28061     firstText : 'First Page',
28062     
28063     prevText : 'Previous Page',
28064     
28065     nextText : 'Next Page',
28066     
28067     lastText : 'Last Page',
28068     
28069     refreshText : 'Refresh',
28070
28071     
28072
28073     
28074
28075     
28076
28077     initComponent : function(){
28078         var pagingItems = [this.first = new T.Button({
28079             tooltip: this.firstText,
28080             overflowText: this.firstText,
28081             iconCls: 'x-tbar-page-first',
28082             disabled: true,
28083             handler: this.moveFirst,
28084             scope: this
28085         }), this.prev = new T.Button({
28086             tooltip: this.prevText,
28087             overflowText: this.prevText,
28088             iconCls: 'x-tbar-page-prev',
28089             disabled: true,
28090             handler: this.movePrevious,
28091             scope: this
28092         }), '-', this.beforePageText,
28093         this.inputItem = new Ext.form.NumberField({
28094             cls: 'x-tbar-page-number',
28095             allowDecimals: false,
28096             allowNegative: false,
28097             enableKeyEvents: true,
28098             selectOnFocus: true,
28099             submitValue: false,
28100             listeners: {
28101                 scope: this,
28102                 keydown: this.onPagingKeyDown,
28103                 blur: this.onPagingBlur
28104             }
28105         }), this.afterTextItem = new T.TextItem({
28106             text: String.format(this.afterPageText, 1)
28107         }), '-', this.next = new T.Button({
28108             tooltip: this.nextText,
28109             overflowText: this.nextText,
28110             iconCls: 'x-tbar-page-next',
28111             disabled: true,
28112             handler: this.moveNext,
28113             scope: this
28114         }), this.last = new T.Button({
28115             tooltip: this.lastText,
28116             overflowText: this.lastText,
28117             iconCls: 'x-tbar-page-last',
28118             disabled: true,
28119             handler: this.moveLast,
28120             scope: this
28121         }), '-', this.refresh = new T.Button({
28122             tooltip: this.refreshText,
28123             overflowText: this.refreshText,
28124             iconCls: 'x-tbar-loading',
28125             handler: this.doRefresh,
28126             scope: this
28127         })];
28128
28129
28130         var userItems = this.items || this.buttons || [];
28131         if (this.prependButtons) {
28132             this.items = userItems.concat(pagingItems);
28133         }else{
28134             this.items = pagingItems.concat(userItems);
28135         }
28136         delete this.buttons;
28137         if(this.displayInfo){
28138             this.items.push('->');
28139             this.items.push(this.displayItem = new T.TextItem({}));
28140         }
28141         Ext.PagingToolbar.superclass.initComponent.call(this);
28142         this.addEvents(
28143             
28144             'change',
28145             
28146             'beforechange'
28147         );
28148         this.on('afterlayout', this.onFirstLayout, this, {single: true});
28149         this.cursor = 0;
28150         this.bindStore(this.store, true);
28151     },
28152
28153     
28154     onFirstLayout : function(){
28155         if(this.dsLoaded){
28156             this.onLoad.apply(this, this.dsLoaded);
28157         }
28158     },
28159
28160     
28161     updateInfo : function(){
28162         if(this.displayItem){
28163             var count = this.store.getCount();
28164             var msg = count == 0 ?
28165                 this.emptyMsg :
28166                 String.format(
28167                     this.displayMsg,
28168                     this.cursor+1, this.cursor+count, this.store.getTotalCount()
28169                 );
28170             this.displayItem.setText(msg);
28171         }
28172     },
28173
28174     
28175     onLoad : function(store, r, o){
28176         if(!this.rendered){
28177             this.dsLoaded = [store, r, o];
28178             return;
28179         }
28180         var p = this.getParams();
28181         this.cursor = (o.params && o.params[p.start]) ? o.params[p.start] : 0;
28182         var d = this.getPageData(), ap = d.activePage, ps = d.pages;
28183
28184         this.afterTextItem.setText(String.format(this.afterPageText, d.pages));
28185         this.inputItem.setValue(ap);
28186         this.first.setDisabled(ap == 1);
28187         this.prev.setDisabled(ap == 1);
28188         this.next.setDisabled(ap == ps);
28189         this.last.setDisabled(ap == ps);
28190         this.refresh.enable();
28191         this.updateInfo();
28192         this.fireEvent('change', this, d);
28193     },
28194
28195     
28196     getPageData : function(){
28197         var total = this.store.getTotalCount();
28198         return {
28199             total : total,
28200             activePage : Math.ceil((this.cursor+this.pageSize)/this.pageSize),
28201             pages :  total < this.pageSize ? 1 : Math.ceil(total/this.pageSize)
28202         };
28203     },
28204
28205     
28206     changePage : function(page){
28207         this.doLoad(((page-1) * this.pageSize).constrain(0, this.store.getTotalCount()));
28208     },
28209
28210     
28211     onLoadError : function(){
28212         if(!this.rendered){
28213             return;
28214         }
28215         this.refresh.enable();
28216     },
28217
28218     
28219     readPage : function(d){
28220         var v = this.inputItem.getValue(), pageNum;
28221         if (!v || isNaN(pageNum = parseInt(v, 10))) {
28222             this.inputItem.setValue(d.activePage);
28223             return false;
28224         }
28225         return pageNum;
28226     },
28227
28228     onPagingFocus : function(){
28229         this.inputItem.select();
28230     },
28231
28232     
28233     onPagingBlur : function(e){
28234         this.inputItem.setValue(this.getPageData().activePage);
28235     },
28236
28237     
28238     onPagingKeyDown : function(field, e){
28239         var k = e.getKey(), d = this.getPageData(), pageNum;
28240         if (k == e.RETURN) {
28241             e.stopEvent();
28242             pageNum = this.readPage(d);
28243             if(pageNum !== false){
28244                 pageNum = Math.min(Math.max(1, pageNum), d.pages) - 1;
28245                 this.doLoad(pageNum * this.pageSize);
28246             }
28247         }else if (k == e.HOME || k == e.END){
28248             e.stopEvent();
28249             pageNum = k == e.HOME ? 1 : d.pages;
28250             field.setValue(pageNum);
28251         }else if (k == e.UP || k == e.PAGEUP || k == e.DOWN || k == e.PAGEDOWN){
28252             e.stopEvent();
28253             if((pageNum = this.readPage(d))){
28254                 var increment = e.shiftKey ? 10 : 1;
28255                 if(k == e.DOWN || k == e.PAGEDOWN){
28256                     increment *= -1;
28257                 }
28258                 pageNum += increment;
28259                 if(pageNum >= 1 & pageNum <= d.pages){
28260                     field.setValue(pageNum);
28261                 }
28262             }
28263         }
28264     },
28265
28266     
28267     getParams : function(){
28268         
28269         return this.paramNames || this.store.paramNames;
28270     },
28271
28272     
28273     beforeLoad : function(){
28274         if(this.rendered && this.refresh){
28275             this.refresh.disable();
28276         }
28277     },
28278
28279     
28280     doLoad : function(start){
28281         var o = {}, pn = this.getParams();
28282         o[pn.start] = start;
28283         o[pn.limit] = this.pageSize;
28284         if(this.fireEvent('beforechange', this, o) !== false){
28285             this.store.load({params:o});
28286         }
28287     },
28288
28289     
28290     moveFirst : function(){
28291         this.doLoad(0);
28292     },
28293
28294     
28295     movePrevious : function(){
28296         this.doLoad(Math.max(0, this.cursor-this.pageSize));
28297     },
28298
28299     
28300     moveNext : function(){
28301         this.doLoad(this.cursor+this.pageSize);
28302     },
28303
28304     
28305     moveLast : function(){
28306         var total = this.store.getTotalCount(),
28307             extra = total % this.pageSize;
28308
28309         this.doLoad(extra ? (total - extra) : total - this.pageSize);
28310     },
28311
28312     
28313     doRefresh : function(){
28314         this.doLoad(this.cursor);
28315     },
28316
28317     
28318     bindStore : function(store, initial){
28319         var doLoad;
28320         if(!initial && this.store){
28321             if(store !== this.store && this.store.autoDestroy){
28322                 this.store.destroy();
28323             }else{
28324                 this.store.un('beforeload', this.beforeLoad, this);
28325                 this.store.un('load', this.onLoad, this);
28326                 this.store.un('exception', this.onLoadError, this);
28327             }
28328             if(!store){
28329                 this.store = null;
28330             }
28331         }
28332         if(store){
28333             store = Ext.StoreMgr.lookup(store);
28334             store.on({
28335                 scope: this,
28336                 beforeload: this.beforeLoad,
28337                 load: this.onLoad,
28338                 exception: this.onLoadError
28339             });
28340             doLoad = true;
28341         }
28342         this.store = store;
28343         if(doLoad){
28344             this.onLoad(store, null, {});
28345         }
28346     },
28347
28348     
28349     unbind : function(store){
28350         this.bindStore(null);
28351     },
28352
28353     
28354     bind : function(store){
28355         this.bindStore(store);
28356     },
28357
28358     
28359     onDestroy : function(){
28360         this.bindStore(null);
28361         Ext.PagingToolbar.superclass.onDestroy.call(this);
28362     }
28363 });
28364
28365 })();
28366 Ext.reg('paging', Ext.PagingToolbar);
28367 Ext.History = (function () {
28368     var iframe, hiddenField;
28369     var ready = false;
28370     var currentToken;
28371
28372     function getHash() {
28373         var href = top.location.href, i = href.indexOf("#");
28374         return i >= 0 ? href.substr(i + 1) : null;
28375     }
28376
28377     function doSave() {
28378         hiddenField.value = currentToken;
28379     }
28380
28381     function handleStateChange(token) {
28382         currentToken = token;
28383         Ext.History.fireEvent('change', token);
28384     }
28385
28386     function updateIFrame (token) {
28387         var html = ['<html><body><div id="state">',Ext.util.Format.htmlEncode(token),'</div></body></html>'].join('');
28388         try {
28389             var doc = iframe.contentWindow.document;
28390             doc.open();
28391             doc.write(html);
28392             doc.close();
28393             return true;
28394         } catch (e) {
28395             return false;
28396         }
28397     }
28398
28399     function checkIFrame() {
28400         if (!iframe.contentWindow || !iframe.contentWindow.document) {
28401             setTimeout(checkIFrame, 10);
28402             return;
28403         }
28404
28405         var doc = iframe.contentWindow.document;
28406         var elem = doc.getElementById("state");
28407         var token = elem ? elem.innerText : null;
28408
28409         var hash = getHash();
28410
28411         setInterval(function () {
28412
28413             doc = iframe.contentWindow.document;
28414             elem = doc.getElementById("state");
28415
28416             var newtoken = elem ? elem.innerText : null;
28417
28418             var newHash = getHash();
28419
28420             if (newtoken !== token) {
28421                 token = newtoken;
28422                 handleStateChange(token);
28423                 top.location.hash = token;
28424                 hash = token;
28425                 doSave();
28426             } else if (newHash !== hash) {
28427                 hash = newHash;
28428                 updateIFrame(newHash);
28429             }
28430
28431         }, 50);
28432
28433         ready = true;
28434
28435         Ext.History.fireEvent('ready', Ext.History);
28436     }
28437
28438     function startUp() {
28439         currentToken = hiddenField.value ? hiddenField.value : getHash();
28440
28441         if (Ext.isIE) {
28442             checkIFrame();
28443         } else {
28444             var hash = getHash();
28445             setInterval(function () {
28446                 var newHash = getHash();
28447                 if (newHash !== hash) {
28448                     hash = newHash;
28449                     handleStateChange(hash);
28450                     doSave();
28451                 }
28452             }, 50);
28453             ready = true;
28454             Ext.History.fireEvent('ready', Ext.History);
28455         }
28456     }
28457
28458     return {
28459         
28460         fieldId: 'x-history-field',
28461         
28462         iframeId: 'x-history-frame',
28463
28464         events:{},
28465
28466         
28467         init: function (onReady, scope) {
28468             if(ready) {
28469                 Ext.callback(onReady, scope, [this]);
28470                 return;
28471             }
28472             if(!Ext.isReady){
28473                 Ext.onReady(function(){
28474                     Ext.History.init(onReady, scope);
28475                 });
28476                 return;
28477             }
28478             hiddenField = Ext.getDom(Ext.History.fieldId);
28479             if (Ext.isIE) {
28480                 iframe = Ext.getDom(Ext.History.iframeId);
28481             }
28482             this.addEvents(
28483                 
28484                 'ready',
28485                 
28486                 'change'
28487             );
28488             if(onReady){
28489                 this.on('ready', onReady, scope, {single:true});
28490             }
28491             startUp();
28492         },
28493
28494         
28495         add: function (token, preventDup) {
28496             if(preventDup !== false){
28497                 if(this.getToken() == token){
28498                     return true;
28499                 }
28500             }
28501             if (Ext.isIE) {
28502                 return updateIFrame(token);
28503             } else {
28504                 top.location.hash = token;
28505                 return true;
28506             }
28507         },
28508
28509         
28510         back: function(){
28511             history.go(-1);
28512         },
28513
28514         
28515         forward: function(){
28516             history.go(1);
28517         },
28518
28519         
28520         getToken: function() {
28521             return ready ? currentToken : getHash();
28522         }
28523     };
28524 })();
28525 Ext.apply(Ext.History, new Ext.util.Observable());
28526 Ext.Tip = Ext.extend(Ext.Panel, {
28527     
28528     
28529     
28530     minWidth : 40,
28531     
28532     maxWidth : 300,
28533     
28534     shadow : "sides",
28535     
28536     defaultAlign : "tl-bl?",
28537     autoRender: true,
28538     quickShowInterval : 250,
28539
28540     
28541     frame:true,
28542     hidden:true,
28543     baseCls: 'x-tip',
28544     floating:{shadow:true,shim:true,useDisplay:true,constrain:false},
28545     autoHeight:true,
28546
28547     closeAction: 'hide',
28548
28549     
28550     initComponent : function(){
28551         Ext.Tip.superclass.initComponent.call(this);
28552         if(this.closable && !this.title){
28553             this.elements += ',header';
28554         }
28555     },
28556
28557     
28558     afterRender : function(){
28559         Ext.Tip.superclass.afterRender.call(this);
28560         if(this.closable){
28561             this.addTool({
28562                 id: 'close',
28563                 handler: this[this.closeAction],
28564                 scope: this
28565             });
28566         }
28567     },
28568
28569     
28570     showAt : function(xy){
28571         Ext.Tip.superclass.show.call(this);
28572         if(this.measureWidth !== false && (!this.initialConfig || typeof this.initialConfig.width != 'number')){
28573             this.doAutoWidth();
28574         }
28575         if(this.constrainPosition){
28576             xy = this.el.adjustForConstraints(xy);
28577         }
28578         this.setPagePosition(xy[0], xy[1]);
28579     },
28580
28581     
28582     doAutoWidth : function(adjust){
28583         adjust = adjust || 0;
28584         var bw = this.body.getTextWidth();
28585         if(this.title){
28586             bw = Math.max(bw, this.header.child('span').getTextWidth(this.title));
28587         }
28588         bw += this.getFrameWidth() + (this.closable ? 20 : 0) + this.body.getPadding("lr") + adjust;
28589         this.setWidth(bw.constrain(this.minWidth, this.maxWidth));
28590         
28591         
28592         if(Ext.isIE7 && !this.repainted){
28593             this.el.repaint();
28594             this.repainted = true;
28595         }
28596     },
28597
28598     
28599     showBy : function(el, pos){
28600         if(!this.rendered){
28601             this.render(Ext.getBody());
28602         }
28603         this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign));
28604     },
28605
28606     initDraggable : function(){
28607         this.dd = new Ext.Tip.DD(this, typeof this.draggable == 'boolean' ? null : this.draggable);
28608         this.header.addClass('x-tip-draggable');
28609     }
28610 });
28611
28612 Ext.reg('tip', Ext.Tip);
28613
28614
28615 Ext.Tip.DD = function(tip, config){
28616     Ext.apply(this, config);
28617     this.tip = tip;
28618     Ext.Tip.DD.superclass.constructor.call(this, tip.el.id, 'WindowDD-'+tip.id);
28619     this.setHandleElId(tip.header.id);
28620     this.scroll = false;
28621 };
28622
28623 Ext.extend(Ext.Tip.DD, Ext.dd.DD, {
28624     moveOnly:true,
28625     scroll:false,
28626     headerOffsets:[100, 25],
28627     startDrag : function(){
28628         this.tip.el.disableShadow();
28629     },
28630     endDrag : function(e){
28631         this.tip.el.enableShadow(true);
28632     }
28633 });
28634 Ext.ToolTip = Ext.extend(Ext.Tip, {
28635     
28636     
28637     
28638     
28639     showDelay : 500,
28640     
28641     hideDelay : 200,
28642     
28643     dismissDelay : 5000,
28644     
28645     
28646     trackMouse : false,
28647     
28648     anchorToTarget : true,
28649     
28650     anchorOffset : 0,
28651     
28652
28653     
28654     targetCounter : 0,
28655
28656     constrainPosition : false,
28657
28658     
28659     initComponent : function(){
28660         Ext.ToolTip.superclass.initComponent.call(this);
28661         this.lastActive = new Date();
28662         this.initTarget(this.target);
28663         this.origAnchor = this.anchor;
28664     },
28665
28666     
28667     onRender : function(ct, position){
28668         Ext.ToolTip.superclass.onRender.call(this, ct, position);
28669         this.anchorCls = 'x-tip-anchor-' + this.getAnchorPosition();
28670         this.anchorEl = this.el.createChild({
28671             cls: 'x-tip-anchor ' + this.anchorCls
28672         });
28673     },
28674
28675     
28676     afterRender : function(){
28677         Ext.ToolTip.superclass.afterRender.call(this);
28678         this.anchorEl.setStyle('z-index', this.el.getZIndex() + 1);
28679     },
28680
28681     
28682     initTarget : function(target){
28683         var t;
28684         if((t = Ext.get(target))){
28685             if(this.target){
28686                 var tg = Ext.get(this.target);
28687                 this.mun(tg, 'mouseover', this.onTargetOver, this);
28688                 this.mun(tg, 'mouseout', this.onTargetOut, this);
28689                 this.mun(tg, 'mousemove', this.onMouseMove, this);
28690             }
28691             this.mon(t, {
28692                 mouseover: this.onTargetOver,
28693                 mouseout: this.onTargetOut,
28694                 mousemove: this.onMouseMove,
28695                 scope: this
28696             });
28697             this.target = t;
28698         }
28699         if(this.anchor){
28700             this.anchorTarget = this.target;
28701         }
28702     },
28703
28704     
28705     onMouseMove : function(e){
28706         var t = this.delegate ? e.getTarget(this.delegate) : this.triggerElement = true;
28707         if (t) {
28708             this.targetXY = e.getXY();
28709             if (t === this.triggerElement) {
28710                 if(!this.hidden && this.trackMouse){
28711                     this.setPagePosition(this.getTargetXY());
28712                 }
28713             } else {
28714                 this.hide();
28715                 this.lastActive = new Date(0);
28716                 this.onTargetOver(e);
28717             }
28718         } else if (!this.closable && this.isVisible()) {
28719             this.hide();
28720         }
28721     },
28722
28723     
28724     getTargetXY : function(){
28725         if(this.delegate){
28726             this.anchorTarget = this.triggerElement;
28727         }
28728         if(this.anchor){
28729             this.targetCounter++;
28730             var offsets = this.getOffsets(),
28731                 xy = (this.anchorToTarget && !this.trackMouse) ? this.el.getAlignToXY(this.anchorTarget, this.getAnchorAlign()) : this.targetXY,
28732                 dw = Ext.lib.Dom.getViewWidth() - 5,
28733                 dh = Ext.lib.Dom.getViewHeight() - 5,
28734                 de = document.documentElement,
28735                 bd = document.body,
28736                 scrollX = (de.scrollLeft || bd.scrollLeft || 0) + 5,
28737                 scrollY = (de.scrollTop || bd.scrollTop || 0) + 5,
28738                 axy = [xy[0] + offsets[0], xy[1] + offsets[1]]
28739                 sz = this.getSize();
28740                 
28741             this.anchorEl.removeClass(this.anchorCls);
28742
28743             if(this.targetCounter < 2){
28744                 if(axy[0] < scrollX){
28745                     if(this.anchorToTarget){
28746                         this.defaultAlign = 'l-r';
28747                         if(this.mouseOffset){this.mouseOffset[0] *= -1;}
28748                     }
28749                     this.anchor = 'left';
28750                     return this.getTargetXY();
28751                 }
28752                 if(axy[0]+sz.width > dw){
28753                     if(this.anchorToTarget){
28754                         this.defaultAlign = 'r-l';
28755                         if(this.mouseOffset){this.mouseOffset[0] *= -1;}
28756                     }
28757                     this.anchor = 'right';
28758                     return this.getTargetXY();
28759                 }
28760                 if(axy[1] < scrollY){
28761                     if(this.anchorToTarget){
28762                         this.defaultAlign = 't-b';
28763                         if(this.mouseOffset){this.mouseOffset[1] *= -1;}
28764                     }
28765                     this.anchor = 'top';
28766                     return this.getTargetXY();
28767                 }
28768                 if(axy[1]+sz.height > dh){
28769                     if(this.anchorToTarget){
28770                         this.defaultAlign = 'b-t';
28771                         if(this.mouseOffset){this.mouseOffset[1] *= -1;}
28772                     }
28773                     this.anchor = 'bottom';
28774                     return this.getTargetXY();
28775                 }
28776             }
28777
28778             this.anchorCls = 'x-tip-anchor-'+this.getAnchorPosition();
28779             this.anchorEl.addClass(this.anchorCls);
28780             this.targetCounter = 0;
28781             return axy;
28782         }else{
28783             var mouseOffset = this.getMouseOffset();
28784             return [this.targetXY[0]+mouseOffset[0], this.targetXY[1]+mouseOffset[1]];
28785         }
28786     },
28787
28788     getMouseOffset : function(){
28789         var offset = this.anchor ? [0,0] : [15,18];
28790         if(this.mouseOffset){
28791             offset[0] += this.mouseOffset[0];
28792             offset[1] += this.mouseOffset[1];
28793         }
28794         return offset;
28795     },
28796
28797     
28798     getAnchorPosition : function(){
28799         if(this.anchor){
28800             this.tipAnchor = this.anchor.charAt(0);
28801         }else{
28802             var m = this.defaultAlign.match(/^([a-z]+)-([a-z]+)(\?)?$/);
28803             if(!m){
28804                throw 'AnchorTip.defaultAlign is invalid';
28805             }
28806             this.tipAnchor = m[1].charAt(0);
28807         }
28808
28809         switch(this.tipAnchor){
28810             case 't': return 'top';
28811             case 'b': return 'bottom';
28812             case 'r': return 'right';
28813         }
28814         return 'left';
28815     },
28816
28817     
28818     getAnchorAlign : function(){
28819         switch(this.anchor){
28820             case 'top'  : return 'tl-bl';
28821             case 'left' : return 'tl-tr';
28822             case 'right': return 'tr-tl';
28823             default     : return 'bl-tl';
28824         }
28825     },
28826
28827     
28828     getOffsets : function(){
28829         var offsets, 
28830             ap = this.getAnchorPosition().charAt(0);
28831         if(this.anchorToTarget && !this.trackMouse){
28832             switch(ap){
28833                 case 't':
28834                     offsets = [0, 9];
28835                     break;
28836                 case 'b':
28837                     offsets = [0, -13];
28838                     break;
28839                 case 'r':
28840                     offsets = [-13, 0];
28841                     break;
28842                 default:
28843                     offsets = [9, 0];
28844                     break;
28845             }
28846         }else{
28847             switch(ap){
28848                 case 't':
28849                     offsets = [-15-this.anchorOffset, 30];
28850                     break;
28851                 case 'b':
28852                     offsets = [-19-this.anchorOffset, -13-this.el.dom.offsetHeight];
28853                     break;
28854                 case 'r':
28855                     offsets = [-15-this.el.dom.offsetWidth, -13-this.anchorOffset];
28856                     break;
28857                 default:
28858                     offsets = [25, -13-this.anchorOffset];
28859                     break;
28860             }
28861         }
28862         var mouseOffset = this.getMouseOffset();
28863         offsets[0] += mouseOffset[0];
28864         offsets[1] += mouseOffset[1];
28865
28866         return offsets;
28867     },
28868
28869     
28870     onTargetOver : function(e){
28871         if(this.disabled || e.within(this.target.dom, true)){
28872             return;
28873         }
28874         var t = e.getTarget(this.delegate);
28875         if (t) {
28876             this.triggerElement = t;
28877             this.clearTimer('hide');
28878             this.targetXY = e.getXY();
28879             this.delayShow();
28880         }
28881     },
28882
28883     
28884     delayShow : function(){
28885         if(this.hidden && !this.showTimer){
28886             if(this.lastActive.getElapsed() < this.quickShowInterval){
28887                 this.show();
28888             }else{
28889                 this.showTimer = this.show.defer(this.showDelay, this);
28890             }
28891         }else if(!this.hidden && this.autoHide !== false){
28892             this.show();
28893         }
28894     },
28895
28896     
28897     onTargetOut : function(e){
28898         if(this.disabled || e.within(this.target.dom, true)){
28899             return;
28900         }
28901         this.clearTimer('show');
28902         if(this.autoHide !== false){
28903             this.delayHide();
28904         }
28905     },
28906
28907     
28908     delayHide : function(){
28909         if(!this.hidden && !this.hideTimer){
28910             this.hideTimer = this.hide.defer(this.hideDelay, this);
28911         }
28912     },
28913
28914     
28915     hide: function(){
28916         this.clearTimer('dismiss');
28917         this.lastActive = new Date();
28918         if(this.anchorEl){
28919             this.anchorEl.hide();
28920         }
28921         Ext.ToolTip.superclass.hide.call(this);
28922         delete this.triggerElement;
28923     },
28924
28925     
28926     show : function(){
28927         if(this.anchor){
28928             
28929             
28930             this.showAt([-1000,-1000]);
28931             this.origConstrainPosition = this.constrainPosition;
28932             this.constrainPosition = false;
28933             this.anchor = this.origAnchor;
28934         }
28935         this.showAt(this.getTargetXY());
28936
28937         if(this.anchor){
28938             this.syncAnchor();
28939             this.anchorEl.show();
28940             this.constrainPosition = this.origConstrainPosition;
28941         }else{
28942             this.anchorEl.hide();
28943         }
28944     },
28945
28946     
28947     showAt : function(xy){
28948         this.lastActive = new Date();
28949         this.clearTimers();
28950         Ext.ToolTip.superclass.showAt.call(this, xy);
28951         if(this.dismissDelay && this.autoHide !== false){
28952             this.dismissTimer = this.hide.defer(this.dismissDelay, this);
28953         }
28954         if(this.anchor && !this.anchorEl.isVisible()){
28955             this.syncAnchor();
28956             this.anchorEl.show();
28957         }
28958     },
28959
28960     
28961     syncAnchor : function(){
28962         var anchorPos, targetPos, offset;
28963         switch(this.tipAnchor.charAt(0)){
28964             case 't':
28965                 anchorPos = 'b';
28966                 targetPos = 'tl';
28967                 offset = [20+this.anchorOffset, 2];
28968                 break;
28969             case 'r':
28970                 anchorPos = 'l';
28971                 targetPos = 'tr';
28972                 offset = [-2, 11+this.anchorOffset];
28973                 break;
28974             case 'b':
28975                 anchorPos = 't';
28976                 targetPos = 'bl';
28977                 offset = [20+this.anchorOffset, -2];
28978                 break;
28979             default:
28980                 anchorPos = 'r';
28981                 targetPos = 'tl';
28982                 offset = [2, 11+this.anchorOffset];
28983                 break;
28984         }
28985         this.anchorEl.alignTo(this.el, anchorPos+'-'+targetPos, offset);
28986     },
28987
28988     
28989     setPagePosition : function(x, y){
28990         Ext.ToolTip.superclass.setPagePosition.call(this, x, y);
28991         if(this.anchor){
28992             this.syncAnchor();
28993         }
28994     },
28995
28996     
28997     clearTimer : function(name){
28998         name = name + 'Timer';
28999         clearTimeout(this[name]);
29000         delete this[name];
29001     },
29002
29003     
29004     clearTimers : function(){
29005         this.clearTimer('show');
29006         this.clearTimer('dismiss');
29007         this.clearTimer('hide');
29008     },
29009
29010     
29011     onShow : function(){
29012         Ext.ToolTip.superclass.onShow.call(this);
29013         Ext.getDoc().on('mousedown', this.onDocMouseDown, this);
29014     },
29015
29016     
29017     onHide : function(){
29018         Ext.ToolTip.superclass.onHide.call(this);
29019         Ext.getDoc().un('mousedown', this.onDocMouseDown, this);
29020     },
29021
29022     
29023     onDocMouseDown : function(e){
29024         if(this.autoHide !== true && !this.closable && !e.within(this.el.dom)){
29025             this.disable();
29026             this.enable.defer(100, this);
29027         }
29028     },
29029
29030     
29031     onDisable : function(){
29032         this.clearTimers();
29033         this.hide();
29034     },
29035
29036     
29037     adjustPosition : function(x, y){
29038         if(this.contstrainPosition){
29039             var ay = this.targetXY[1], h = this.getSize().height;
29040             if(y <= ay && (y+h) >= ay){
29041                 y = ay-h-5;
29042             }
29043         }
29044         return {x : x, y: y};
29045     },
29046     
29047     beforeDestroy : function(){
29048         this.clearTimers();
29049         Ext.destroy(this.anchorEl);
29050         delete this.anchorEl;
29051         delete this.target;
29052         delete this.anchorTarget;
29053         delete this.triggerElement;
29054         Ext.ToolTip.superclass.beforeDestroy.call(this);    
29055     },
29056
29057     
29058     onDestroy : function(){
29059         Ext.getDoc().un('mousedown', this.onDocMouseDown, this);
29060         Ext.ToolTip.superclass.onDestroy.call(this);
29061     }
29062 });
29063
29064 Ext.reg('tooltip', Ext.ToolTip);
29065 Ext.QuickTip = Ext.extend(Ext.ToolTip, {
29066     
29067     
29068     interceptTitles : false,
29069
29070     
29071     tagConfig : {
29072         namespace : "ext",
29073         attribute : "qtip",
29074         width : "qwidth",
29075         target : "target",
29076         title : "qtitle",
29077         hide : "hide",
29078         cls : "qclass",
29079         align : "qalign",
29080         anchor : "anchor"
29081     },
29082
29083     
29084     initComponent : function(){
29085         this.target = this.target || Ext.getDoc();
29086         this.targets = this.targets || {};
29087         Ext.QuickTip.superclass.initComponent.call(this);
29088     },
29089
29090     
29091     register : function(config){
29092         var cs = Ext.isArray(config) ? config : arguments;
29093         for(var i = 0, len = cs.length; i < len; i++){
29094             var c = cs[i];
29095             var target = c.target;
29096             if(target){
29097                 if(Ext.isArray(target)){
29098                     for(var j = 0, jlen = target.length; j < jlen; j++){
29099                         this.targets[Ext.id(target[j])] = c;
29100                     }
29101                 } else{
29102                     this.targets[Ext.id(target)] = c;
29103                 }
29104             }
29105         }
29106     },
29107
29108     
29109     unregister : function(el){
29110         delete this.targets[Ext.id(el)];
29111     },
29112     
29113     
29114     cancelShow: function(el){
29115         var at = this.activeTarget;
29116         el = Ext.get(el).dom;
29117         if(this.isVisible()){
29118             if(at && at.el == el){
29119                 this.hide();
29120             }
29121         }else if(at && at.el == el){
29122             this.clearTimer('show');
29123         }
29124     },
29125     
29126     getTipCfg: function(e) {
29127         var t = e.getTarget(), 
29128             ttp, 
29129             cfg;
29130         if(this.interceptTitles && t.title && Ext.isString(t.title)){
29131             ttp = t.title;
29132             t.qtip = ttp;
29133             t.removeAttribute("title");
29134             e.preventDefault();
29135         }else{
29136             cfg = this.tagConfig;
29137             ttp = t.qtip || Ext.fly(t).getAttribute(cfg.attribute, cfg.namespace);
29138         }
29139         return ttp;
29140     },
29141
29142     
29143     onTargetOver : function(e){
29144         if(this.disabled){
29145             return;
29146         }
29147         this.targetXY = e.getXY();
29148         var t = e.getTarget();
29149         if(!t || t.nodeType !== 1 || t == document || t == document.body){
29150             return;
29151         }
29152         if(this.activeTarget && ((t == this.activeTarget.el) || Ext.fly(this.activeTarget.el).contains(t))){
29153             this.clearTimer('hide');
29154             this.show();
29155             return;
29156         }
29157         if(t && this.targets[t.id]){
29158             this.activeTarget = this.targets[t.id];
29159             this.activeTarget.el = t;
29160             this.anchor = this.activeTarget.anchor;
29161             if(this.anchor){
29162                 this.anchorTarget = t;
29163             }
29164             this.delayShow();
29165             return;
29166         }
29167         var ttp, et = Ext.fly(t), cfg = this.tagConfig, ns = cfg.namespace;
29168         if(ttp = this.getTipCfg(e)){
29169             var autoHide = et.getAttribute(cfg.hide, ns);
29170             this.activeTarget = {
29171                 el: t,
29172                 text: ttp,
29173                 width: et.getAttribute(cfg.width, ns),
29174                 autoHide: autoHide != "user" && autoHide !== 'false',
29175                 title: et.getAttribute(cfg.title, ns),
29176                 cls: et.getAttribute(cfg.cls, ns),
29177                 align: et.getAttribute(cfg.align, ns)
29178                 
29179             };
29180             this.anchor = et.getAttribute(cfg.anchor, ns);
29181             if(this.anchor){
29182                 this.anchorTarget = t;
29183             }
29184             this.delayShow();
29185         }
29186     },
29187
29188     
29189     onTargetOut : function(e){
29190
29191         
29192         if (this.activeTarget && e.within(this.activeTarget.el) && !this.getTipCfg(e)) {
29193             return;
29194         }
29195
29196         this.clearTimer('show');
29197         if(this.autoHide !== false){
29198             this.delayHide();
29199         }
29200     },
29201
29202     
29203     showAt : function(xy){
29204         var t = this.activeTarget;
29205         if(t){
29206             if(!this.rendered){
29207                 this.render(Ext.getBody());
29208                 this.activeTarget = t;
29209             }
29210             if(t.width){
29211                 this.setWidth(t.width);
29212                 this.body.setWidth(this.adjustBodyWidth(t.width - this.getFrameWidth()));
29213                 this.measureWidth = false;
29214             } else{
29215                 this.measureWidth = true;
29216             }
29217             this.setTitle(t.title || '');
29218             this.body.update(t.text);
29219             this.autoHide = t.autoHide;
29220             this.dismissDelay = t.dismissDelay || this.dismissDelay;
29221             if(this.lastCls){
29222                 this.el.removeClass(this.lastCls);
29223                 delete this.lastCls;
29224             }
29225             if(t.cls){
29226                 this.el.addClass(t.cls);
29227                 this.lastCls = t.cls;
29228             }
29229             if(this.anchor){
29230                 this.constrainPosition = false;
29231             }else if(t.align){ 
29232                 xy = this.el.getAlignToXY(t.el, t.align);
29233                 this.constrainPosition = false;
29234             }else{
29235                 this.constrainPosition = true;
29236             }
29237         }
29238         Ext.QuickTip.superclass.showAt.call(this, xy);
29239     },
29240
29241     
29242     hide: function(){
29243         delete this.activeTarget;
29244         Ext.QuickTip.superclass.hide.call(this);
29245     }
29246 });
29247 Ext.reg('quicktip', Ext.QuickTip);
29248 Ext.QuickTips = function(){
29249     var tip, locks = [];
29250     return {
29251         
29252         init : function(autoRender){
29253             if(!tip){
29254                 if(!Ext.isReady){
29255                     Ext.onReady(function(){
29256                         Ext.QuickTips.init(autoRender);
29257                     });
29258                     return;
29259                 }
29260                 tip = new Ext.QuickTip({elements:'header,body'});
29261                 if(autoRender !== false){
29262                     tip.render(Ext.getBody());
29263                 }
29264             }
29265         },
29266
29267         
29268         enable : function(){
29269             if(tip){
29270                 locks.pop();
29271                 if(locks.length < 1){
29272                     tip.enable();
29273                 }
29274             }
29275         },
29276
29277         
29278         disable : function(){
29279             if(tip){
29280                 tip.disable();
29281             }
29282             locks.push(1);
29283         },
29284
29285         
29286         isEnabled : function(){
29287             return tip !== undefined && !tip.disabled;
29288         },
29289
29290         
29291         getQuickTip : function(){
29292             return tip;
29293         },
29294
29295         
29296         register : function(){
29297             tip.register.apply(tip, arguments);
29298         },
29299
29300         
29301         unregister : function(){
29302             tip.unregister.apply(tip, arguments);
29303         },
29304
29305         
29306         tips :function(){
29307             tip.register.apply(tip, arguments);
29308         }
29309     }
29310 }();
29311 Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
29312     rootVisible : true,
29313     animate : Ext.enableFx,
29314     lines : true,
29315     enableDD : false,
29316     hlDrop : Ext.enableFx,
29317     pathSeparator : '/',
29318
29319     
29320     bubbleEvents : [],
29321
29322     initComponent : function(){
29323         Ext.tree.TreePanel.superclass.initComponent.call(this);
29324
29325         if(!this.eventModel){
29326             this.eventModel = new Ext.tree.TreeEventModel(this);
29327         }
29328
29329         
29330         var l = this.loader;
29331         if(!l){
29332             l = new Ext.tree.TreeLoader({
29333                 dataUrl: this.dataUrl,
29334                 requestMethod: this.requestMethod
29335             });
29336         }else if(Ext.isObject(l) && !l.load){
29337             l = new Ext.tree.TreeLoader(l);
29338         }
29339         this.loader = l;
29340
29341         this.nodeHash = {};
29342
29343         
29344         if(this.root){
29345             var r = this.root;
29346             delete this.root;
29347             this.setRootNode(r);
29348         }
29349
29350
29351         this.addEvents(
29352
29353             
29354            'append',
29355            
29356            'remove',
29357            
29358            'movenode',
29359            
29360            'insert',
29361            
29362            'beforeappend',
29363            
29364            'beforeremove',
29365            
29366            'beforemovenode',
29367            
29368             'beforeinsert',
29369
29370             
29371             'beforeload',
29372             
29373             'load',
29374             
29375             'textchange',
29376             
29377             'beforeexpandnode',
29378             
29379             'beforecollapsenode',
29380             
29381             'expandnode',
29382             
29383             'disabledchange',
29384             
29385             'collapsenode',
29386             
29387             'beforeclick',
29388             
29389             'click',
29390             
29391             'containerclick',
29392             
29393             'checkchange',
29394             
29395             'beforedblclick',
29396             
29397             'dblclick',
29398             
29399             'containerdblclick',
29400             
29401             'contextmenu',
29402             
29403             'containercontextmenu',
29404             
29405             'beforechildrenrendered',
29406            
29407             'startdrag',
29408             
29409             'enddrag',
29410             
29411             'dragdrop',
29412             
29413             'beforenodedrop',
29414             
29415             'nodedrop',
29416              
29417             'nodedragover'
29418         );
29419         if(this.singleExpand){
29420             this.on('beforeexpandnode', this.restrictExpand, this);
29421         }
29422     },
29423
29424     
29425     proxyNodeEvent : function(ename, a1, a2, a3, a4, a5, a6){
29426         if(ename == 'collapse' || ename == 'expand' || ename == 'beforecollapse' || ename == 'beforeexpand' || ename == 'move' || ename == 'beforemove'){
29427             ename = ename+'node';
29428         }
29429         
29430         return this.fireEvent(ename, a1, a2, a3, a4, a5, a6);
29431     },
29432
29433
29434     
29435     getRootNode : function(){
29436         return this.root;
29437     },
29438
29439     
29440     setRootNode : function(node){
29441         Ext.destroy(this.root);
29442         if(!node.render){ 
29443             node = this.loader.createNode(node);
29444         }
29445         this.root = node;
29446         node.ownerTree = this;
29447         node.isRoot = true;
29448         this.registerNode(node);
29449         if(!this.rootVisible){
29450             var uiP = node.attributes.uiProvider;
29451             node.ui = uiP ? new uiP(node) : new Ext.tree.RootTreeNodeUI(node);
29452         }
29453         if (this.innerCt) {
29454             this.innerCt.update('');
29455             this.afterRender();
29456         }
29457         return node;
29458     },
29459
29460     
29461     getNodeById : function(id){
29462         return this.nodeHash[id];
29463     },
29464
29465     
29466     registerNode : function(node){
29467         this.nodeHash[node.id] = node;
29468     },
29469
29470     
29471     unregisterNode : function(node){
29472         delete this.nodeHash[node.id];
29473     },
29474
29475     
29476     toString : function(){
29477         return '[Tree'+(this.id?' '+this.id:'')+']';
29478     },
29479
29480     
29481     restrictExpand : function(node){
29482         var p = node.parentNode;
29483         if(p){
29484             if(p.expandedChild && p.expandedChild.parentNode == p){
29485                 p.expandedChild.collapse();
29486             }
29487             p.expandedChild = node;
29488         }
29489     },
29490
29491     
29492     getChecked : function(a, startNode){
29493         startNode = startNode || this.root;
29494         var r = [];
29495         var f = function(){
29496             if(this.attributes.checked){
29497                 r.push(!a ? this : (a == 'id' ? this.id : this.attributes[a]));
29498             }
29499         };
29500         startNode.cascade(f);
29501         return r;
29502     },
29503
29504     
29505     getLoader : function(){
29506         return this.loader;
29507     },
29508
29509     
29510     expandAll : function(){
29511         this.root.expand(true);
29512     },
29513
29514     
29515     collapseAll : function(){
29516         this.root.collapse(true);
29517     },
29518
29519     
29520     getSelectionModel : function(){
29521         if(!this.selModel){
29522             this.selModel = new Ext.tree.DefaultSelectionModel();
29523         }
29524         return this.selModel;
29525     },
29526
29527     
29528     expandPath : function(path, attr, callback){
29529         attr = attr || 'id';
29530         var keys = path.split(this.pathSeparator);
29531         var curNode = this.root;
29532         if(curNode.attributes[attr] != keys[1]){ 
29533             if(callback){
29534                 callback(false, null);
29535             }
29536             return;
29537         }
29538         var index = 1;
29539         var f = function(){
29540             if(++index == keys.length){
29541                 if(callback){
29542                     callback(true, curNode);
29543                 }
29544                 return;
29545             }
29546             var c = curNode.findChild(attr, keys[index]);
29547             if(!c){
29548                 if(callback){
29549                     callback(false, curNode);
29550                 }
29551                 return;
29552             }
29553             curNode = c;
29554             c.expand(false, false, f);
29555         };
29556         curNode.expand(false, false, f);
29557     },
29558
29559     
29560     selectPath : function(path, attr, callback){
29561         attr = attr || 'id';
29562         var keys = path.split(this.pathSeparator),
29563             v = keys.pop();
29564         if(keys.length > 1){
29565             var f = function(success, node){
29566                 if(success && node){
29567                     var n = node.findChild(attr, v);
29568                     if(n){
29569                         n.select();
29570                         if(callback){
29571                             callback(true, n);
29572                         }
29573                     }else if(callback){
29574                         callback(false, n);
29575                     }
29576                 }else{
29577                     if(callback){
29578                         callback(false, n);
29579                     }
29580                 }
29581             };
29582             this.expandPath(keys.join(this.pathSeparator), attr, f);
29583         }else{
29584             this.root.select();
29585             if(callback){
29586                 callback(true, this.root);
29587             }
29588         }
29589     },
29590
29591     
29592     getTreeEl : function(){
29593         return this.body;
29594     },
29595
29596     
29597     onRender : function(ct, position){
29598         Ext.tree.TreePanel.superclass.onRender.call(this, ct, position);
29599         this.el.addClass('x-tree');
29600         this.innerCt = this.body.createChild({tag:'ul',
29601                cls:'x-tree-root-ct ' +
29602                (this.useArrows ? 'x-tree-arrows' : this.lines ? 'x-tree-lines' : 'x-tree-no-lines')});
29603     },
29604
29605     
29606     initEvents : function(){
29607         Ext.tree.TreePanel.superclass.initEvents.call(this);
29608
29609         if(this.containerScroll){
29610             Ext.dd.ScrollManager.register(this.body);
29611         }
29612         if((this.enableDD || this.enableDrop) && !this.dropZone){
29613            
29614              this.dropZone = new Ext.tree.TreeDropZone(this, this.dropConfig || {
29615                ddGroup: this.ddGroup || 'TreeDD', appendOnly: this.ddAppendOnly === true
29616            });
29617         }
29618         if((this.enableDD || this.enableDrag) && !this.dragZone){
29619            
29620             this.dragZone = new Ext.tree.TreeDragZone(this, this.dragConfig || {
29621                ddGroup: this.ddGroup || 'TreeDD',
29622                scroll: this.ddScroll
29623            });
29624         }
29625         this.getSelectionModel().init(this);
29626     },
29627
29628     
29629     afterRender : function(){
29630         Ext.tree.TreePanel.superclass.afterRender.call(this);
29631         this.root.render();
29632         if(!this.rootVisible){
29633             this.root.renderChildren();
29634         }
29635     },
29636
29637     beforeDestroy : function(){
29638         if(this.rendered){
29639             Ext.dd.ScrollManager.unregister(this.body);
29640             Ext.destroy(this.dropZone, this.dragZone);
29641         }
29642         Ext.destroy(this.root, this.loader);
29643         this.nodeHash = this.root = this.loader = null;
29644         Ext.tree.TreePanel.superclass.beforeDestroy.call(this);
29645     }
29646
29647     
29648     
29649     
29650     
29651     
29652     
29653     
29654     
29655     
29656     
29657     
29658     
29659     
29660     
29661     
29662     
29663     
29664     
29665     
29666     
29667     
29668     
29669     
29670     
29671     
29672     
29673     
29674     
29675     
29676     
29677     
29678
29679
29680
29681     
29682     
29683     
29684     
29685     
29686     
29687     
29688     
29689     
29690     
29691     
29692     
29693     
29694 });
29695
29696 Ext.tree.TreePanel.nodeTypes = {};
29697
29698 Ext.reg('treepanel', Ext.tree.TreePanel);Ext.tree.TreeEventModel = function(tree){
29699     this.tree = tree;
29700     this.tree.on('render', this.initEvents, this);
29701 }
29702
29703 Ext.tree.TreeEventModel.prototype = {
29704     initEvents : function(){
29705         var t = this.tree;
29706             
29707         if(t.trackMouseOver !== false){
29708             t.mon(t.innerCt, {
29709                 scope: this,
29710                 mouseover: this.delegateOver,
29711                 mouseout: this.delegateOut
29712             });
29713         }
29714         t.mon(t.getTreeEl(), {
29715             scope: this,
29716             click: this.delegateClick,
29717             dblclick: this.delegateDblClick,
29718             contextmenu: this.delegateContextMenu
29719         });
29720     },
29721
29722     getNode : function(e){
29723         var t;
29724         if(t = e.getTarget('.x-tree-node-el', 10)){
29725             var id = Ext.fly(t, '_treeEvents').getAttribute('tree-node-id', 'ext');
29726             if(id){
29727                 return this.tree.getNodeById(id);
29728             }
29729         }
29730         return null;
29731     },
29732
29733     getNodeTarget : function(e){
29734         var t = e.getTarget('.x-tree-node-icon', 1);
29735         if(!t){
29736             t = e.getTarget('.x-tree-node-el', 6);
29737         }
29738         return t;
29739     },
29740
29741     delegateOut : function(e, t){
29742         if(!this.beforeEvent(e)){
29743             return;
29744         }
29745         if(e.getTarget('.x-tree-ec-icon', 1)){
29746             var n = this.getNode(e);
29747             this.onIconOut(e, n);
29748             if(n == this.lastEcOver){
29749                 delete this.lastEcOver;
29750             }
29751         }
29752         if((t = this.getNodeTarget(e)) && !e.within(t, true)){
29753             this.onNodeOut(e, this.getNode(e));
29754         }
29755     },
29756
29757     delegateOver : function(e, t){
29758         if(!this.beforeEvent(e)){
29759             return;
29760         }
29761         if(Ext.isGecko && !this.trackingDoc){ 
29762             Ext.getBody().on('mouseover', this.trackExit, this);
29763             this.trackingDoc = true;
29764         }
29765         if(this.lastEcOver){ 
29766             this.onIconOut(e, this.lastEcOver);
29767             delete this.lastEcOver;
29768         }
29769         if(e.getTarget('.x-tree-ec-icon', 1)){
29770             this.lastEcOver = this.getNode(e);
29771             this.onIconOver(e, this.lastEcOver);
29772         }
29773         if(t = this.getNodeTarget(e)){
29774             this.onNodeOver(e, this.getNode(e));
29775         }
29776     },
29777
29778     trackExit : function(e){
29779         if(this.lastOverNode && !e.within(this.lastOverNode.ui.getEl())){
29780             this.onNodeOut(e, this.lastOverNode);
29781             delete this.lastOverNode;
29782             Ext.getBody().un('mouseover', this.trackExit, this);
29783             this.trackingDoc = false;
29784         }
29785     },
29786
29787     delegateClick : function(e, t){
29788         if(this.beforeEvent(e)){
29789             if(e.getTarget('input[type=checkbox]', 1)){
29790                 this.onCheckboxClick(e, this.getNode(e));
29791             }else if(e.getTarget('.x-tree-ec-icon', 1)){
29792                 this.onIconClick(e, this.getNode(e));
29793             }else if(this.getNodeTarget(e)){
29794                 this.onNodeClick(e, this.getNode(e));
29795             }else{
29796                 this.onContainerEvent(e, 'click');
29797             }
29798         }
29799     },
29800
29801     delegateDblClick : function(e, t){
29802         if(this.beforeEvent(e)){
29803             if(this.getNodeTarget(e)){
29804                 this.onNodeDblClick(e, this.getNode(e));
29805             }else{
29806                 this.onContainerEvent(e, 'dblclick');    
29807             }
29808         }
29809     },
29810
29811     delegateContextMenu : function(e, t){
29812         if(this.beforeEvent(e)){
29813             if(this.getNodeTarget(e)){
29814                 this.onNodeContextMenu(e, this.getNode(e));
29815             }else{
29816                 this.onContainerEvent(e, 'contextmenu');    
29817             }
29818         }
29819     },
29820     
29821     onContainerEvent: function(e, type){
29822         this.tree.fireEvent('container' + type, this.tree, e); 
29823     },
29824
29825     onNodeClick : function(e, node){
29826         node.ui.onClick(e);
29827     },
29828
29829     onNodeOver : function(e, node){
29830         this.lastOverNode = node;
29831         node.ui.onOver(e);
29832     },
29833
29834     onNodeOut : function(e, node){
29835         node.ui.onOut(e);
29836     },
29837
29838     onIconOver : function(e, node){
29839         node.ui.addClass('x-tree-ec-over');
29840     },
29841
29842     onIconOut : function(e, node){
29843         node.ui.removeClass('x-tree-ec-over');
29844     },
29845
29846     onIconClick : function(e, node){
29847         node.ui.ecClick(e);
29848     },
29849
29850     onCheckboxClick : function(e, node){
29851         node.ui.onCheckChange(e);
29852     },
29853
29854     onNodeDblClick : function(e, node){
29855         node.ui.onDblClick(e);
29856     },
29857
29858     onNodeContextMenu : function(e, node){
29859         node.ui.onContextMenu(e);
29860     },
29861
29862     beforeEvent : function(e){
29863         if(this.disabled){
29864             e.stopEvent();
29865             return false;
29866         }
29867         return true;
29868     },
29869
29870     disable: function(){
29871         this.disabled = true;
29872     },
29873
29874     enable: function(){
29875         this.disabled = false;
29876     }
29877 };
29878 Ext.tree.DefaultSelectionModel = function(config){
29879    this.selNode = null;
29880    
29881    this.addEvents(
29882        
29883        'selectionchange',
29884
29885        
29886        'beforeselect'
29887    );
29888
29889     Ext.apply(this, config);
29890     Ext.tree.DefaultSelectionModel.superclass.constructor.call(this);
29891 };
29892
29893 Ext.extend(Ext.tree.DefaultSelectionModel, Ext.util.Observable, {
29894     init : function(tree){
29895         this.tree = tree;
29896         tree.mon(tree.getTreeEl(), 'keydown', this.onKeyDown, this);
29897         tree.on('click', this.onNodeClick, this);
29898     },
29899     
29900     onNodeClick : function(node, e){
29901         this.select(node);
29902     },
29903     
29904     
29905     select : function(node,  selectNextNode){
29906         
29907         if (!Ext.fly(node.ui.wrap).isVisible() && selectNextNode) {
29908             return selectNextNode.call(this, node);
29909         }
29910         var last = this.selNode;
29911         if(node == last){
29912             node.ui.onSelectedChange(true);
29913         }else if(this.fireEvent('beforeselect', this, node, last) !== false){
29914             if(last && last.ui){
29915                 last.ui.onSelectedChange(false);
29916             }
29917             this.selNode = node;
29918             node.ui.onSelectedChange(true);
29919             this.fireEvent('selectionchange', this, node, last);
29920         }
29921         return node;
29922     },
29923     
29924     
29925     unselect : function(node, silent){
29926         if(this.selNode == node){
29927             this.clearSelections(silent);
29928         }    
29929     },
29930     
29931     
29932     clearSelections : function(silent){
29933         var n = this.selNode;
29934         if(n){
29935             n.ui.onSelectedChange(false);
29936             this.selNode = null;
29937             if(silent !== true){
29938                 this.fireEvent('selectionchange', this, null);
29939             }
29940         }
29941         return n;
29942     },
29943     
29944     
29945     getSelectedNode : function(){
29946         return this.selNode;    
29947     },
29948     
29949     
29950     isSelected : function(node){
29951         return this.selNode == node;  
29952     },
29953
29954     
29955     selectPrevious : function( s){
29956         if(!(s = s || this.selNode || this.lastSelNode)){
29957             return null;
29958         }
29959         
29960         var ps = s.previousSibling;
29961         if(ps){
29962             if(!ps.isExpanded() || ps.childNodes.length < 1){
29963                 return this.select(ps, this.selectPrevious);
29964             } else{
29965                 var lc = ps.lastChild;
29966                 while(lc && lc.isExpanded() && Ext.fly(lc.ui.wrap).isVisible() && lc.childNodes.length > 0){
29967                     lc = lc.lastChild;
29968                 }
29969                 return this.select(lc, this.selectPrevious);
29970             }
29971         } else if(s.parentNode && (this.tree.rootVisible || !s.parentNode.isRoot)){
29972             return this.select(s.parentNode, this.selectPrevious);
29973         }
29974         return null;
29975     },
29976
29977     
29978     selectNext : function( s){
29979         if(!(s = s || this.selNode || this.lastSelNode)){
29980             return null;
29981         }
29982         
29983         if(s.firstChild && s.isExpanded() && Ext.fly(s.ui.wrap).isVisible()){
29984              return this.select(s.firstChild, this.selectNext);
29985          }else if(s.nextSibling){
29986              return this.select(s.nextSibling, this.selectNext);
29987          }else if(s.parentNode){
29988             var newS = null;
29989             s.parentNode.bubble(function(){
29990                 if(this.nextSibling){
29991                     newS = this.getOwnerTree().selModel.select(this.nextSibling, this.selectNext);
29992                     return false;
29993                 }
29994             });
29995             return newS;
29996          }
29997         return null;
29998     },
29999
30000     onKeyDown : function(e){
30001         var s = this.selNode || this.lastSelNode;
30002         
30003         var sm = this;
30004         if(!s){
30005             return;
30006         }
30007         var k = e.getKey();
30008         switch(k){
30009              case e.DOWN:
30010                  e.stopEvent();
30011                  this.selectNext();
30012              break;
30013              case e.UP:
30014                  e.stopEvent();
30015                  this.selectPrevious();
30016              break;
30017              case e.RIGHT:
30018                  e.preventDefault();
30019                  if(s.hasChildNodes()){
30020                      if(!s.isExpanded()){
30021                          s.expand();
30022                      }else if(s.firstChild){
30023                          this.select(s.firstChild, e);
30024                      }
30025                  }
30026              break;
30027              case e.LEFT:
30028                  e.preventDefault();
30029                  if(s.hasChildNodes() && s.isExpanded()){
30030                      s.collapse();
30031                  }else if(s.parentNode && (this.tree.rootVisible || s.parentNode != this.tree.getRootNode())){
30032                      this.select(s.parentNode, e);
30033                  }
30034              break;
30035         };
30036     }
30037 });
30038
30039
30040 Ext.tree.MultiSelectionModel = function(config){
30041    this.selNodes = [];
30042    this.selMap = {};
30043    this.addEvents(
30044        
30045        'selectionchange'
30046    );
30047     Ext.apply(this, config);
30048     Ext.tree.MultiSelectionModel.superclass.constructor.call(this);
30049 };
30050
30051 Ext.extend(Ext.tree.MultiSelectionModel, Ext.util.Observable, {
30052     init : function(tree){
30053         this.tree = tree;
30054         tree.mon(tree.getTreeEl(), 'keydown', this.onKeyDown, this);
30055         tree.on('click', this.onNodeClick, this);
30056     },
30057     
30058     onNodeClick : function(node, e){
30059         if(e.ctrlKey && this.isSelected(node)){
30060             this.unselect(node);
30061         }else{
30062             this.select(node, e, e.ctrlKey);
30063         }
30064     },
30065     
30066     
30067     select : function(node, e, keepExisting){
30068         if(keepExisting !== true){
30069             this.clearSelections(true);
30070         }
30071         if(this.isSelected(node)){
30072             this.lastSelNode = node;
30073             return node;
30074         }
30075         this.selNodes.push(node);
30076         this.selMap[node.id] = node;
30077         this.lastSelNode = node;
30078         node.ui.onSelectedChange(true);
30079         this.fireEvent('selectionchange', this, this.selNodes);
30080         return node;
30081     },
30082     
30083     
30084     unselect : function(node){
30085         if(this.selMap[node.id]){
30086             node.ui.onSelectedChange(false);
30087             var sn = this.selNodes;
30088             var index = sn.indexOf(node);
30089             if(index != -1){
30090                 this.selNodes.splice(index, 1);
30091             }
30092             delete this.selMap[node.id];
30093             this.fireEvent('selectionchange', this, this.selNodes);
30094         }
30095     },
30096     
30097     
30098     clearSelections : function(suppressEvent){
30099         var sn = this.selNodes;
30100         if(sn.length > 0){
30101             for(var i = 0, len = sn.length; i < len; i++){
30102                 sn[i].ui.onSelectedChange(false);
30103             }
30104             this.selNodes = [];
30105             this.selMap = {};
30106             if(suppressEvent !== true){
30107                 this.fireEvent('selectionchange', this, this.selNodes);
30108             }
30109         }
30110     },
30111     
30112     
30113     isSelected : function(node){
30114         return this.selMap[node.id] ? true : false;  
30115     },
30116     
30117     
30118     getSelectedNodes : function(){
30119         return this.selNodes;    
30120     },
30121
30122     onKeyDown : Ext.tree.DefaultSelectionModel.prototype.onKeyDown,
30123
30124     selectNext : Ext.tree.DefaultSelectionModel.prototype.selectNext,
30125
30126     selectPrevious : Ext.tree.DefaultSelectionModel.prototype.selectPrevious
30127 });
30128 Ext.data.Tree = function(root){
30129    this.nodeHash = {};
30130    
30131    this.root = null;
30132    if(root){
30133        this.setRootNode(root);
30134    }
30135    this.addEvents(
30136        
30137        "append",
30138        
30139        "remove",
30140        
30141        "move",
30142        
30143        "insert",
30144        
30145        "beforeappend",
30146        
30147        "beforeremove",
30148        
30149        "beforemove",
30150        
30151        "beforeinsert"
30152    );
30153
30154     Ext.data.Tree.superclass.constructor.call(this);
30155 };
30156
30157 Ext.extend(Ext.data.Tree, Ext.util.Observable, {
30158     
30159     pathSeparator: "/",
30160
30161     
30162     proxyNodeEvent : function(){
30163         return this.fireEvent.apply(this, arguments);
30164     },
30165
30166     
30167     getRootNode : function(){
30168         return this.root;
30169     },
30170
30171     
30172     setRootNode : function(node){
30173         this.root = node;
30174         node.ownerTree = this;
30175         node.isRoot = true;
30176         this.registerNode(node);
30177         return node;
30178     },
30179
30180     
30181     getNodeById : function(id){
30182         return this.nodeHash[id];
30183     },
30184
30185     
30186     registerNode : function(node){
30187         this.nodeHash[node.id] = node;
30188     },
30189
30190     
30191     unregisterNode : function(node){
30192         delete this.nodeHash[node.id];
30193     },
30194
30195     toString : function(){
30196         return "[Tree"+(this.id?" "+this.id:"")+"]";
30197     }
30198 });
30199
30200
30201 Ext.data.Node = function(attributes){
30202     
30203     this.attributes = attributes || {};
30204     this.leaf = this.attributes.leaf;
30205     
30206     this.id = this.attributes.id;
30207     if(!this.id){
30208         this.id = Ext.id(null, "xnode-");
30209         this.attributes.id = this.id;
30210     }
30211     
30212     this.childNodes = [];
30213     if(!this.childNodes.indexOf){ 
30214         this.childNodes.indexOf = function(o){
30215             for(var i = 0, len = this.length; i < len; i++){
30216                 if(this[i] == o){
30217                     return i;
30218                 }
30219             }
30220             return -1;
30221         };
30222     }
30223     
30224     this.parentNode = null;
30225     
30226     this.firstChild = null;
30227     
30228     this.lastChild = null;
30229     
30230     this.previousSibling = null;
30231     
30232     this.nextSibling = null;
30233
30234     this.addEvents({
30235        
30236        "append" : true,
30237        
30238        "remove" : true,
30239        
30240        "move" : true,
30241        
30242        "insert" : true,
30243        
30244        "beforeappend" : true,
30245        
30246        "beforeremove" : true,
30247        
30248        "beforemove" : true,
30249        
30250        "beforeinsert" : true
30251    });
30252     this.listeners = this.attributes.listeners;
30253     Ext.data.Node.superclass.constructor.call(this);
30254 };
30255
30256 Ext.extend(Ext.data.Node, Ext.util.Observable, {
30257     
30258     fireEvent : function(evtName){
30259         
30260         if(Ext.data.Node.superclass.fireEvent.apply(this, arguments) === false){
30261             return false;
30262         }
30263         
30264         var ot = this.getOwnerTree();
30265         if(ot){
30266             if(ot.proxyNodeEvent.apply(ot, arguments) === false){
30267                 return false;
30268             }
30269         }
30270         return true;
30271     },
30272
30273     
30274     isLeaf : function(){
30275         return this.leaf === true;
30276     },
30277
30278     
30279     setFirstChild : function(node){
30280         this.firstChild = node;
30281     },
30282
30283     
30284     setLastChild : function(node){
30285         this.lastChild = node;
30286     },
30287
30288
30289     
30290     isLast : function(){
30291        return (!this.parentNode ? true : this.parentNode.lastChild == this);
30292     },
30293
30294     
30295     isFirst : function(){
30296        return (!this.parentNode ? true : this.parentNode.firstChild == this);
30297     },
30298
30299     
30300     hasChildNodes : function(){
30301         return !this.isLeaf() && this.childNodes.length > 0;
30302     },
30303     
30304     
30305     isExpandable : function(){
30306         return this.attributes.expandable || this.hasChildNodes();
30307     },
30308
30309     
30310     appendChild : function(node){
30311         var multi = false;
30312         if(Ext.isArray(node)){
30313             multi = node;
30314         }else if(arguments.length > 1){
30315             multi = arguments;
30316         }
30317         
30318         if(multi){
30319             for(var i = 0, len = multi.length; i < len; i++) {
30320                 this.appendChild(multi[i]);
30321             }
30322         }else{
30323             if(this.fireEvent("beforeappend", this.ownerTree, this, node) === false){
30324                 return false;
30325             }
30326             var index = this.childNodes.length;
30327             var oldParent = node.parentNode;
30328             
30329             if(oldParent){
30330                 if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index) === false){
30331                     return false;
30332                 }
30333                 oldParent.removeChild(node);
30334             }
30335             index = this.childNodes.length;
30336             if(index === 0){
30337                 this.setFirstChild(node);
30338             }
30339             this.childNodes.push(node);
30340             node.parentNode = this;
30341             var ps = this.childNodes[index-1];
30342             if(ps){
30343                 node.previousSibling = ps;
30344                 ps.nextSibling = node;
30345             }else{
30346                 node.previousSibling = null;
30347             }
30348             node.nextSibling = null;
30349             this.setLastChild(node);
30350             node.setOwnerTree(this.getOwnerTree());
30351             this.fireEvent("append", this.ownerTree, this, node, index);
30352             if(oldParent){
30353                 node.fireEvent("move", this.ownerTree, node, oldParent, this, index);
30354             }
30355             return node;
30356         }
30357     },
30358
30359     
30360     removeChild : function(node, destroy){
30361         var index = this.childNodes.indexOf(node);
30362         if(index == -1){
30363             return false;
30364         }
30365         if(this.fireEvent("beforeremove", this.ownerTree, this, node) === false){
30366             return false;
30367         }
30368
30369         
30370         this.childNodes.splice(index, 1);
30371
30372         
30373         if(node.previousSibling){
30374             node.previousSibling.nextSibling = node.nextSibling;
30375         }
30376         if(node.nextSibling){
30377             node.nextSibling.previousSibling = node.previousSibling;
30378         }
30379
30380         
30381         if(this.firstChild == node){
30382             this.setFirstChild(node.nextSibling);
30383         }
30384         if(this.lastChild == node){
30385             this.setLastChild(node.previousSibling);
30386         }
30387
30388         node.clear();
30389         this.fireEvent("remove", this.ownerTree, this, node);
30390         if(destroy){
30391             node.destroy();
30392         }
30393         return node;
30394     },
30395     
30396     
30397     clear : function(destroy){
30398         
30399         this.setOwnerTree(null, destroy);
30400         this.parentNode = this.previousSibling = this.nextSibling = null
30401         if(destroy){
30402             this.firstChild = this.lastChild = null; 
30403         }
30404     },
30405     
30406     
30407     destroy : function(){
30408         this.purgeListeners();
30409         this.clear(true);  
30410         Ext.each(this.childNodes, function(n){
30411             n.destroy();
30412         });
30413         this.childNodes = null;
30414     },
30415
30416     
30417     insertBefore : function(node, refNode){
30418         if(!refNode){ 
30419             return this.appendChild(node);
30420         }
30421         
30422         if(node == refNode){
30423             return false;
30424         }
30425
30426         if(this.fireEvent("beforeinsert", this.ownerTree, this, node, refNode) === false){
30427             return false;
30428         }
30429         var index = this.childNodes.indexOf(refNode);
30430         var oldParent = node.parentNode;
30431         var refIndex = index;
30432
30433         
30434         if(oldParent == this && this.childNodes.indexOf(node) < index){
30435             refIndex--;
30436         }
30437
30438         
30439         if(oldParent){
30440             if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index, refNode) === false){
30441                 return false;
30442             }
30443             oldParent.removeChild(node);
30444         }
30445         if(refIndex === 0){
30446             this.setFirstChild(node);
30447         }
30448         this.childNodes.splice(refIndex, 0, node);
30449         node.parentNode = this;
30450         var ps = this.childNodes[refIndex-1];
30451         if(ps){
30452             node.previousSibling = ps;
30453             ps.nextSibling = node;
30454         }else{
30455             node.previousSibling = null;
30456         }
30457         node.nextSibling = refNode;
30458         refNode.previousSibling = node;
30459         node.setOwnerTree(this.getOwnerTree());
30460         this.fireEvent("insert", this.ownerTree, this, node, refNode);
30461         if(oldParent){
30462             node.fireEvent("move", this.ownerTree, node, oldParent, this, refIndex, refNode);
30463         }
30464         return node;
30465     },
30466
30467     
30468     remove : function(destroy){
30469         this.parentNode.removeChild(this, destroy);
30470         return this;
30471     },
30472
30473     
30474     item : function(index){
30475         return this.childNodes[index];
30476     },
30477
30478     
30479     replaceChild : function(newChild, oldChild){
30480         var s = oldChild ? oldChild.nextSibling : null;
30481         this.removeChild(oldChild);
30482         this.insertBefore(newChild, s);
30483         return oldChild;
30484     },
30485
30486     
30487     indexOf : function(child){
30488         return this.childNodes.indexOf(child);
30489     },
30490
30491     
30492     getOwnerTree : function(){
30493         
30494         if(!this.ownerTree){
30495             var p = this;
30496             while(p){
30497                 if(p.ownerTree){
30498                     this.ownerTree = p.ownerTree;
30499                     break;
30500                 }
30501                 p = p.parentNode;
30502             }
30503         }
30504         return this.ownerTree;
30505     },
30506
30507     
30508     getDepth : function(){
30509         var depth = 0;
30510         var p = this;
30511         while(p.parentNode){
30512             ++depth;
30513             p = p.parentNode;
30514         }
30515         return depth;
30516     },
30517
30518     
30519     setOwnerTree : function(tree, destroy){
30520         
30521         if(tree != this.ownerTree){
30522             if(this.ownerTree){
30523                 this.ownerTree.unregisterNode(this);
30524             }
30525             this.ownerTree = tree;
30526             
30527             if(destroy !== true){
30528                 Ext.each(this.childNodes, function(n){
30529                     n.setOwnerTree(tree);
30530                 });
30531             }
30532             if(tree){
30533                 tree.registerNode(this);
30534             }
30535         }
30536     },
30537     
30538     
30539     setId: function(id){
30540         if(id !== this.id){
30541             var t = this.ownerTree;
30542             if(t){
30543                 t.unregisterNode(this);
30544             }
30545             this.id = this.attributes.id = id;
30546             if(t){
30547                 t.registerNode(this);
30548             }
30549             this.onIdChange(id);
30550         }
30551     },
30552     
30553     
30554     onIdChange: Ext.emptyFn,
30555
30556     
30557     getPath : function(attr){
30558         attr = attr || "id";
30559         var p = this.parentNode;
30560         var b = [this.attributes[attr]];
30561         while(p){
30562             b.unshift(p.attributes[attr]);
30563             p = p.parentNode;
30564         }
30565         var sep = this.getOwnerTree().pathSeparator;
30566         return sep + b.join(sep);
30567     },
30568
30569     
30570     bubble : function(fn, scope, args){
30571         var p = this;
30572         while(p){
30573             if(fn.apply(scope || p, args || [p]) === false){
30574                 break;
30575             }
30576             p = p.parentNode;
30577         }
30578     },
30579
30580     
30581     cascade : function(fn, scope, args){
30582         if(fn.apply(scope || this, args || [this]) !== false){
30583             var cs = this.childNodes;
30584             for(var i = 0, len = cs.length; i < len; i++) {
30585                 cs[i].cascade(fn, scope, args);
30586             }
30587         }
30588     },
30589
30590     
30591     eachChild : function(fn, scope, args){
30592         var cs = this.childNodes;
30593         for(var i = 0, len = cs.length; i < len; i++) {
30594                 if(fn.apply(scope || this, args || [cs[i]]) === false){
30595                     break;
30596                 }
30597         }
30598     },
30599
30600     
30601     findChild : function(attribute, value){
30602         var cs = this.childNodes;
30603         for(var i = 0, len = cs.length; i < len; i++) {
30604                 if(cs[i].attributes[attribute] == value){
30605                     return cs[i];
30606                 }
30607         }
30608         return null;
30609     },
30610
30611     
30612     findChildBy : function(fn, scope){
30613         var cs = this.childNodes;
30614         for(var i = 0, len = cs.length; i < len; i++) {
30615                 if(fn.call(scope||cs[i], cs[i]) === true){
30616                     return cs[i];
30617                 }
30618         }
30619         return null;
30620     },
30621
30622     
30623     sort : function(fn, scope){
30624         var cs = this.childNodes;
30625         var len = cs.length;
30626         if(len > 0){
30627             var sortFn = scope ? function(){fn.apply(scope, arguments);} : fn;
30628             cs.sort(sortFn);
30629             for(var i = 0; i < len; i++){
30630                 var n = cs[i];
30631                 n.previousSibling = cs[i-1];
30632                 n.nextSibling = cs[i+1];
30633                 if(i === 0){
30634                     this.setFirstChild(n);
30635                 }
30636                 if(i == len-1){
30637                     this.setLastChild(n);
30638                 }
30639             }
30640         }
30641     },
30642
30643     
30644     contains : function(node){
30645         return node.isAncestor(this);
30646     },
30647
30648     
30649     isAncestor : function(node){
30650         var p = this.parentNode;
30651         while(p){
30652             if(p == node){
30653                 return true;
30654             }
30655             p = p.parentNode;
30656         }
30657         return false;
30658     },
30659
30660     toString : function(){
30661         return "[Node"+(this.id?" "+this.id:"")+"]";
30662     }
30663 });
30664 Ext.tree.TreeNode = function(attributes){
30665     attributes = attributes || {};
30666     if(Ext.isString(attributes)){
30667         attributes = {text: attributes};
30668     }
30669     this.childrenRendered = false;
30670     this.rendered = false;
30671     Ext.tree.TreeNode.superclass.constructor.call(this, attributes);
30672     this.expanded = attributes.expanded === true;
30673     this.isTarget = attributes.isTarget !== false;
30674     this.draggable = attributes.draggable !== false && attributes.allowDrag !== false;
30675     this.allowChildren = attributes.allowChildren !== false && attributes.allowDrop !== false;
30676
30677     
30678     this.text = attributes.text;
30679     
30680     this.disabled = attributes.disabled === true;
30681     
30682     this.hidden = attributes.hidden === true;
30683
30684     this.addEvents(
30685         
30686         'textchange',
30687         
30688         'beforeexpand',
30689         
30690         'beforecollapse',
30691         
30692         'expand',
30693         
30694         'disabledchange',
30695         
30696         'collapse',
30697         
30698         'beforeclick',
30699         
30700         'click',
30701         
30702         'checkchange',
30703         
30704         'beforedblclick',
30705         
30706         'dblclick',
30707         
30708         'contextmenu',
30709         
30710         'beforechildrenrendered'
30711     );
30712
30713     var uiClass = this.attributes.uiProvider || this.defaultUI || Ext.tree.TreeNodeUI;
30714
30715     
30716     this.ui = new uiClass(this);
30717 };
30718 Ext.extend(Ext.tree.TreeNode, Ext.data.Node, {
30719     preventHScroll : true,
30720     
30721     isExpanded : function(){
30722         return this.expanded;
30723     },
30724
30725
30726     getUI : function(){
30727         return this.ui;
30728     },
30729
30730     getLoader : function(){
30731         var owner;
30732         return this.loader || ((owner = this.getOwnerTree()) && owner.loader ? owner.loader : (this.loader = new Ext.tree.TreeLoader()));
30733     },
30734
30735     
30736     setFirstChild : function(node){
30737         var of = this.firstChild;
30738         Ext.tree.TreeNode.superclass.setFirstChild.call(this, node);
30739         if(this.childrenRendered && of && node != of){
30740             of.renderIndent(true, true);
30741         }
30742         if(this.rendered){
30743             this.renderIndent(true, true);
30744         }
30745     },
30746
30747     
30748     setLastChild : function(node){
30749         var ol = this.lastChild;
30750         Ext.tree.TreeNode.superclass.setLastChild.call(this, node);
30751         if(this.childrenRendered && ol && node != ol){
30752             ol.renderIndent(true, true);
30753         }
30754         if(this.rendered){
30755             this.renderIndent(true, true);
30756         }
30757     },
30758
30759     
30760     
30761     appendChild : function(n){
30762         if(!n.render && !Ext.isArray(n)){
30763             n = this.getLoader().createNode(n);
30764         }
30765         var node = Ext.tree.TreeNode.superclass.appendChild.call(this, n);
30766         if(node && this.childrenRendered){
30767             node.render();
30768         }
30769         this.ui.updateExpandIcon();
30770         return node;
30771     },
30772
30773     
30774     removeChild : function(node, destroy){
30775         this.ownerTree.getSelectionModel().unselect(node);
30776         Ext.tree.TreeNode.superclass.removeChild.apply(this, arguments);
30777         
30778         if(node.ui.rendered){
30779             node.ui.remove();
30780         }
30781         if(this.childNodes.length < 1){
30782             this.collapse(false, false);
30783         }else{
30784             this.ui.updateExpandIcon();
30785         }
30786         if(!this.firstChild && !this.isHiddenRoot()) {
30787             this.childrenRendered = false;
30788         }
30789         return node;
30790     },
30791
30792     
30793     insertBefore : function(node, refNode){
30794         if(!node.render){
30795             node = this.getLoader().createNode(node);
30796         }
30797         var newNode = Ext.tree.TreeNode.superclass.insertBefore.call(this, node, refNode);
30798         if(newNode && refNode && this.childrenRendered){
30799             node.render();
30800         }
30801         this.ui.updateExpandIcon();
30802         return newNode;
30803     },
30804
30805     
30806     setText : function(text){
30807         var oldText = this.text;
30808         this.text = this.attributes.text = text;
30809         if(this.rendered){ 
30810             this.ui.onTextChange(this, text, oldText);
30811         }
30812         this.fireEvent('textchange', this, text, oldText);
30813     },
30814
30815     
30816     select : function(){
30817         var t = this.getOwnerTree();
30818         if(t){
30819             t.getSelectionModel().select(this);
30820         }
30821     },
30822
30823     
30824     unselect : function(silent){
30825         var t = this.getOwnerTree();
30826         if(t){
30827             t.getSelectionModel().unselect(this, silent);
30828         }
30829     },
30830
30831     
30832     isSelected : function(){
30833         var t = this.getOwnerTree();
30834         return t ? t.getSelectionModel().isSelected(this) : false;
30835     },
30836
30837     
30838     expand : function(deep, anim, callback, scope){
30839         if(!this.expanded){
30840             if(this.fireEvent('beforeexpand', this, deep, anim) === false){
30841                 return;
30842             }
30843             if(!this.childrenRendered){
30844                 this.renderChildren();
30845             }
30846             this.expanded = true;
30847             if(!this.isHiddenRoot() && (this.getOwnerTree().animate && anim !== false) || anim){
30848                 this.ui.animExpand(function(){
30849                     this.fireEvent('expand', this);
30850                     this.runCallback(callback, scope || this, [this]);
30851                     if(deep === true){
30852                         this.expandChildNodes(true);
30853                     }
30854                 }.createDelegate(this));
30855                 return;
30856             }else{
30857                 this.ui.expand();
30858                 this.fireEvent('expand', this);
30859                 this.runCallback(callback, scope || this, [this]);
30860             }
30861         }else{
30862            this.runCallback(callback, scope || this, [this]);
30863         }
30864         if(deep === true){
30865             this.expandChildNodes(true);
30866         }
30867     },
30868
30869     runCallback : function(cb, scope, args){
30870         if(Ext.isFunction(cb)){
30871             cb.apply(scope, args);
30872         }
30873     },
30874
30875     isHiddenRoot : function(){
30876         return this.isRoot && !this.getOwnerTree().rootVisible;
30877     },
30878
30879     
30880     collapse : function(deep, anim, callback, scope){
30881         if(this.expanded && !this.isHiddenRoot()){
30882             if(this.fireEvent('beforecollapse', this, deep, anim) === false){
30883                 return;
30884             }
30885             this.expanded = false;
30886             if((this.getOwnerTree().animate && anim !== false) || anim){
30887                 this.ui.animCollapse(function(){
30888                     this.fireEvent('collapse', this);
30889                     this.runCallback(callback, scope || this, [this]);
30890                     if(deep === true){
30891                         this.collapseChildNodes(true);
30892                     }
30893                 }.createDelegate(this));
30894                 return;
30895             }else{
30896                 this.ui.collapse();
30897                 this.fireEvent('collapse', this);
30898                 this.runCallback(callback, scope || this, [this]);
30899             }
30900         }else if(!this.expanded){
30901             this.runCallback(callback, scope || this, [this]);
30902         }
30903         if(deep === true){
30904             var cs = this.childNodes;
30905             for(var i = 0, len = cs.length; i < len; i++) {
30906                 cs[i].collapse(true, false);
30907             }
30908         }
30909     },
30910
30911     
30912     delayedExpand : function(delay){
30913         if(!this.expandProcId){
30914             this.expandProcId = this.expand.defer(delay, this);
30915         }
30916     },
30917
30918     
30919     cancelExpand : function(){
30920         if(this.expandProcId){
30921             clearTimeout(this.expandProcId);
30922         }
30923         this.expandProcId = false;
30924     },
30925
30926     
30927     toggle : function(){
30928         if(this.expanded){
30929             this.collapse();
30930         }else{
30931             this.expand();
30932         }
30933     },
30934
30935     
30936     ensureVisible : function(callback, scope){
30937         var tree = this.getOwnerTree();
30938         tree.expandPath(this.parentNode ? this.parentNode.getPath() : this.getPath(), false, function(){
30939             var node = tree.getNodeById(this.id);  
30940             tree.getTreeEl().scrollChildIntoView(node.ui.anchor);
30941             this.runCallback(callback, scope || this, [this]);
30942         }.createDelegate(this));
30943     },
30944
30945     
30946     expandChildNodes : function(deep){
30947         var cs = this.childNodes;
30948         for(var i = 0, len = cs.length; i < len; i++) {
30949                 cs[i].expand(deep);
30950         }
30951     },
30952
30953     
30954     collapseChildNodes : function(deep){
30955         var cs = this.childNodes;
30956         for(var i = 0, len = cs.length; i < len; i++) {
30957                 cs[i].collapse(deep);
30958         }
30959     },
30960
30961     
30962     disable : function(){
30963         this.disabled = true;
30964         this.unselect();
30965         if(this.rendered && this.ui.onDisableChange){ 
30966             this.ui.onDisableChange(this, true);
30967         }
30968         this.fireEvent('disabledchange', this, true);
30969     },
30970
30971     
30972     enable : function(){
30973         this.disabled = false;
30974         if(this.rendered && this.ui.onDisableChange){ 
30975             this.ui.onDisableChange(this, false);
30976         }
30977         this.fireEvent('disabledchange', this, false);
30978     },
30979
30980     
30981     renderChildren : function(suppressEvent){
30982         if(suppressEvent !== false){
30983             this.fireEvent('beforechildrenrendered', this);
30984         }
30985         var cs = this.childNodes;
30986         for(var i = 0, len = cs.length; i < len; i++){
30987             cs[i].render(true);
30988         }
30989         this.childrenRendered = true;
30990     },
30991
30992     
30993     sort : function(fn, scope){
30994         Ext.tree.TreeNode.superclass.sort.apply(this, arguments);
30995         if(this.childrenRendered){
30996             var cs = this.childNodes;
30997             for(var i = 0, len = cs.length; i < len; i++){
30998                 cs[i].render(true);
30999             }
31000         }
31001     },
31002
31003     
31004     render : function(bulkRender){
31005         this.ui.render(bulkRender);
31006         if(!this.rendered){
31007             
31008             this.getOwnerTree().registerNode(this);
31009             this.rendered = true;
31010             if(this.expanded){
31011                 this.expanded = false;
31012                 this.expand(false, false);
31013             }
31014         }
31015     },
31016
31017     
31018     renderIndent : function(deep, refresh){
31019         if(refresh){
31020             this.ui.childIndent = null;
31021         }
31022         this.ui.renderIndent();
31023         if(deep === true && this.childrenRendered){
31024             var cs = this.childNodes;
31025             for(var i = 0, len = cs.length; i < len; i++){
31026                 cs[i].renderIndent(true, refresh);
31027             }
31028         }
31029     },
31030
31031     beginUpdate : function(){
31032         this.childrenRendered = false;
31033     },
31034
31035     endUpdate : function(){
31036         if(this.expanded && this.rendered){
31037             this.renderChildren();
31038         }
31039     },
31040
31041     destroy : function(){
31042         this.unselect(true);
31043         Ext.tree.TreeNode.superclass.destroy.call(this);
31044         Ext.destroy(this.ui, this.loader);
31045         this.ui = this.loader = null;
31046     },
31047
31048     
31049     onIdChange : function(id){
31050         this.ui.onIdChange(id);
31051     }
31052 });
31053
31054 Ext.tree.TreePanel.nodeTypes.node = Ext.tree.TreeNode;
31055  Ext.tree.AsyncTreeNode = function(config){
31056     this.loaded = config && config.loaded === true;
31057     this.loading = false;
31058     Ext.tree.AsyncTreeNode.superclass.constructor.apply(this, arguments);
31059     
31060     this.addEvents('beforeload', 'load');
31061     
31062     
31063 };
31064 Ext.extend(Ext.tree.AsyncTreeNode, Ext.tree.TreeNode, {
31065     expand : function(deep, anim, callback, scope){
31066         if(this.loading){ 
31067             var timer;
31068             var f = function(){
31069                 if(!this.loading){ 
31070                     clearInterval(timer);
31071                     this.expand(deep, anim, callback, scope);
31072                 }
31073             }.createDelegate(this);
31074             timer = setInterval(f, 200);
31075             return;
31076         }
31077         if(!this.loaded){
31078             if(this.fireEvent("beforeload", this) === false){
31079                 return;
31080             }
31081             this.loading = true;
31082             this.ui.beforeLoad(this);
31083             var loader = this.loader || this.attributes.loader || this.getOwnerTree().getLoader();
31084             if(loader){
31085                 loader.load(this, this.loadComplete.createDelegate(this, [deep, anim, callback, scope]), this);
31086                 return;
31087             }
31088         }
31089         Ext.tree.AsyncTreeNode.superclass.expand.call(this, deep, anim, callback, scope);
31090     },
31091     
31092     
31093     isLoading : function(){
31094         return this.loading;  
31095     },
31096     
31097     loadComplete : function(deep, anim, callback, scope){
31098         this.loading = false;
31099         this.loaded = true;
31100         this.ui.afterLoad(this);
31101         this.fireEvent("load", this);
31102         this.expand(deep, anim, callback, scope);
31103     },
31104     
31105     
31106     isLoaded : function(){
31107         return this.loaded;
31108     },
31109     
31110     hasChildNodes : function(){
31111         if(!this.isLeaf() && !this.loaded){
31112             return true;
31113         }else{
31114             return Ext.tree.AsyncTreeNode.superclass.hasChildNodes.call(this);
31115         }
31116     },
31117
31118     
31119     reload : function(callback, scope){
31120         this.collapse(false, false);
31121         while(this.firstChild){
31122             this.removeChild(this.firstChild).destroy();
31123         }
31124         this.childrenRendered = false;
31125         this.loaded = false;
31126         if(this.isHiddenRoot()){
31127             this.expanded = false;
31128         }
31129         this.expand(false, false, callback, scope);
31130     }
31131 });
31132
31133 Ext.tree.TreePanel.nodeTypes.async = Ext.tree.AsyncTreeNode;
31134 Ext.tree.TreeNodeUI = function(node){
31135     this.node = node;
31136     this.rendered = false;
31137     this.animating = false;
31138     this.wasLeaf = true;
31139     this.ecc = 'x-tree-ec-icon x-tree-elbow';
31140     this.emptyIcon = Ext.BLANK_IMAGE_URL;
31141 };
31142
31143 Ext.tree.TreeNodeUI.prototype = {
31144     
31145     removeChild : function(node){
31146         if(this.rendered){
31147             this.ctNode.removeChild(node.ui.getEl());
31148         } 
31149     },
31150
31151     
31152     beforeLoad : function(){
31153          this.addClass("x-tree-node-loading");
31154     },
31155
31156     
31157     afterLoad : function(){
31158          this.removeClass("x-tree-node-loading");
31159     },
31160
31161     
31162     onTextChange : function(node, text, oldText){
31163         if(this.rendered){
31164             this.textNode.innerHTML = text;
31165         }
31166     },
31167
31168     
31169     onDisableChange : function(node, state){
31170         this.disabled = state;
31171         if (this.checkbox) {
31172             this.checkbox.disabled = state;
31173         }        
31174         if(state){
31175             this.addClass("x-tree-node-disabled");
31176         }else{
31177             this.removeClass("x-tree-node-disabled");
31178         } 
31179     },
31180
31181     
31182     onSelectedChange : function(state){
31183         if(state){
31184             this.focus();
31185             this.addClass("x-tree-selected");
31186         }else{
31187             
31188             this.removeClass("x-tree-selected");
31189         }
31190     },
31191
31192     
31193     onMove : function(tree, node, oldParent, newParent, index, refNode){
31194         this.childIndent = null;
31195         if(this.rendered){
31196             var targetNode = newParent.ui.getContainer();
31197             if(!targetNode){
31198                 this.holder = document.createElement("div");
31199                 this.holder.appendChild(this.wrap);
31200                 return;
31201             }
31202             var insertBefore = refNode ? refNode.ui.getEl() : null;
31203             if(insertBefore){
31204                 targetNode.insertBefore(this.wrap, insertBefore);
31205             }else{
31206                 targetNode.appendChild(this.wrap);
31207             }
31208             this.node.renderIndent(true, oldParent != newParent);
31209         }
31210     },
31211
31212
31213     addClass : function(cls){
31214         if(this.elNode){
31215             Ext.fly(this.elNode).addClass(cls);
31216         }
31217     },
31218
31219
31220     removeClass : function(cls){
31221         if(this.elNode){
31222             Ext.fly(this.elNode).removeClass(cls);  
31223         }
31224     },
31225
31226     
31227     remove : function(){
31228         if(this.rendered){
31229             this.holder = document.createElement("div");
31230             this.holder.appendChild(this.wrap);
31231         }  
31232     },
31233
31234     
31235     fireEvent : function(){
31236         return this.node.fireEvent.apply(this.node, arguments);  
31237     },
31238
31239     
31240     initEvents : function(){
31241         this.node.on("move", this.onMove, this);
31242
31243         if(this.node.disabled){
31244             this.onDisableChange(this.node, true);            
31245         }
31246         if(this.node.hidden){
31247             this.hide();
31248         }
31249         var ot = this.node.getOwnerTree();
31250         var dd = ot.enableDD || ot.enableDrag || ot.enableDrop;
31251         if(dd && (!this.node.isRoot || ot.rootVisible)){
31252             Ext.dd.Registry.register(this.elNode, {
31253                 node: this.node,
31254                 handles: this.getDDHandles(),
31255                 isHandle: false
31256             });
31257         }
31258     },
31259
31260     
31261     getDDHandles : function(){
31262         return [this.iconNode, this.textNode, this.elNode];
31263     },
31264
31265
31266     hide : function(){
31267         this.node.hidden = true;
31268         if(this.wrap){
31269             this.wrap.style.display = "none";
31270         }
31271     },
31272
31273
31274     show : function(){
31275         this.node.hidden = false;
31276         if(this.wrap){
31277             this.wrap.style.display = "";
31278         } 
31279     },
31280
31281     
31282     onContextMenu : function(e){
31283         if (this.node.hasListener("contextmenu") || this.node.getOwnerTree().hasListener("contextmenu")) {
31284             e.preventDefault();
31285             this.focus();
31286             this.fireEvent("contextmenu", this.node, e);
31287         }
31288     },
31289
31290     
31291     onClick : function(e){
31292         if(this.dropping){
31293             e.stopEvent();
31294             return;
31295         }
31296         if(this.fireEvent("beforeclick", this.node, e) !== false){
31297             var a = e.getTarget('a');
31298             if(!this.disabled && this.node.attributes.href && a){
31299                 this.fireEvent("click", this.node, e);
31300                 return;
31301             }else if(a && e.ctrlKey){
31302                 e.stopEvent();
31303             }
31304             e.preventDefault();
31305             if(this.disabled){
31306                 return;
31307             }
31308
31309             if(this.node.attributes.singleClickExpand && !this.animating && this.node.isExpandable()){
31310                 this.node.toggle();
31311             }
31312
31313             this.fireEvent("click", this.node, e);
31314         }else{
31315             e.stopEvent();
31316         }
31317     },
31318
31319     
31320     onDblClick : function(e){
31321         e.preventDefault();
31322         if(this.disabled){
31323             return;
31324         }
31325         if(this.fireEvent("beforedblclick", this.node, e) !== false){
31326             if(this.checkbox){
31327                 this.toggleCheck();
31328             }
31329             if(!this.animating && this.node.isExpandable()){
31330                 this.node.toggle();
31331             }
31332             this.fireEvent("dblclick", this.node, e);
31333         }
31334     },
31335
31336     onOver : function(e){
31337         this.addClass('x-tree-node-over');
31338     },
31339
31340     onOut : function(e){
31341         this.removeClass('x-tree-node-over');
31342     },
31343
31344     
31345     onCheckChange : function(){
31346         var checked = this.checkbox.checked;
31347         
31348         this.checkbox.defaultChecked = checked;        
31349         this.node.attributes.checked = checked;
31350         this.fireEvent('checkchange', this.node, checked);
31351     },
31352
31353     
31354     ecClick : function(e){
31355         if(!this.animating && this.node.isExpandable()){
31356             this.node.toggle();
31357         }
31358     },
31359
31360     
31361     startDrop : function(){
31362         this.dropping = true;
31363     },
31364     
31365     
31366     endDrop : function(){ 
31367        setTimeout(function(){
31368            this.dropping = false;
31369        }.createDelegate(this), 50); 
31370     },
31371
31372     
31373     expand : function(){
31374         this.updateExpandIcon();
31375         this.ctNode.style.display = "";
31376     },
31377
31378     
31379     focus : function(){
31380         if(!this.node.preventHScroll){
31381             try{this.anchor.focus();
31382             }catch(e){}
31383         }else{
31384             try{
31385                 var noscroll = this.node.getOwnerTree().getTreeEl().dom;
31386                 var l = noscroll.scrollLeft;
31387                 this.anchor.focus();
31388                 noscroll.scrollLeft = l;
31389             }catch(e){}
31390         }
31391     },
31392
31393
31394     toggleCheck : function(value){
31395         var cb = this.checkbox;
31396         if(cb){
31397             cb.checked = (value === undefined ? !cb.checked : value);
31398             this.onCheckChange();
31399         }
31400     },
31401
31402     
31403     blur : function(){
31404         try{
31405             this.anchor.blur();
31406         }catch(e){} 
31407     },
31408
31409     
31410     animExpand : function(callback){
31411         var ct = Ext.get(this.ctNode);
31412         ct.stopFx();
31413         if(!this.node.isExpandable()){
31414             this.updateExpandIcon();
31415             this.ctNode.style.display = "";
31416             Ext.callback(callback);
31417             return;
31418         }
31419         this.animating = true;
31420         this.updateExpandIcon();
31421         
31422         ct.slideIn('t', {
31423            callback : function(){
31424                this.animating = false;
31425                Ext.callback(callback);
31426             },
31427             scope: this,
31428             duration: this.node.ownerTree.duration || .25
31429         });
31430     },
31431
31432     
31433     highlight : function(){
31434         var tree = this.node.getOwnerTree();
31435         Ext.fly(this.wrap).highlight(
31436             tree.hlColor || "C3DAF9",
31437             {endColor: tree.hlBaseColor}
31438         );
31439     },
31440
31441     
31442     collapse : function(){
31443         this.updateExpandIcon();
31444         this.ctNode.style.display = "none";
31445     },
31446
31447     
31448     animCollapse : function(callback){
31449         var ct = Ext.get(this.ctNode);
31450         ct.enableDisplayMode('block');
31451         ct.stopFx();
31452
31453         this.animating = true;
31454         this.updateExpandIcon();
31455
31456         ct.slideOut('t', {
31457             callback : function(){
31458                this.animating = false;
31459                Ext.callback(callback);
31460             },
31461             scope: this,
31462             duration: this.node.ownerTree.duration || .25
31463         });
31464     },
31465
31466     
31467     getContainer : function(){
31468         return this.ctNode;  
31469     },
31470
31471
31472     getEl : function(){
31473         return this.wrap;  
31474     },
31475
31476     
31477     appendDDGhost : function(ghostNode){
31478         ghostNode.appendChild(this.elNode.cloneNode(true));
31479     },
31480
31481     
31482     getDDRepairXY : function(){
31483         return Ext.lib.Dom.getXY(this.iconNode);
31484     },
31485
31486     
31487     onRender : function(){
31488         this.render();    
31489     },
31490
31491     
31492     render : function(bulkRender){
31493         var n = this.node, a = n.attributes;
31494         var targetNode = n.parentNode ? 
31495               n.parentNode.ui.getContainer() : n.ownerTree.innerCt.dom;
31496         
31497         if(!this.rendered){
31498             this.rendered = true;
31499
31500             this.renderElements(n, a, targetNode, bulkRender);
31501
31502             if(a.qtip){
31503                if(this.textNode.setAttributeNS){
31504                    this.textNode.setAttributeNS("ext", "qtip", a.qtip);
31505                    if(a.qtipTitle){
31506                        this.textNode.setAttributeNS("ext", "qtitle", a.qtipTitle);
31507                    }
31508                }else{
31509                    this.textNode.setAttribute("ext:qtip", a.qtip);
31510                    if(a.qtipTitle){
31511                        this.textNode.setAttribute("ext:qtitle", a.qtipTitle);
31512                    }
31513                } 
31514             }else if(a.qtipCfg){
31515                 a.qtipCfg.target = Ext.id(this.textNode);
31516                 Ext.QuickTips.register(a.qtipCfg);
31517             }
31518             this.initEvents();
31519             if(!this.node.expanded){
31520                 this.updateExpandIcon(true);
31521             }
31522         }else{
31523             if(bulkRender === true) {
31524                 targetNode.appendChild(this.wrap);
31525             }
31526         }
31527     },
31528
31529     
31530     renderElements : function(n, a, targetNode, bulkRender){
31531         
31532         this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';
31533
31534         var cb = Ext.isBoolean(a.checked),
31535             nel,
31536             href = a.href ? a.href : Ext.isGecko ? "" : "#",
31537             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">',
31538             '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",
31539             '<img src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow" />',
31540             '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on" />',
31541             cb ? ('<input class="x-tree-node-cb" type="checkbox" ' + (a.checked ? 'checked="checked" />' : '/>')) : '',
31542             '<a hidefocus="on" class="x-tree-node-anchor" href="',href,'" tabIndex="1" ',
31543              a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", '><span unselectable="on">',n.text,"</span></a></div>",
31544             '<ul class="x-tree-node-ct" style="display:none;"></ul>',
31545             "</li>"].join('');
31546
31547         if(bulkRender !== true && n.nextSibling && (nel = n.nextSibling.ui.getEl())){
31548             this.wrap = Ext.DomHelper.insertHtml("beforeBegin", nel, buf);
31549         }else{
31550             this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf);
31551         }
31552         
31553         this.elNode = this.wrap.childNodes[0];
31554         this.ctNode = this.wrap.childNodes[1];
31555         var cs = this.elNode.childNodes;
31556         this.indentNode = cs[0];
31557         this.ecNode = cs[1];
31558         this.iconNode = cs[2];
31559         var index = 3;
31560         if(cb){
31561             this.checkbox = cs[3];
31562             
31563             this.checkbox.defaultChecked = this.checkbox.checked;
31564             index++;
31565         }
31566         this.anchor = cs[index];
31567         this.textNode = cs[index].firstChild;
31568     },
31569
31570
31571     getAnchor : function(){
31572         return this.anchor;
31573     },
31574     
31575
31576     getTextEl : function(){
31577         return this.textNode;
31578     },
31579     
31580
31581     getIconEl : function(){
31582         return this.iconNode;
31583     },
31584
31585
31586     isChecked : function(){
31587         return this.checkbox ? this.checkbox.checked : false; 
31588     },
31589
31590     
31591     updateExpandIcon : function(){
31592         if(this.rendered){
31593             var n = this.node, 
31594                 c1, 
31595                 c2,
31596                 cls = n.isLast() ? "x-tree-elbow-end" : "x-tree-elbow",
31597                 hasChild = n.hasChildNodes();
31598             if(hasChild || n.attributes.expandable){
31599                 if(n.expanded){
31600                     cls += "-minus";
31601                     c1 = "x-tree-node-collapsed";
31602                     c2 = "x-tree-node-expanded";
31603                 }else{
31604                     cls += "-plus";
31605                     c1 = "x-tree-node-expanded";
31606                     c2 = "x-tree-node-collapsed";
31607                 }
31608                 if(this.wasLeaf){
31609                     this.removeClass("x-tree-node-leaf");
31610                     this.wasLeaf = false;
31611                 }
31612                 if(this.c1 != c1 || this.c2 != c2){
31613                     Ext.fly(this.elNode).replaceClass(c1, c2);
31614                     this.c1 = c1; this.c2 = c2;
31615                 }
31616             }else{
31617                 if(!this.wasLeaf){
31618                     Ext.fly(this.elNode).replaceClass("x-tree-node-expanded", "x-tree-node-leaf");
31619                     delete this.c1;
31620                     delete this.c2;
31621                     this.wasLeaf = true;
31622                 }
31623             }
31624             var ecc = "x-tree-ec-icon "+cls;
31625             if(this.ecc != ecc){
31626                 this.ecNode.className = ecc;
31627                 this.ecc = ecc;
31628             }
31629         }
31630     },
31631     
31632     
31633     onIdChange: function(id){
31634         if(this.rendered){
31635             this.elNode.setAttribute('ext:tree-node-id', id);
31636         }
31637     },
31638
31639     
31640     getChildIndent : function(){
31641         if(!this.childIndent){
31642             var buf = [],
31643                 p = this.node;
31644             while(p){
31645                 if(!p.isRoot || (p.isRoot && p.ownerTree.rootVisible)){
31646                     if(!p.isLast()) {
31647                         buf.unshift('<img src="'+this.emptyIcon+'" class="x-tree-elbow-line" />');
31648                     } else {
31649                         buf.unshift('<img src="'+this.emptyIcon+'" class="x-tree-icon" />');
31650                     }
31651                 }
31652                 p = p.parentNode;
31653             }
31654             this.childIndent = buf.join("");
31655         }
31656         return this.childIndent;
31657     },
31658
31659     
31660     renderIndent : function(){
31661         if(this.rendered){
31662             var indent = "",
31663                 p = this.node.parentNode;
31664             if(p){
31665                 indent = p.ui.getChildIndent();
31666             }
31667             if(this.indentMarkup != indent){ 
31668                 this.indentNode.innerHTML = indent;
31669                 this.indentMarkup = indent;
31670             }
31671             this.updateExpandIcon();
31672         }
31673     },
31674
31675     destroy : function(){
31676         if(this.elNode){
31677             Ext.dd.Registry.unregister(this.elNode.id);
31678         }
31679         
31680         Ext.each(['textnode', 'anchor', 'checkbox', 'indentNode', 'ecNode', 'iconNode', 'elNode', 'ctNode', 'wrap', 'holder'], function(el){
31681             if(this[el]){
31682                 Ext.fly(this[el]).remove();
31683                 delete this[el];
31684             }
31685         }, this);
31686         delete this.node;
31687     }
31688 };
31689
31690
31691 Ext.tree.RootTreeNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
31692     
31693     render : function(){
31694         if(!this.rendered){
31695             var targetNode = this.node.ownerTree.innerCt.dom;
31696             this.node.expanded = true;
31697             targetNode.innerHTML = '<div class="x-tree-root-node"></div>';
31698             this.wrap = this.ctNode = targetNode.firstChild;
31699         }
31700     },
31701     collapse : Ext.emptyFn,
31702     expand : Ext.emptyFn
31703 });
31704 Ext.tree.TreeLoader = function(config){
31705     this.baseParams = {};
31706     Ext.apply(this, config);
31707
31708     this.addEvents(
31709         
31710         "beforeload",
31711         
31712         "load",
31713         
31714         "loadexception"
31715     );
31716     Ext.tree.TreeLoader.superclass.constructor.call(this);
31717     if(Ext.isString(this.paramOrder)){
31718         this.paramOrder = this.paramOrder.split(/[\s,|]/);
31719     }
31720 };
31721
31722 Ext.extend(Ext.tree.TreeLoader, Ext.util.Observable, {
31723     
31724     
31725     
31726     
31727     
31728     
31729     
31730     uiProviders : {},
31731
31732     
31733     clearOnLoad : true,
31734
31735     
31736     paramOrder: undefined,
31737
31738     
31739     paramsAsHash: false,
31740     
31741     
31742     nodeParameter: 'node',
31743
31744     
31745     directFn : undefined,
31746
31747     
31748     load : function(node, callback, scope){
31749         if(this.clearOnLoad){
31750             while(node.firstChild){
31751                 node.removeChild(node.firstChild);
31752             }
31753         }
31754         if(this.doPreload(node)){ 
31755             this.runCallback(callback, scope || node, [node]);
31756         }else if(this.directFn || this.dataUrl || this.url){
31757             this.requestData(node, callback, scope || node);
31758         }
31759     },
31760
31761     doPreload : function(node){
31762         if(node.attributes.children){
31763             if(node.childNodes.length < 1){ 
31764                 var cs = node.attributes.children;
31765                 node.beginUpdate();
31766                 for(var i = 0, len = cs.length; i < len; i++){
31767                     var cn = node.appendChild(this.createNode(cs[i]));
31768                     if(this.preloadChildren){
31769                         this.doPreload(cn);
31770                     }
31771                 }
31772                 node.endUpdate();
31773             }
31774             return true;
31775         }
31776         return false;
31777     },
31778
31779     getParams: function(node){
31780         var buf = [], bp = this.baseParams;
31781         if(this.directFn){
31782             buf.push(node.id);
31783             if(bp){
31784                 if(this.paramOrder){
31785                     for(var i = 0, len = this.paramOrder.length; i < len; i++){
31786                         buf.push(bp[this.paramOrder[i]]);
31787                     }
31788                 }else if(this.paramsAsHash){
31789                     buf.push(bp);
31790                 }
31791             }
31792             return buf;
31793         }else{
31794             var o = Ext.apply({}, bp);
31795             o[this.nodeParameter] = node.id;
31796             return o;
31797         }
31798     },
31799
31800     requestData : function(node, callback, scope){
31801         if(this.fireEvent("beforeload", this, node, callback) !== false){
31802             if(this.directFn){
31803                 var args = this.getParams(node);
31804                 args.push(this.processDirectResponse.createDelegate(this, [{callback: callback, node: node, scope: scope}], true));
31805                 this.directFn.apply(window, args);
31806             }else{
31807                 this.transId = Ext.Ajax.request({
31808                     method:this.requestMethod,
31809                     url: this.dataUrl||this.url,
31810                     success: this.handleResponse,
31811                     failure: this.handleFailure,
31812                     scope: this,
31813                     argument: {callback: callback, node: node, scope: scope},
31814                     params: this.getParams(node)
31815                 });
31816             }
31817         }else{
31818             
31819             
31820             this.runCallback(callback, scope || node, []);
31821         }
31822     },
31823
31824     processDirectResponse: function(result, response, args){
31825         if(response.status){
31826             this.handleResponse({
31827                 responseData: Ext.isArray(result) ? result : null,
31828                 responseText: result,
31829                 argument: args
31830             });
31831         }else{
31832             this.handleFailure({
31833                 argument: args
31834             });
31835         }
31836     },
31837
31838     
31839     runCallback: function(cb, scope, args){
31840         if(Ext.isFunction(cb)){
31841             cb.apply(scope, args);
31842         }
31843     },
31844
31845     isLoading : function(){
31846         return !!this.transId;
31847     },
31848
31849     abort : function(){
31850         if(this.isLoading()){
31851             Ext.Ajax.abort(this.transId);
31852         }
31853     },
31854
31855     
31856     createNode : function(attr){
31857         
31858         if(this.baseAttrs){
31859             Ext.applyIf(attr, this.baseAttrs);
31860         }
31861         if(this.applyLoader !== false && !attr.loader){
31862             attr.loader = this;
31863         }
31864         if(Ext.isString(attr.uiProvider)){
31865            attr.uiProvider = this.uiProviders[attr.uiProvider] || eval(attr.uiProvider);
31866         }
31867         if(attr.nodeType){
31868             return new Ext.tree.TreePanel.nodeTypes[attr.nodeType](attr);
31869         }else{
31870             return attr.leaf ?
31871                         new Ext.tree.TreeNode(attr) :
31872                         new Ext.tree.AsyncTreeNode(attr);
31873         }
31874     },
31875
31876     processResponse : function(response, node, callback, scope){
31877         var json = response.responseText;
31878         try {
31879             var o = response.responseData || Ext.decode(json);
31880             node.beginUpdate();
31881             for(var i = 0, len = o.length; i < len; i++){
31882                 var n = this.createNode(o[i]);
31883                 if(n){
31884                     node.appendChild(n);
31885                 }
31886             }
31887             node.endUpdate();
31888             this.runCallback(callback, scope || node, [node]);
31889         }catch(e){
31890             this.handleFailure(response);
31891         }
31892     },
31893
31894     handleResponse : function(response){
31895         this.transId = false;
31896         var a = response.argument;
31897         this.processResponse(response, a.node, a.callback, a.scope);
31898         this.fireEvent("load", this, a.node, response);
31899     },
31900
31901     handleFailure : function(response){
31902         this.transId = false;
31903         var a = response.argument;
31904         this.fireEvent("loadexception", this, a.node, response);
31905         this.runCallback(a.callback, a.scope || a.node, [a.node]);
31906     },
31907     
31908     destroy : function(){
31909         this.purgeListeners();
31910     }
31911 });
31912 Ext.tree.TreeFilter = function(tree, config){
31913     this.tree = tree;
31914     this.filtered = {};
31915     Ext.apply(this, config);
31916 };
31917
31918 Ext.tree.TreeFilter.prototype = {
31919     clearBlank:false,
31920     reverse:false,
31921     autoClear:false,
31922     remove:false,
31923
31924      
31925     filter : function(value, attr, startNode){
31926         attr = attr || "text";
31927         var f;
31928         if(typeof value == "string"){
31929             var vlen = value.length;
31930             
31931             if(vlen == 0 && this.clearBlank){
31932                 this.clear();
31933                 return;
31934             }
31935             value = value.toLowerCase();
31936             f = function(n){
31937                 return n.attributes[attr].substr(0, vlen).toLowerCase() == value;
31938             };
31939         }else if(value.exec){ 
31940             f = function(n){
31941                 return value.test(n.attributes[attr]);
31942             };
31943         }else{
31944             throw 'Illegal filter type, must be string or regex';
31945         }
31946         this.filterBy(f, null, startNode);
31947         },
31948
31949     
31950     filterBy : function(fn, scope, startNode){
31951         startNode = startNode || this.tree.root;
31952         if(this.autoClear){
31953             this.clear();
31954         }
31955         var af = this.filtered, rv = this.reverse;
31956         var f = function(n){
31957             if(n == startNode){
31958                 return true;
31959             }
31960             if(af[n.id]){
31961                 return false;
31962             }
31963             var m = fn.call(scope || n, n);
31964             if(!m || rv){
31965                 af[n.id] = n;
31966                 n.ui.hide();
31967                 return false;
31968             }
31969             return true;
31970         };
31971         startNode.cascade(f);
31972         if(this.remove){
31973            for(var id in af){
31974                if(typeof id != "function"){
31975                    var n = af[id];
31976                    if(n && n.parentNode){
31977                        n.parentNode.removeChild(n);
31978                    }
31979                }
31980            }
31981         }
31982     },
31983
31984     
31985     clear : function(){
31986         var t = this.tree;
31987         var af = this.filtered;
31988         for(var id in af){
31989             if(typeof id != "function"){
31990                 var n = af[id];
31991                 if(n){
31992                     n.ui.show();
31993                 }
31994             }
31995         }
31996         this.filtered = {};
31997     }
31998 };
31999
32000 Ext.tree.TreeSorter = function(tree, config){
32001     
32002     
32003     
32004     
32005     
32006     
32007     
32008     Ext.apply(this, config);
32009     tree.on("beforechildrenrendered", this.doSort, this);
32010     tree.on("append", this.updateSort, this);
32011     tree.on("insert", this.updateSort, this);
32012     tree.on("textchange", this.updateSortParent, this);
32013     
32014     var dsc = this.dir && this.dir.toLowerCase() == "desc";
32015     var p = this.property || "text";
32016     var sortType = this.sortType;
32017     var fs = this.folderSort;
32018     var cs = this.caseSensitive === true;
32019     var leafAttr = this.leafAttr || 'leaf';
32020
32021     this.sortFn = function(n1, n2){
32022         if(fs){
32023             if(n1.attributes[leafAttr] && !n2.attributes[leafAttr]){
32024                 return 1;
32025             }
32026             if(!n1.attributes[leafAttr] && n2.attributes[leafAttr]){
32027                 return -1;
32028             }
32029         }
32030         var v1 = sortType ? sortType(n1.attributes[p]) : (cs ? n1.attributes[p] : n1.attributes[p].toUpperCase());
32031         var v2 = sortType ? sortType(n2.attributes[p]) : (cs ? n2.attributes[p] : n2.attributes[p].toUpperCase());
32032         if(v1 < v2){
32033                         return dsc ? +1 : -1;
32034                 }else if(v1 > v2){
32035                         return dsc ? -1 : +1;
32036         }else{
32037                 return 0;
32038         }
32039     };
32040 };
32041
32042 Ext.tree.TreeSorter.prototype = {
32043     doSort : function(node){
32044         node.sort(this.sortFn);
32045     },
32046     
32047     compareNodes : function(n1, n2){
32048         return (n1.text.toUpperCase() > n2.text.toUpperCase() ? 1 : -1);
32049     },
32050     
32051     updateSort : function(tree, node){
32052         if(node.childrenRendered){
32053             this.doSort.defer(1, this, [node]);
32054         }
32055     },
32056     
32057     updateSortParent : function(node){
32058                 var p = node.parentNode;
32059                 if(p && p.childrenRendered){
32060             this.doSort.defer(1, this, [p]);
32061         }
32062     }
32063 };
32064 if(Ext.dd.DropZone){
32065     
32066 Ext.tree.TreeDropZone = function(tree, config){
32067     
32068     this.allowParentInsert = config.allowParentInsert || false;
32069     
32070     this.allowContainerDrop = config.allowContainerDrop || false;
32071     
32072     this.appendOnly = config.appendOnly || false;
32073
32074     Ext.tree.TreeDropZone.superclass.constructor.call(this, tree.getTreeEl(), config);
32075     
32076     this.tree = tree;
32077     
32078     this.dragOverData = {};
32079     
32080     this.lastInsertClass = "x-tree-no-status";
32081 };
32082
32083 Ext.extend(Ext.tree.TreeDropZone, Ext.dd.DropZone, {
32084     
32085     ddGroup : "TreeDD",
32086
32087     
32088     expandDelay : 1000,
32089
32090     
32091     expandNode : function(node){
32092         if(node.hasChildNodes() && !node.isExpanded()){
32093             node.expand(false, null, this.triggerCacheRefresh.createDelegate(this));
32094         }
32095     },
32096
32097     
32098     queueExpand : function(node){
32099         this.expandProcId = this.expandNode.defer(this.expandDelay, this, [node]);
32100     },
32101
32102     
32103     cancelExpand : function(){
32104         if(this.expandProcId){
32105             clearTimeout(this.expandProcId);
32106             this.expandProcId = false;
32107         }
32108     },
32109
32110     
32111     isValidDropPoint : function(n, pt, dd, e, data){
32112         if(!n || !data){ return false; }
32113         var targetNode = n.node;
32114         var dropNode = data.node;
32115         
32116         if(!(targetNode && targetNode.isTarget && pt)){
32117             return false;
32118         }
32119         if(pt == "append" && targetNode.allowChildren === false){
32120             return false;
32121         }
32122         if((pt == "above" || pt == "below") && (targetNode.parentNode && targetNode.parentNode.allowChildren === false)){
32123             return false;
32124         }
32125         if(dropNode && (targetNode == dropNode || dropNode.contains(targetNode))){
32126             return false;
32127         }
32128         
32129         var overEvent = this.dragOverData;
32130         overEvent.tree = this.tree;
32131         overEvent.target = targetNode;
32132         overEvent.data = data;
32133         overEvent.point = pt;
32134         overEvent.source = dd;
32135         overEvent.rawEvent = e;
32136         overEvent.dropNode = dropNode;
32137         overEvent.cancel = false;  
32138         var result = this.tree.fireEvent("nodedragover", overEvent);
32139         return overEvent.cancel === false && result !== false;
32140     },
32141
32142     
32143     getDropPoint : function(e, n, dd){
32144         var tn = n.node;
32145         if(tn.isRoot){
32146             return tn.allowChildren !== false ? "append" : false; 
32147         }
32148         var dragEl = n.ddel;
32149         var t = Ext.lib.Dom.getY(dragEl), b = t + dragEl.offsetHeight;
32150         var y = Ext.lib.Event.getPageY(e);
32151         var noAppend = tn.allowChildren === false || tn.isLeaf();
32152         if(this.appendOnly || tn.parentNode.allowChildren === false){
32153             return noAppend ? false : "append";
32154         }
32155         var noBelow = false;
32156         if(!this.allowParentInsert){
32157             noBelow = tn.hasChildNodes() && tn.isExpanded();
32158         }
32159         var q = (b - t) / (noAppend ? 2 : 3);
32160         if(y >= t && y < (t + q)){
32161             return "above";
32162         }else if(!noBelow && (noAppend || y >= b-q && y <= b)){
32163             return "below";
32164         }else{
32165             return "append";
32166         }
32167     },
32168
32169     
32170     onNodeEnter : function(n, dd, e, data){
32171         this.cancelExpand();
32172     },
32173     
32174     onContainerOver : function(dd, e, data) {
32175         if (this.allowContainerDrop && this.isValidDropPoint({ ddel: this.tree.getRootNode().ui.elNode, node: this.tree.getRootNode() }, "append", dd, e, data)) {
32176             return this.dropAllowed;
32177         }
32178         return this.dropNotAllowed;
32179     },
32180
32181     
32182     onNodeOver : function(n, dd, e, data){
32183         var pt = this.getDropPoint(e, n, dd);
32184         var node = n.node;
32185         
32186         
32187         if(!this.expandProcId && pt == "append" && node.hasChildNodes() && !n.node.isExpanded()){
32188             this.queueExpand(node);
32189         }else if(pt != "append"){
32190             this.cancelExpand();
32191         }
32192         
32193         
32194         var returnCls = this.dropNotAllowed;
32195         if(this.isValidDropPoint(n, pt, dd, e, data)){
32196            if(pt){
32197                var el = n.ddel;
32198                var cls;
32199                if(pt == "above"){
32200                    returnCls = n.node.isFirst() ? "x-tree-drop-ok-above" : "x-tree-drop-ok-between";
32201                    cls = "x-tree-drag-insert-above";
32202                }else if(pt == "below"){
32203                    returnCls = n.node.isLast() ? "x-tree-drop-ok-below" : "x-tree-drop-ok-between";
32204                    cls = "x-tree-drag-insert-below";
32205                }else{
32206                    returnCls = "x-tree-drop-ok-append";
32207                    cls = "x-tree-drag-append";
32208                }
32209                if(this.lastInsertClass != cls){
32210                    Ext.fly(el).replaceClass(this.lastInsertClass, cls);
32211                    this.lastInsertClass = cls;
32212                }
32213            }
32214        }
32215        return returnCls;
32216     },
32217
32218     
32219     onNodeOut : function(n, dd, e, data){
32220         this.cancelExpand();
32221         this.removeDropIndicators(n);
32222     },
32223
32224     
32225     onNodeDrop : function(n, dd, e, data){
32226         var point = this.getDropPoint(e, n, dd);
32227         var targetNode = n.node;
32228         targetNode.ui.startDrop();
32229         if(!this.isValidDropPoint(n, point, dd, e, data)){
32230             targetNode.ui.endDrop();
32231             return false;
32232         }
32233         
32234         var dropNode = data.node || (dd.getTreeNode ? dd.getTreeNode(data, targetNode, point, e) : null);
32235         return this.processDrop(targetNode, data, point, dd, e, dropNode);
32236     },
32237     
32238     onContainerDrop : function(dd, e, data){
32239         if (this.allowContainerDrop && this.isValidDropPoint({ ddel: this.tree.getRootNode().ui.elNode, node: this.tree.getRootNode() }, "append", dd, e, data)) {
32240             var targetNode = this.tree.getRootNode();       
32241             targetNode.ui.startDrop();
32242             var dropNode = data.node || (dd.getTreeNode ? dd.getTreeNode(data, targetNode, 'append', e) : null);
32243             return this.processDrop(targetNode, data, 'append', dd, e, dropNode);
32244         }
32245         return false;
32246     },
32247     
32248     
32249     processDrop: function(target, data, point, dd, e, dropNode){
32250         var dropEvent = {
32251             tree : this.tree,
32252             target: target,
32253             data: data,
32254             point: point,
32255             source: dd,
32256             rawEvent: e,
32257             dropNode: dropNode,
32258             cancel: !dropNode,
32259             dropStatus: false
32260         };
32261         var retval = this.tree.fireEvent("beforenodedrop", dropEvent);
32262         if(retval === false || dropEvent.cancel === true || !dropEvent.dropNode){
32263             target.ui.endDrop();
32264             return dropEvent.dropStatus;
32265         }
32266     
32267         target = dropEvent.target;
32268         if(point == 'append' && !target.isExpanded()){
32269             target.expand(false, null, function(){
32270                 this.completeDrop(dropEvent);
32271             }.createDelegate(this));
32272         }else{
32273             this.completeDrop(dropEvent);
32274         }
32275         return true;
32276     },
32277
32278     
32279     completeDrop : function(de){
32280         var ns = de.dropNode, p = de.point, t = de.target;
32281         if(!Ext.isArray(ns)){
32282             ns = [ns];
32283         }
32284         var n;
32285         for(var i = 0, len = ns.length; i < len; i++){
32286             n = ns[i];
32287             if(p == "above"){
32288                 t.parentNode.insertBefore(n, t);
32289             }else if(p == "below"){
32290                 t.parentNode.insertBefore(n, t.nextSibling);
32291             }else{
32292                 t.appendChild(n);
32293             }
32294         }
32295         n.ui.focus();
32296         if(Ext.enableFx && this.tree.hlDrop){
32297             n.ui.highlight();
32298         }
32299         t.ui.endDrop();
32300         this.tree.fireEvent("nodedrop", de);
32301     },
32302
32303     
32304     afterNodeMoved : function(dd, data, e, targetNode, dropNode){
32305         if(Ext.enableFx && this.tree.hlDrop){
32306             dropNode.ui.focus();
32307             dropNode.ui.highlight();
32308         }
32309         this.tree.fireEvent("nodedrop", this.tree, targetNode, data, dd, e);
32310     },
32311
32312     
32313     getTree : function(){
32314         return this.tree;
32315     },
32316
32317     
32318     removeDropIndicators : function(n){
32319         if(n && n.ddel){
32320             var el = n.ddel;
32321             Ext.fly(el).removeClass([
32322                     "x-tree-drag-insert-above",
32323                     "x-tree-drag-insert-below",
32324                     "x-tree-drag-append"]);
32325             this.lastInsertClass = "_noclass";
32326         }
32327     },
32328
32329     
32330     beforeDragDrop : function(target, e, id){
32331         this.cancelExpand();
32332         return true;
32333     },
32334
32335     
32336     afterRepair : function(data){
32337         if(data && Ext.enableFx){
32338             data.node.ui.highlight();
32339         }
32340         this.hideProxy();
32341     }    
32342 });
32343
32344 }
32345 if(Ext.dd.DragZone){
32346 Ext.tree.TreeDragZone = function(tree, config){
32347     Ext.tree.TreeDragZone.superclass.constructor.call(this, tree.innerCt, config);
32348     
32349     this.tree = tree;
32350 };
32351
32352 Ext.extend(Ext.tree.TreeDragZone, Ext.dd.DragZone, {
32353     
32354     ddGroup : "TreeDD",
32355
32356     
32357     onBeforeDrag : function(data, e){
32358         var n = data.node;
32359         return n && n.draggable && !n.disabled;
32360     },
32361
32362     
32363     onInitDrag : function(e){
32364         var data = this.dragData;
32365         this.tree.getSelectionModel().select(data.node);
32366         this.tree.eventModel.disable();
32367         this.proxy.update("");
32368         data.node.ui.appendDDGhost(this.proxy.ghost.dom);
32369         this.tree.fireEvent("startdrag", this.tree, data.node, e);
32370     },
32371
32372     
32373     getRepairXY : function(e, data){
32374         return data.node.ui.getDDRepairXY();
32375     },
32376
32377     
32378     onEndDrag : function(data, e){
32379         this.tree.eventModel.enable.defer(100, this.tree.eventModel);
32380         this.tree.fireEvent("enddrag", this.tree, data.node, e);
32381     },
32382
32383     
32384     onValidDrop : function(dd, e, id){
32385         this.tree.fireEvent("dragdrop", this.tree, this.dragData.node, dd, e);
32386         this.hideProxy();
32387     },
32388
32389     
32390     beforeInvalidDrop : function(e, id){
32391         
32392         var sm = this.tree.getSelectionModel();
32393         sm.clearSelections();
32394         sm.select(this.dragData.node);
32395     },
32396     
32397     
32398     afterRepair : function(){
32399         if (Ext.enableFx && this.tree.hlDrop) {
32400             Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
32401         }
32402         this.dragging = false;
32403     }
32404 });
32405 }
32406 Ext.tree.TreeEditor = function(tree, fc, config){
32407     fc = fc || {};
32408     var field = fc.events ? fc : new Ext.form.TextField(fc);
32409     Ext.tree.TreeEditor.superclass.constructor.call(this, field, config);
32410
32411     this.tree = tree;
32412
32413     if(!tree.rendered){
32414         tree.on('render', this.initEditor, this);
32415     }else{
32416         this.initEditor(tree);
32417     }
32418 };
32419
32420 Ext.extend(Ext.tree.TreeEditor, Ext.Editor, {
32421     
32422     alignment: "l-l",
32423     
32424     autoSize: false,
32425     
32426     hideEl : false,
32427     
32428     cls: "x-small-editor x-tree-editor",
32429     
32430     shim:false,
32431     
32432     shadow:"frame",
32433     
32434     maxWidth: 250,
32435     
32436     editDelay : 350,
32437
32438     initEditor : function(tree){
32439         tree.on({
32440             scope: this,
32441             beforeclick: this.beforeNodeClick,
32442             dblclick: this.onNodeDblClick
32443         });
32444         this.on({
32445             scope: this,
32446             complete: this.updateNode,
32447             beforestartedit: this.fitToTree,
32448             specialkey: this.onSpecialKey
32449         });
32450         this.on('startedit', this.bindScroll, this, {delay:10});
32451     },
32452
32453     
32454     fitToTree : function(ed, el){
32455         var td = this.tree.getTreeEl().dom, nd = el.dom;
32456         if(td.scrollLeft >  nd.offsetLeft){ 
32457             td.scrollLeft = nd.offsetLeft;
32458         }
32459         var w = Math.min(
32460                 this.maxWidth,
32461                 (td.clientWidth > 20 ? td.clientWidth : td.offsetWidth) - Math.max(0, nd.offsetLeft-td.scrollLeft) - 5);
32462         this.setSize(w, '');
32463     },
32464
32465     
32466     triggerEdit : function(node, defer){
32467         this.completeEdit();
32468                 if(node.attributes.editable !== false){
32469            
32470                         this.editNode = node;
32471             if(this.tree.autoScroll){
32472                 Ext.fly(node.ui.getEl()).scrollIntoView(this.tree.body);
32473             }
32474             var value = node.text || '';
32475             if (!Ext.isGecko && Ext.isEmpty(node.text)){
32476                 node.setText('&#160;');
32477             }
32478             this.autoEditTimer = this.startEdit.defer(this.editDelay, this, [node.ui.textNode, value]);
32479             return false;
32480         }
32481     },
32482
32483     
32484     bindScroll : function(){
32485         this.tree.getTreeEl().on('scroll', this.cancelEdit, this);
32486     },
32487
32488     
32489     beforeNodeClick : function(node, e){
32490         clearTimeout(this.autoEditTimer);
32491         if(this.tree.getSelectionModel().isSelected(node)){
32492             e.stopEvent();
32493             return this.triggerEdit(node);
32494         }
32495     },
32496
32497     onNodeDblClick : function(node, e){
32498         clearTimeout(this.autoEditTimer);
32499     },
32500
32501     
32502     updateNode : function(ed, value){
32503         this.tree.getTreeEl().un('scroll', this.cancelEdit, this);
32504         this.editNode.setText(value);
32505     },
32506
32507     
32508     onHide : function(){
32509         Ext.tree.TreeEditor.superclass.onHide.call(this);
32510         if(this.editNode){
32511             this.editNode.ui.focus.defer(50, this.editNode.ui);
32512         }
32513     },
32514
32515     
32516     onSpecialKey : function(field, e){
32517         var k = e.getKey();
32518         if(k == e.ESC){
32519             e.stopEvent();
32520             this.cancelEdit();
32521         }else if(k == e.ENTER && !e.hasModifier()){
32522             e.stopEvent();
32523             this.completeEdit();
32524         }
32525     },
32526     
32527     onDestroy : function(){
32528         clearTimeout(this.autoEditTimer);
32529         Ext.tree.TreeEditor.superclass.onDestroy.call(this);
32530         var tree = this.tree;
32531         tree.un('beforeclick', this.beforeNodeClick, this);
32532         tree.un('dblclick', this.onNodeDblClick, this);
32533     }
32534 });
32535
32536 var swfobject = function() {
32537     
32538     var UNDEF = "undefined",
32539         OBJECT = "object",
32540         SHOCKWAVE_FLASH = "Shockwave Flash",
32541         SHOCKWAVE_FLASH_AX = "ShockwaveFlash.ShockwaveFlash",
32542         FLASH_MIME_TYPE = "application/x-shockwave-flash",
32543         EXPRESS_INSTALL_ID = "SWFObjectExprInst",
32544         ON_READY_STATE_CHANGE = "onreadystatechange",
32545         
32546         win = window,
32547         doc = document,
32548         nav = navigator,
32549         
32550         plugin = false,
32551         domLoadFnArr = [main],
32552         regObjArr = [],
32553         objIdArr = [],
32554         listenersArr = [],
32555         storedAltContent,
32556         storedAltContentId,
32557         storedCallbackFn,
32558         storedCallbackObj,
32559         isDomLoaded = false,
32560         isExpressInstallActive = false,
32561         dynamicStylesheet,
32562         dynamicStylesheetMedia,
32563         autoHideShow = true,
32564     
32565       
32566     ua = function() {
32567         var w3cdom = typeof doc.getElementById != UNDEF && typeof doc.getElementsByTagName != UNDEF && typeof doc.createElement != UNDEF,
32568             u = nav.userAgent.toLowerCase(),
32569             p = nav.platform.toLowerCase(),
32570             windows = p ? /win/.test(p) : /win/.test(u),
32571             mac = p ? /mac/.test(p) : /mac/.test(u),
32572             webkit = /webkit/.test(u) ? parseFloat(u.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false, 
32573             ie = !+"\v1", 
32574             playerVersion = [0,0,0],
32575             d = null;
32576         if (typeof nav.plugins != UNDEF && typeof nav.plugins[SHOCKWAVE_FLASH] == OBJECT) {
32577             d = nav.plugins[SHOCKWAVE_FLASH].description;
32578             if (d && !(typeof nav.mimeTypes != UNDEF && nav.mimeTypes[FLASH_MIME_TYPE] && !nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) { 
32579                 plugin = true;
32580                 ie = false; 
32581                 d = d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
32582                 playerVersion[0] = parseInt(d.replace(/^(.*)\..*$/, "$1"), 10);
32583                 playerVersion[1] = parseInt(d.replace(/^.*\.(.*)\s.*$/, "$1"), 10);
32584                 playerVersion[2] = /[a-zA-Z]/.test(d) ? parseInt(d.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0;
32585             }
32586         }
32587         else if (typeof win.ActiveXObject != UNDEF) {
32588             try {
32589                 var a = new ActiveXObject(SHOCKWAVE_FLASH_AX);
32590                 if (a) { 
32591                     d = a.GetVariable("$version");
32592                     if (d) {
32593                         ie = true; 
32594                         d = d.split(" ")[1].split(",");
32595                         playerVersion = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
32596                     }
32597                 }
32598             }
32599             catch(e) {}
32600         }
32601         return { w3:w3cdom, pv:playerVersion, wk:webkit, ie:ie, win:windows, mac:mac };
32602     }(),
32603     
32604      
32605     onDomLoad = function() {
32606         if (!ua.w3) { return; }
32607         if ((typeof doc.readyState != UNDEF && doc.readyState == "complete") || (typeof doc.readyState == UNDEF && (doc.getElementsByTagName("body")[0] || doc.body))) { 
32608             callDomLoadFunctions();
32609         }
32610         if (!isDomLoaded) {
32611             if (typeof doc.addEventListener != UNDEF) {
32612                 doc.addEventListener("DOMContentLoaded", callDomLoadFunctions, false);
32613             }       
32614             if (ua.ie && ua.win) {
32615                 doc.attachEvent(ON_READY_STATE_CHANGE, function() {
32616                     if (doc.readyState == "complete") {
32617                         doc.detachEvent(ON_READY_STATE_CHANGE, arguments.callee);
32618                         callDomLoadFunctions();
32619                     }
32620                 });
32621                 if (win == top) { 
32622                     (function(){
32623                         if (isDomLoaded) { return; }
32624                         try {
32625                             doc.documentElement.doScroll("left");
32626                         }
32627                         catch(e) {
32628                             setTimeout(arguments.callee, 0);
32629                             return;
32630                         }
32631                         callDomLoadFunctions();
32632                     })();
32633                 }
32634             }
32635             if (ua.wk) {
32636                 (function(){
32637                     if (isDomLoaded) { return; }
32638                     if (!/loaded|complete/.test(doc.readyState)) {
32639                         setTimeout(arguments.callee, 0);
32640                         return;
32641                     }
32642                     callDomLoadFunctions();
32643                 })();
32644             }
32645             addLoadEvent(callDomLoadFunctions);
32646         }
32647     }();
32648     
32649     function callDomLoadFunctions() {
32650         if (isDomLoaded) { return; }
32651         try { 
32652             var t = doc.getElementsByTagName("body")[0].appendChild(createElement("span"));
32653             t.parentNode.removeChild(t);
32654         }
32655         catch (e) { return; }
32656         isDomLoaded = true;
32657         var dl = domLoadFnArr.length;
32658         for (var i = 0; i < dl; i++) {
32659             domLoadFnArr[i]();
32660         }
32661     }
32662     
32663     function addDomLoadEvent(fn) {
32664         if (isDomLoaded) {
32665             fn();
32666         }
32667         else { 
32668             domLoadFnArr[domLoadFnArr.length] = fn; 
32669         }
32670     }
32671     
32672     
32673     function addLoadEvent(fn) {
32674         if (typeof win.addEventListener != UNDEF) {
32675             win.addEventListener("load", fn, false);
32676         }
32677         else if (typeof doc.addEventListener != UNDEF) {
32678             doc.addEventListener("load", fn, false);
32679         }
32680         else if (typeof win.attachEvent != UNDEF) {
32681             addListener(win, "onload", fn);
32682         }
32683         else if (typeof win.onload == "function") {
32684             var fnOld = win.onload;
32685             win.onload = function() {
32686                 fnOld();
32687                 fn();
32688             };
32689         }
32690         else {
32691             win.onload = fn;
32692         }
32693     }
32694     
32695     
32696     function main() { 
32697         if (plugin) {
32698             testPlayerVersion();
32699         }
32700         else {
32701             matchVersions();
32702         }
32703     }
32704     
32705     
32706     function testPlayerVersion() {
32707         var b = doc.getElementsByTagName("body")[0];
32708         var o = createElement(OBJECT);
32709         o.setAttribute("type", FLASH_MIME_TYPE);
32710         var t = b.appendChild(o);
32711         if (t) {
32712             var counter = 0;
32713             (function(){
32714                 if (typeof t.GetVariable != UNDEF) {
32715                     var d = t.GetVariable("$version");
32716                     if (d) {
32717                         d = d.split(" ")[1].split(",");
32718                         ua.pv = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
32719                     }
32720                 }
32721                 else if (counter < 10) {
32722                     counter++;
32723                     setTimeout(arguments.callee, 10);
32724                     return;
32725                 }
32726                 b.removeChild(o);
32727                 t = null;
32728                 matchVersions();
32729             })();
32730         }
32731         else {
32732             matchVersions();
32733         }
32734     }
32735     
32736     
32737     function matchVersions() {
32738         var rl = regObjArr.length;
32739         if (rl > 0) {
32740             for (var i = 0; i < rl; i++) { 
32741                 var id = regObjArr[i].id;
32742                 var cb = regObjArr[i].callbackFn;
32743                 var cbObj = {success:false, id:id};
32744                 if (ua.pv[0] > 0) {
32745                     var obj = getElementById(id);
32746                     if (obj) {
32747                         if (hasPlayerVersion(regObjArr[i].swfVersion) && !(ua.wk && ua.wk < 312)) { 
32748                             setVisibility(id, true);
32749                             if (cb) {
32750                                 cbObj.success = true;
32751                                 cbObj.ref = getObjectById(id);
32752                                 cb(cbObj);
32753                             }
32754                         }
32755                         else if (regObjArr[i].expressInstall && canExpressInstall()) { 
32756                             var att = {};
32757                             att.data = regObjArr[i].expressInstall;
32758                             att.width = obj.getAttribute("width") || "0";
32759                             att.height = obj.getAttribute("height") || "0";
32760                             if (obj.getAttribute("class")) { att.styleclass = obj.getAttribute("class"); }
32761                             if (obj.getAttribute("align")) { att.align = obj.getAttribute("align"); }
32762                             
32763                             var par = {};
32764                             var p = obj.getElementsByTagName("param");
32765                             var pl = p.length;
32766                             for (var j = 0; j < pl; j++) {
32767                                 if (p[j].getAttribute("name").toLowerCase() != "movie") {
32768                                     par[p[j].getAttribute("name")] = p[j].getAttribute("value");
32769                                 }
32770                             }
32771                             showExpressInstall(att, par, id, cb);
32772                         }
32773                         else { 
32774                             displayAltContent(obj);
32775                             if (cb) { cb(cbObj); }
32776                         }
32777                     }
32778                 }
32779                 else {  
32780                     setVisibility(id, true);
32781                     if (cb) {
32782                         var o = getObjectById(id); 
32783                         if (o && typeof o.SetVariable != UNDEF) { 
32784                             cbObj.success = true;
32785                             cbObj.ref = o;
32786                         }
32787                         cb(cbObj);
32788                     }
32789                 }
32790             }
32791         }
32792     }
32793     
32794     function getObjectById(objectIdStr) {
32795         var r = null;
32796         var o = getElementById(objectIdStr);
32797         if (o && o.nodeName == "OBJECT") {
32798             if (typeof o.SetVariable != UNDEF) {
32799                 r = o;
32800             }
32801             else {
32802                 var n = o.getElementsByTagName(OBJECT)[0];
32803                 if (n) {
32804                     r = n;
32805                 }
32806             }
32807         }
32808         return r;
32809     }
32810     
32811     
32812     function canExpressInstall() {
32813         return !isExpressInstallActive && hasPlayerVersion("6.0.65") && (ua.win || ua.mac) && !(ua.wk && ua.wk < 312);
32814     }
32815     
32816     
32817     function showExpressInstall(att, par, replaceElemIdStr, callbackFn) {
32818         isExpressInstallActive = true;
32819         storedCallbackFn = callbackFn || null;
32820         storedCallbackObj = {success:false, id:replaceElemIdStr};
32821         var obj = getElementById(replaceElemIdStr);
32822         if (obj) {
32823             if (obj.nodeName == "OBJECT") { 
32824                 storedAltContent = abstractAltContent(obj);
32825                 storedAltContentId = null;
32826             }
32827             else { 
32828                 storedAltContent = obj;
32829                 storedAltContentId = replaceElemIdStr;
32830             }
32831             att.id = EXPRESS_INSTALL_ID;
32832             if (typeof att.width == UNDEF || (!/%$/.test(att.width) && parseInt(att.width, 10) < 310)) { att.width = "310"; }
32833             if (typeof att.height == UNDEF || (!/%$/.test(att.height) && parseInt(att.height, 10) < 137)) { att.height = "137"; }
32834             doc.title = doc.title.slice(0, 47) + " - Flash Player Installation";
32835             var pt = ua.ie && ua.win ? "ActiveX" : "PlugIn",
32836                 fv = "MMredirectURL=" + win.location.toString().replace(/&/g,"%26") + "&MMplayerType=" + pt + "&MMdoctitle=" + doc.title;
32837             if (typeof par.flashvars != UNDEF) {
32838                 par.flashvars += "&" + fv;
32839             }
32840             else {
32841                 par.flashvars = fv;
32842             }
32843             
32844             
32845             if (ua.ie && ua.win && obj.readyState != 4) {
32846                 var newObj = createElement("div");
32847                 replaceElemIdStr += "SWFObjectNew";
32848                 newObj.setAttribute("id", replaceElemIdStr);
32849                 obj.parentNode.insertBefore(newObj, obj); 
32850                 obj.style.display = "none";
32851                 (function(){
32852                     if (obj.readyState == 4) {
32853                         obj.parentNode.removeChild(obj);
32854                     }
32855                     else {
32856                         setTimeout(arguments.callee, 10);
32857                     }
32858                 })();
32859             }
32860             createSWF(att, par, replaceElemIdStr);
32861         }
32862     }
32863     
32864     
32865     function displayAltContent(obj) {
32866         if (ua.ie && ua.win && obj.readyState != 4) {
32867             
32868             
32869             var el = createElement("div");
32870             obj.parentNode.insertBefore(el, obj); 
32871             el.parentNode.replaceChild(abstractAltContent(obj), el);
32872             obj.style.display = "none";
32873             (function(){
32874                 if (obj.readyState == 4) {
32875                     obj.parentNode.removeChild(obj);
32876                 }
32877                 else {
32878                     setTimeout(arguments.callee, 10);
32879                 }
32880             })();
32881         }
32882         else {
32883             obj.parentNode.replaceChild(abstractAltContent(obj), obj);
32884         }
32885     } 
32886
32887     function abstractAltContent(obj) {
32888         var ac = createElement("div");
32889         if (ua.win && ua.ie) {
32890             ac.innerHTML = obj.innerHTML;
32891         }
32892         else {
32893             var nestedObj = obj.getElementsByTagName(OBJECT)[0];
32894             if (nestedObj) {
32895                 var c = nestedObj.childNodes;
32896                 if (c) {
32897                     var cl = c.length;
32898                     for (var i = 0; i < cl; i++) {
32899                         if (!(c[i].nodeType == 1 && c[i].nodeName == "PARAM") && !(c[i].nodeType == 8)) {
32900                             ac.appendChild(c[i].cloneNode(true));
32901                         }
32902                     }
32903                 }
32904             }
32905         }
32906         return ac;
32907     }
32908     
32909     
32910     function createSWF(attObj, parObj, id) {
32911         var r, el = getElementById(id);
32912         if (ua.wk && ua.wk < 312) { return r; }
32913         if (el) {
32914             if (typeof attObj.id == UNDEF) { 
32915                 attObj.id = id;
32916             }
32917             if (ua.ie && ua.win) { 
32918                 var att = "";
32919                 for (var i in attObj) {
32920                     if (attObj[i] != Object.prototype[i]) { 
32921                         if (i.toLowerCase() == "data") {
32922                             parObj.movie = attObj[i];
32923                         }
32924                         else if (i.toLowerCase() == "styleclass") { 
32925                             att += ' class="' + attObj[i] + '"';
32926                         }
32927                         else if (i.toLowerCase() != "classid") {
32928                             att += ' ' + i + '="' + attObj[i] + '"';
32929                         }
32930                     }
32931                 }
32932                 var par = "";
32933                 for (var j in parObj) {
32934                     if (parObj[j] != Object.prototype[j]) { 
32935                         par += '<param name="' + j + '" value="' + parObj[j] + '" />';
32936                     }
32937                 }
32938                 el.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' + att + '>' + par + '</object>';
32939                 objIdArr[objIdArr.length] = attObj.id; 
32940                 r = getElementById(attObj.id);  
32941             }
32942             else { 
32943                 var o = createElement(OBJECT);
32944                 o.setAttribute("type", FLASH_MIME_TYPE);
32945                 for (var m in attObj) {
32946                     if (attObj[m] != Object.prototype[m]) { 
32947                         if (m.toLowerCase() == "styleclass") { 
32948                             o.setAttribute("class", attObj[m]);
32949                         }
32950                         else if (m.toLowerCase() != "classid") { 
32951                             o.setAttribute(m, attObj[m]);
32952                         }
32953                     }
32954                 }
32955                 for (var n in parObj) {
32956                     if (parObj[n] != Object.prototype[n] && n.toLowerCase() != "movie") { 
32957                         createObjParam(o, n, parObj[n]);
32958                     }
32959                 }
32960                 el.parentNode.replaceChild(o, el);
32961                 r = o;
32962             }
32963         }
32964         return r;
32965     }
32966     
32967     function createObjParam(el, pName, pValue) {
32968         var p = createElement("param");
32969         p.setAttribute("name", pName);  
32970         p.setAttribute("value", pValue);
32971         el.appendChild(p);
32972     }
32973     
32974     
32975     function removeSWF(id) {
32976         var obj = getElementById(id);
32977         if (obj && obj.nodeName == "OBJECT") {
32978             if (ua.ie && ua.win) {
32979                 obj.style.display = "none";
32980                 (function(){
32981                     if (obj.readyState == 4) {
32982                         removeObjectInIE(id);
32983                     }
32984                     else {
32985                         setTimeout(arguments.callee, 10);
32986                     }
32987                 })();
32988             }
32989             else {
32990                 obj.parentNode.removeChild(obj);
32991             }
32992         }
32993     }
32994     
32995     function removeObjectInIE(id) {
32996         var obj = getElementById(id);
32997         if (obj) {
32998             for (var i in obj) {
32999                 if (typeof obj[i] == "function") {
33000                     obj[i] = null;
33001                 }
33002             }
33003             obj.parentNode.removeChild(obj);
33004         }
33005     }
33006     
33007     
33008     function getElementById(id) {
33009         var el = null;
33010         try {
33011             el = doc.getElementById(id);
33012         }
33013         catch (e) {}
33014         return el;
33015     }
33016     
33017     function createElement(el) {
33018         return doc.createElement(el);
33019     }
33020     
33021       
33022     function addListener(target, eventType, fn) {
33023         target.attachEvent(eventType, fn);
33024         listenersArr[listenersArr.length] = [target, eventType, fn];
33025     }
33026     
33027     
33028     function hasPlayerVersion(rv) {
33029         var pv = ua.pv, v = rv.split(".");
33030         v[0] = parseInt(v[0], 10);
33031         v[1] = parseInt(v[1], 10) || 0; 
33032         v[2] = parseInt(v[2], 10) || 0;
33033         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;
33034     }
33035     
33036       
33037     function createCSS(sel, decl, media, newStyle) {
33038         if (ua.ie && ua.mac) { return; }
33039         var h = doc.getElementsByTagName("head")[0];
33040         if (!h) { return; } 
33041         var m = (media && typeof media == "string") ? media : "screen";
33042         if (newStyle) {
33043             dynamicStylesheet = null;
33044             dynamicStylesheetMedia = null;
33045         }
33046         if (!dynamicStylesheet || dynamicStylesheetMedia != m) { 
33047             
33048             var s = createElement("style");
33049             s.setAttribute("type", "text/css");
33050             s.setAttribute("media", m);
33051             dynamicStylesheet = h.appendChild(s);
33052             if (ua.ie && ua.win && typeof doc.styleSheets != UNDEF && doc.styleSheets.length > 0) {
33053                 dynamicStylesheet = doc.styleSheets[doc.styleSheets.length - 1];
33054             }
33055             dynamicStylesheetMedia = m;
33056         }
33057         
33058         if (ua.ie && ua.win) {
33059             if (dynamicStylesheet && typeof dynamicStylesheet.addRule == OBJECT) {
33060                 dynamicStylesheet.addRule(sel, decl);
33061             }
33062         }
33063         else {
33064             if (dynamicStylesheet && typeof doc.createTextNode != UNDEF) {
33065                 dynamicStylesheet.appendChild(doc.createTextNode(sel + " {" + decl + "}"));
33066             }
33067         }
33068     }
33069     
33070     function setVisibility(id, isVisible) {
33071         if (!autoHideShow) { return; }
33072         var v = isVisible ? "visible" : "hidden";
33073         if (isDomLoaded && getElementById(id)) {
33074             getElementById(id).style.visibility = v;
33075         }
33076         else {
33077             createCSS("#" + id, "visibility:" + v);
33078         }
33079     }
33080
33081     
33082     function urlEncodeIfNecessary(s) {
33083         var regex = /[\\\"<>\.;]/;
33084         var hasBadChars = regex.exec(s) != null;
33085         return hasBadChars && typeof encodeURIComponent != UNDEF ? encodeURIComponent(s) : s;
33086     }
33087     
33088     
33089     var cleanup = function() {
33090         if (ua.ie && ua.win) {
33091             window.attachEvent("onunload", function() {
33092                 
33093                 var ll = listenersArr.length;
33094                 for (var i = 0; i < ll; i++) {
33095                     listenersArr[i][0].detachEvent(listenersArr[i][1], listenersArr[i][2]);
33096                 }
33097                 
33098                 var il = objIdArr.length;
33099                 for (var j = 0; j < il; j++) {
33100                     removeSWF(objIdArr[j]);
33101                 }
33102                 
33103                 for (var k in ua) {
33104                     ua[k] = null;
33105                 }
33106                 ua = null;
33107                 for (var l in swfobject) {
33108                     swfobject[l] = null;
33109                 }
33110                 swfobject = null;
33111             });
33112         }
33113     }();
33114     
33115     return {
33116          
33117         registerObject: function(objectIdStr, swfVersionStr, xiSwfUrlStr, callbackFn) {
33118             if (ua.w3 && objectIdStr && swfVersionStr) {
33119                 var regObj = {};
33120                 regObj.id = objectIdStr;
33121                 regObj.swfVersion = swfVersionStr;
33122                 regObj.expressInstall = xiSwfUrlStr;
33123                 regObj.callbackFn = callbackFn;
33124                 regObjArr[regObjArr.length] = regObj;
33125                 setVisibility(objectIdStr, false);
33126             }
33127             else if (callbackFn) {
33128                 callbackFn({success:false, id:objectIdStr});
33129             }
33130         },
33131         
33132         getObjectById: function(objectIdStr) {
33133             if (ua.w3) {
33134                 return getObjectById(objectIdStr);
33135             }
33136         },
33137         
33138         embedSWF: function(swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr, xiSwfUrlStr, flashvarsObj, parObj, attObj, callbackFn) {
33139             var callbackObj = {success:false, id:replaceElemIdStr};
33140             if (ua.w3 && !(ua.wk && ua.wk < 312) && swfUrlStr && replaceElemIdStr && widthStr && heightStr && swfVersionStr) {
33141                 setVisibility(replaceElemIdStr, false);
33142                 addDomLoadEvent(function() {
33143                     widthStr += ""; 
33144                     heightStr += "";
33145                     var att = {};
33146                     if (attObj && typeof attObj === OBJECT) {
33147                         for (var i in attObj) { 
33148                             att[i] = attObj[i];
33149                         }
33150                     }
33151                     att.data = swfUrlStr;
33152                     att.width = widthStr;
33153                     att.height = heightStr;
33154                     var par = {}; 
33155                     if (parObj && typeof parObj === OBJECT) {
33156                         for (var j in parObj) { 
33157                             par[j] = parObj[j];
33158                         }
33159                     }
33160                     if (flashvarsObj && typeof flashvarsObj === OBJECT) {
33161                         for (var k in flashvarsObj) { 
33162                             if (typeof par.flashvars != UNDEF) {
33163                                 par.flashvars += "&" + k + "=" + flashvarsObj[k];
33164                             }
33165                             else {
33166                                 par.flashvars = k + "=" + flashvarsObj[k];
33167                             }
33168                         }
33169                     }
33170                     if (hasPlayerVersion(swfVersionStr)) { 
33171                         var obj = createSWF(att, par, replaceElemIdStr);
33172                         if (att.id == replaceElemIdStr) {
33173                             setVisibility(replaceElemIdStr, true);
33174                         }
33175                         callbackObj.success = true;
33176                         callbackObj.ref = obj;
33177                     }
33178                     else if (xiSwfUrlStr && canExpressInstall()) { 
33179                         att.data = xiSwfUrlStr;
33180                         showExpressInstall(att, par, replaceElemIdStr, callbackFn);
33181                         return;
33182                     }
33183                     else { 
33184                         setVisibility(replaceElemIdStr, true);
33185                     }
33186                     if (callbackFn) { callbackFn(callbackObj); }
33187                 });
33188             }
33189             else if (callbackFn) { callbackFn(callbackObj); }
33190         },
33191         
33192         switchOffAutoHideShow: function() {
33193             autoHideShow = false;
33194         },
33195         
33196         ua: ua,
33197         
33198         getFlashPlayerVersion: function() {
33199             return { major:ua.pv[0], minor:ua.pv[1], release:ua.pv[2] };
33200         },
33201         
33202         hasFlashPlayerVersion: hasPlayerVersion,
33203         
33204         createSWF: function(attObj, parObj, replaceElemIdStr) {
33205             if (ua.w3) {
33206                 return createSWF(attObj, parObj, replaceElemIdStr);
33207             }
33208             else {
33209                 return undefined;
33210             }
33211         },
33212         
33213         showExpressInstall: function(att, par, replaceElemIdStr, callbackFn) {
33214             if (ua.w3 && canExpressInstall()) {
33215                 showExpressInstall(att, par, replaceElemIdStr, callbackFn);
33216             }
33217         },
33218         
33219         removeSWF: function(objElemIdStr) {
33220             if (ua.w3) {
33221                 removeSWF(objElemIdStr);
33222             }
33223         },
33224         
33225         createCSS: function(selStr, declStr, mediaStr, newStyleBoolean) {
33226             if (ua.w3) {
33227                 createCSS(selStr, declStr, mediaStr, newStyleBoolean);
33228             }
33229         },
33230         
33231         addDomLoadEvent: addDomLoadEvent,
33232         
33233         addLoadEvent: addLoadEvent,
33234         
33235         getQueryParamValue: function(param) {
33236             var q = doc.location.search || doc.location.hash;
33237             if (q) {
33238                 if (/\?/.test(q)) { q = q.split("?")[1]; } 
33239                 if (param == null) {
33240                     return urlEncodeIfNecessary(q);
33241                 }
33242                 var pairs = q.split("&");
33243                 for (var i = 0; i < pairs.length; i++) {
33244                     if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) {
33245                         return urlEncodeIfNecessary(pairs[i].substring((pairs[i].indexOf("=") + 1)));
33246                     }
33247                 }
33248             }
33249             return "";
33250         },
33251         
33252         
33253         expressInstallCallback: function() {
33254             if (isExpressInstallActive) {
33255                 var obj = getElementById(EXPRESS_INSTALL_ID);
33256                 if (obj && storedAltContent) {
33257                     obj.parentNode.replaceChild(storedAltContent, obj);
33258                     if (storedAltContentId) {
33259                         setVisibility(storedAltContentId, true);
33260                         if (ua.ie && ua.win) { storedAltContent.style.display = "block"; }
33261                     }
33262                     if (storedCallbackFn) { storedCallbackFn(storedCallbackObj); }
33263                 }
33264                 isExpressInstallActive = false;
33265             } 
33266         }
33267     };
33268 }();
33269
33270 Ext.FlashComponent = Ext.extend(Ext.BoxComponent, {
33271     
33272     flashVersion : '9.0.115',
33273
33274     
33275     backgroundColor: '#ffffff',
33276
33277     
33278     wmode: 'opaque',
33279     
33280     
33281     flashVars: undefined,
33282     
33283     
33284     flashParams: undefined,
33285
33286     
33287     url: undefined,
33288     swfId : undefined,
33289     swfWidth: '100%',
33290     swfHeight: '100%',
33291
33292     
33293     expressInstall: false,
33294
33295     initComponent : function(){
33296         Ext.FlashComponent.superclass.initComponent.call(this);
33297
33298         this.addEvents(
33299             
33300             'initialize'
33301         );
33302     },
33303
33304     onRender : function(){
33305         Ext.FlashComponent.superclass.onRender.apply(this, arguments);
33306
33307         var params = Ext.apply({
33308             allowScriptAccess: 'always',
33309             bgcolor: this.backgroundColor,
33310             wmode: this.wmode
33311         }, this.flashParams), vars = Ext.apply({
33312             allowedDomain: document.location.hostname,
33313             elementID: this.getId(),
33314             eventHandler: 'Ext.FlashEventProxy.onEvent'
33315         }, this.flashVars);
33316
33317         new swfobject.embedSWF(this.url, this.id, this.swfWidth, this.swfHeight, this.flashVersion,
33318             this.expressInstall ? Ext.FlashComponent.EXPRESS_INSTALL_URL : undefined, vars, params);
33319
33320         this.swf = Ext.getDom(this.id);
33321         this.el = Ext.get(this.swf);
33322     },
33323
33324     getSwfId : function(){
33325         return this.swfId || (this.swfId = "extswf" + (++Ext.Component.AUTO_ID));
33326     },
33327
33328     getId : function(){
33329         return this.id || (this.id = "extflashcmp" + (++Ext.Component.AUTO_ID));
33330     },
33331
33332     onFlashEvent : function(e){
33333         switch(e.type){
33334             case "swfReady":
33335                 this.initSwf();
33336                 return;
33337             case "log":
33338                 return;
33339         }
33340         e.component = this;
33341         this.fireEvent(e.type.toLowerCase().replace(/event$/, ''), e);
33342     },
33343
33344     initSwf : function(){
33345         this.onSwfReady(!!this.isInitialized);
33346         this.isInitialized = true;
33347         this.fireEvent('initialize', this);
33348     },
33349
33350     beforeDestroy: function(){
33351         if(this.rendered){
33352             swfobject.removeSWF(this.swf.id);
33353         }
33354         Ext.FlashComponent.superclass.beforeDestroy.call(this);
33355     },
33356
33357     onSwfReady : Ext.emptyFn
33358 });
33359
33360
33361 Ext.FlashComponent.EXPRESS_INSTALL_URL = 'http:/' + '/swfobject.googlecode.com/svn/trunk/swfobject/expressInstall.swf';
33362
33363 Ext.reg('flash', Ext.FlashComponent);
33364 Ext.FlashEventProxy = {
33365     onEvent : function(id, e){
33366         var fp = Ext.getCmp(id);
33367         if(fp){
33368             fp.onFlashEvent(e);
33369         }else{
33370             arguments.callee.defer(10, this, [id, e]);
33371         }
33372     }
33373 }
33374  
33375  Ext.chart.Chart = Ext.extend(Ext.FlashComponent, {
33376     refreshBuffer: 100,
33377     
33378     
33379
33380     
33381     chartStyle: {
33382         padding: 10,
33383         animationEnabled: true,
33384         font: {
33385             name: 'Tahoma',
33386             color: 0x444444,
33387             size: 11
33388         },
33389         dataTip: {
33390             padding: 5,
33391             border: {
33392                 color: 0x99bbe8,
33393                 size:1
33394             },
33395             background: {
33396                 color: 0xDAE7F6,
33397                 alpha: .9
33398             },
33399             font: {
33400                 name: 'Tahoma',
33401                 color: 0x15428B,
33402                 size: 10,
33403                 bold: true
33404             }
33405         }
33406     },
33407     
33408     
33409     
33410     
33411     extraStyle: null,
33412     
33413     
33414     seriesStyles: null,
33415     
33416     
33417     disableCaching: Ext.isIE || Ext.isOpera,
33418     disableCacheParam: '_dc',
33419
33420     initComponent : function(){
33421         Ext.chart.Chart.superclass.initComponent.call(this);
33422         if(!this.url){
33423             this.url = Ext.chart.Chart.CHART_URL;
33424         }
33425         if(this.disableCaching){
33426             this.url = Ext.urlAppend(this.url, String.format('{0}={1}', this.disableCacheParam, new Date().getTime()));
33427         }
33428         this.addEvents(
33429             'itemmouseover',
33430             'itemmouseout',
33431             'itemclick',
33432             'itemdoubleclick',
33433             'itemdragstart',
33434             'itemdrag',
33435             'itemdragend',
33436             
33437             'beforerefresh',
33438             
33439             'refresh'
33440         );
33441         this.store = Ext.StoreMgr.lookup(this.store);
33442     },
33443
33444     
33445      setStyle: function(name, value){
33446          this.swf.setStyle(name, Ext.encode(value));
33447      },
33448
33449     
33450     setStyles: function(styles){
33451         this.swf.setStyles(Ext.encode(styles));
33452     },
33453
33454     
33455     setSeriesStyles: function(styles){
33456         this.seriesStyles = styles;
33457         var s = [];
33458         Ext.each(styles, function(style){
33459             s.push(Ext.encode(style));
33460         });
33461         this.swf.setSeriesStyles(s);
33462     },
33463
33464     setCategoryNames : function(names){
33465         this.swf.setCategoryNames(names);
33466     },
33467
33468     setTipRenderer : function(fn){
33469         var chart = this;
33470         this.tipFnName = this.createFnProxy(function(item, index, series){
33471             var record = chart.store.getAt(index);
33472             return fn(chart, record, index, series);
33473         }, this.tipFnName);
33474         this.swf.setDataTipFunction(this.tipFnName);
33475     },
33476
33477     setSeries : function(series){
33478         this.series = series;
33479         this.refresh();
33480     },
33481
33482     
33483     bindStore : function(store, initial){
33484         if(!initial && this.store){
33485             if(store !== this.store && this.store.autoDestroy){
33486                 this.store.destroy();
33487             }else{
33488                 this.store.un("datachanged", this.refresh, this);
33489                 this.store.un("add", this.delayRefresh, this);
33490                 this.store.un("remove", this.delayRefresh, this);
33491                 this.store.un("update", this.delayRefresh, this);
33492                 this.store.un("clear", this.refresh, this);
33493             }
33494         }
33495         if(store){
33496             store = Ext.StoreMgr.lookup(store);
33497             store.on({
33498                 scope: this,
33499                 datachanged: this.refresh,
33500                 add: this.delayRefresh,
33501                 remove: this.delayRefresh,
33502                 update: this.delayRefresh,
33503                 clear: this.refresh
33504             });
33505         }
33506         this.store = store;
33507         if(store && !initial){
33508             this.refresh();
33509         }
33510     },
33511
33512     onSwfReady : function(isReset){
33513         Ext.chart.Chart.superclass.onSwfReady.call(this, isReset);
33514         this.swf.setType(this.type);
33515
33516         if(this.chartStyle){
33517             this.setStyles(Ext.apply({}, this.extraStyle, this.chartStyle));
33518         }
33519
33520         if(this.categoryNames){
33521             this.setCategoryNames(this.categoryNames);
33522         }
33523
33524         if(this.tipRenderer){
33525             this.setTipRenderer(this.tipRenderer);
33526         }
33527         if(!isReset){
33528             this.bindStore(this.store, true);
33529         }
33530         this.refresh.defer(10, this);
33531     },
33532
33533     delayRefresh : function(){
33534         if(!this.refreshTask){
33535             this.refreshTask = new Ext.util.DelayedTask(this.refresh, this);
33536         }
33537         this.refreshTask.delay(this.refreshBuffer);
33538     },
33539
33540     refresh : function(){
33541         if(this.fireEvent('beforerefresh', this) !== false){
33542                 var styleChanged = false;
33543                 
33544                 var data = [], rs = this.store.data.items;
33545                 for(var j = 0, len = rs.length; j < len; j++){
33546                     data[j] = rs[j].data;
33547                 }
33548                 
33549                 
33550                 var dataProvider = [];
33551                 var seriesCount = 0;
33552                 var currentSeries = null;
33553                 var i = 0;
33554                 if(this.series){
33555                     seriesCount = this.series.length;
33556                     for(i = 0; i < seriesCount; i++){
33557                         currentSeries = this.series[i];
33558                         var clonedSeries = {};
33559                         for(var prop in currentSeries){
33560                             if(prop == "style" && currentSeries.style !== null){
33561                                 clonedSeries.style = Ext.encode(currentSeries.style);
33562                                 styleChanged = true;
33563                                 
33564                                 
33565                                 
33566                                 
33567                             } else{
33568                                 clonedSeries[prop] = currentSeries[prop];
33569                             }
33570                         }
33571                         dataProvider.push(clonedSeries);
33572                     }
33573                 }
33574         
33575                 if(seriesCount > 0){
33576                     for(i = 0; i < seriesCount; i++){
33577                         currentSeries = dataProvider[i];
33578                         if(!currentSeries.type){
33579                             currentSeries.type = this.type;
33580                         }
33581                         currentSeries.dataProvider = data;
33582                     }
33583                 } else{
33584                     dataProvider.push({type: this.type, dataProvider: data});
33585                 }
33586                 this.swf.setDataProvider(dataProvider);
33587                 if(this.seriesStyles){
33588                     this.setSeriesStyles(this.seriesStyles);
33589                 }
33590             this.fireEvent('refresh', this);
33591         }
33592     },
33593
33594     createFnProxy : function(fn, old){
33595         if(old){
33596             delete window[old];
33597         }
33598         var fnName = "extFnProxy" + (++Ext.chart.Chart.PROXY_FN_ID);
33599         window[fnName] = fn;
33600         return fnName;
33601     },
33602     
33603     onDestroy: function(){
33604         Ext.chart.Chart.superclass.onDestroy.call(this);
33605         this.bindStore(null);
33606         var tip = this.tipFnName;
33607         if(!Ext.isEmpty(tip)){
33608             delete window[tip];
33609         }
33610     }
33611 });
33612 Ext.reg('chart', Ext.chart.Chart);
33613 Ext.chart.Chart.PROXY_FN_ID = 0;
33614
33615
33616 Ext.chart.Chart.CHART_URL = 'http:/' + '/yui.yahooapis.com/2.7.0/build/charts/assets/charts.swf';
33617
33618
33619 Ext.chart.PieChart = Ext.extend(Ext.chart.Chart, {
33620     type: 'pie',
33621
33622     onSwfReady : function(isReset){
33623         Ext.chart.PieChart.superclass.onSwfReady.call(this, isReset);
33624
33625         this.setDataField(this.dataField);
33626         this.setCategoryField(this.categoryField);
33627     },
33628
33629     setDataField : function(field){
33630         this.dataField = field;
33631         this.swf.setDataField(field);
33632     },
33633
33634     setCategoryField : function(field){
33635         this.categoryField = field;
33636         this.swf.setCategoryField(field);
33637     }
33638 });
33639 Ext.reg('piechart', Ext.chart.PieChart);
33640
33641
33642 Ext.chart.CartesianChart = Ext.extend(Ext.chart.Chart, {
33643     onSwfReady : function(isReset){
33644         Ext.chart.CartesianChart.superclass.onSwfReady.call(this, isReset);
33645
33646         if(this.xField){
33647             this.setXField(this.xField);
33648         }
33649         if(this.yField){
33650             this.setYField(this.yField);
33651         }
33652         if(this.xAxis){
33653             this.setXAxis(this.xAxis);
33654         }
33655         if(this.yAxis){
33656             this.setYAxis(this.yAxis);
33657         }
33658     },
33659
33660     setXField : function(value){
33661         this.xField = value;
33662         this.swf.setHorizontalField(value);
33663     },
33664
33665     setYField : function(value){
33666         this.yField = value;
33667         this.swf.setVerticalField(value);
33668     },
33669
33670     setXAxis : function(value){
33671         this.xAxis = this.createAxis('xAxis', value);
33672         this.swf.setHorizontalAxis(this.xAxis);
33673     },
33674
33675     setYAxis : function(value){
33676         this.yAxis = this.createAxis('yAxis', value);
33677         this.swf.setVerticalAxis(this.yAxis);
33678     },
33679
33680     createAxis : function(axis, value){
33681         var o = Ext.apply({}, value), oldFn = null;
33682         if(this[axis]){
33683             oldFn = this[axis].labelFunction;
33684         }
33685         if(o.labelRenderer){
33686             var fn = o.labelRenderer;
33687             o.labelFunction = this.createFnProxy(function(v){
33688                 return fn(v);
33689             }, oldFn);
33690             delete o.labelRenderer;
33691         }
33692         return o;
33693     }
33694 });
33695 Ext.reg('cartesianchart', Ext.chart.CartesianChart);
33696
33697
33698 Ext.chart.LineChart = Ext.extend(Ext.chart.CartesianChart, {
33699     type: 'line'
33700 });
33701 Ext.reg('linechart', Ext.chart.LineChart);
33702
33703
33704 Ext.chart.ColumnChart = Ext.extend(Ext.chart.CartesianChart, {
33705     type: 'column'
33706 });
33707 Ext.reg('columnchart', Ext.chart.ColumnChart);
33708
33709
33710 Ext.chart.StackedColumnChart = Ext.extend(Ext.chart.CartesianChart, {
33711     type: 'stackcolumn'
33712 });
33713 Ext.reg('stackedcolumnchart', Ext.chart.StackedColumnChart);
33714
33715
33716 Ext.chart.BarChart = Ext.extend(Ext.chart.CartesianChart, {
33717     type: 'bar'
33718 });
33719 Ext.reg('barchart', Ext.chart.BarChart);
33720
33721
33722 Ext.chart.StackedBarChart = Ext.extend(Ext.chart.CartesianChart, {
33723     type: 'stackbar'
33724 });
33725 Ext.reg('stackedbarchart', Ext.chart.StackedBarChart);
33726
33727
33728
33729
33730 Ext.chart.Axis = function(config){
33731     Ext.apply(this, config);
33732 };
33733
33734 Ext.chart.Axis.prototype =
33735 {
33736     
33737     type: null,
33738
33739     
33740     orientation: "horizontal",
33741
33742     
33743     reverse: false,
33744
33745     
33746     labelFunction: null,
33747
33748     
33749     hideOverlappingLabels: true
33750 };
33751
33752
33753 Ext.chart.NumericAxis = Ext.extend(Ext.chart.Axis, {
33754     type: "numeric",
33755
33756     
33757     minimum: NaN,
33758
33759     
33760     maximum: NaN,
33761
33762     
33763     majorUnit: NaN,
33764
33765     
33766     minorUnit: NaN,
33767
33768     
33769     snapToUnits: true,
33770
33771     
33772     alwaysShowZero: true,
33773
33774     
33775     scale: "linear"
33776 });
33777
33778
33779 Ext.chart.TimeAxis = Ext.extend(Ext.chart.Axis, {
33780     type: "time",
33781
33782     
33783     minimum: null,
33784
33785     
33786     maximum: null,
33787
33788     
33789     majorUnit: NaN,
33790
33791     
33792     majorTimeUnit: null,
33793
33794     
33795     minorUnit: NaN,
33796
33797     
33798     minorTimeUnit: null,
33799
33800     
33801     snapToUnits: true
33802 });
33803
33804
33805 Ext.chart.CategoryAxis = Ext.extend(Ext.chart.Axis, {
33806     type: "category",
33807
33808     
33809     categoryNames: null
33810 });
33811
33812
33813 Ext.chart.Series = function(config) { Ext.apply(this, config); };
33814
33815 Ext.chart.Series.prototype =
33816 {
33817     
33818     type: null,
33819
33820     
33821     displayName: null
33822 };
33823
33824
33825 Ext.chart.CartesianSeries = Ext.extend(Ext.chart.Series, {
33826     
33827     xField: null,
33828
33829     
33830     yField: null
33831 });
33832
33833
33834 Ext.chart.ColumnSeries = Ext.extend(Ext.chart.CartesianSeries, {
33835     type: "column"
33836 });
33837
33838
33839 Ext.chart.LineSeries = Ext.extend(Ext.chart.CartesianSeries, {
33840     type: "line"
33841 });
33842
33843
33844 Ext.chart.BarSeries = Ext.extend(Ext.chart.CartesianSeries, {
33845     type: "bar"
33846 });
33847
33848
33849
33850 Ext.chart.PieSeries = Ext.extend(Ext.chart.Series, {
33851     type: "pie",
33852     dataField: null,
33853     categoryField: null
33854 });
33855  Ext.layout.MenuLayout = Ext.extend(Ext.layout.ContainerLayout, {
33856     monitorResize : true,
33857
33858     setContainer : function(ct){
33859         this.monitorResize = !ct.floating;
33860         
33861         
33862         ct.on('autosize', this.doAutoSize, this);
33863         Ext.layout.MenuLayout.superclass.setContainer.call(this, ct);
33864     },
33865
33866     renderItem : function(c, position, target){
33867         if (!this.itemTpl) {
33868             this.itemTpl = Ext.layout.MenuLayout.prototype.itemTpl = new Ext.XTemplate(
33869                 '<li id="{itemId}" class="{itemCls}">',
33870                     '<tpl if="needsIcon">',
33871                         '<img src="{icon}" class="{iconCls}"/>',
33872                     '</tpl>',
33873                 '</li>'
33874             );
33875         }
33876
33877         if(c && !c.rendered){
33878             if(Ext.isNumber(position)){
33879                 position = target.dom.childNodes[position];
33880             }
33881             var a = this.getItemArgs(c);
33882
33883
33884             c.render(c.positionEl = position ?
33885                 this.itemTpl.insertBefore(position, a, true) :
33886                 this.itemTpl.append(target, a, true));
33887
33888
33889             c.positionEl.menuItemId = c.getItemId();
33890
33891
33892
33893             if (!a.isMenuItem && a.needsIcon) {
33894                 c.positionEl.addClass('x-menu-list-item-indent');
33895             }
33896             this.configureItem(c, position);
33897         }else if(c && !this.isValidParent(c, target)){
33898             if(Ext.isNumber(position)){
33899                 position = target.dom.childNodes[position];
33900             }
33901             target.dom.insertBefore(c.getActionEl().dom, position || null);
33902         }
33903     },
33904
33905     getItemArgs : function(c) {
33906         var isMenuItem = c instanceof Ext.menu.Item;
33907         return {
33908             isMenuItem: isMenuItem,
33909             needsIcon: !isMenuItem && (c.icon || c.iconCls),
33910             icon: c.icon || Ext.BLANK_IMAGE_URL,
33911             iconCls: 'x-menu-item-icon ' + (c.iconCls || ''),
33912             itemId: 'x-menu-el-' + c.id,
33913             itemCls: 'x-menu-list-item '
33914         };
33915     },
33916
33917
33918     isValidParent : function(c, target) {
33919         return c.el.up('li.x-menu-list-item', 5).dom.parentNode === (target.dom || target);
33920     },
33921
33922     onLayout : function(ct, target){
33923         this.renderAll(ct, target);
33924         this.doAutoSize();
33925     },
33926
33927     doAutoSize : function(){
33928         var ct = this.container, w = ct.width;
33929         if(ct.floating){
33930             if(w){
33931                 ct.setWidth(w);
33932             }else if(Ext.isIE){
33933                 ct.setWidth(Ext.isStrict && (Ext.isIE7 || Ext.isIE8) ? 'auto' : ct.minWidth);
33934                 var el = ct.getEl(), t = el.dom.offsetWidth; 
33935                 ct.setWidth(ct.getLayoutTarget().getWidth() + el.getFrameWidth('lr'));
33936             }
33937         }
33938     }
33939 });
33940 Ext.Container.LAYOUTS['menu'] = Ext.layout.MenuLayout;
33941
33942
33943 Ext.menu.Menu = Ext.extend(Ext.Container, {
33944     
33945     
33946     
33947     minWidth : 120,
33948     
33949     shadow : 'sides',
33950     
33951     subMenuAlign : 'tl-tr?',
33952     
33953     defaultAlign : 'tl-bl?',
33954     
33955     allowOtherMenus : false,
33956     
33957     ignoreParentClicks : false,
33958     
33959     enableScrolling : true,
33960     
33961     maxHeight : null,
33962     
33963     scrollIncrement : 24,
33964     
33965     showSeparator : true,
33966     
33967     defaultOffsets : [0, 0],
33968
33969     
33970     plain : false,
33971
33972     
33973     floating : true,
33974
33975     
33976     hidden : true,
33977
33978     
33979     layout : 'menu',
33980     hideMode : 'offsets',    
33981     scrollerHeight : 8,
33982     autoLayout : true,       
33983     defaultType : 'menuitem',
33984     bufferResize : false,
33985
33986     initComponent : function(){
33987         if(Ext.isArray(this.initialConfig)){
33988             Ext.apply(this, {items:this.initialConfig});
33989         }
33990         this.addEvents(
33991             
33992             'click',
33993             
33994             'mouseover',
33995             
33996             'mouseout',
33997             
33998             'itemclick'
33999         );
34000         Ext.menu.MenuMgr.register(this);
34001         if(this.floating){
34002             Ext.EventManager.onWindowResize(this.hide, this);
34003         }else{
34004             if(this.initialConfig.hidden !== false){
34005                 this.hidden = false;
34006             }
34007             this.internalDefaults = {hideOnClick: false};
34008         }
34009         Ext.menu.Menu.superclass.initComponent.call(this);
34010         if(this.autoLayout){
34011             this.on({
34012                 add: this.doLayout,
34013                 remove: this.doLayout,
34014                 scope: this
34015             });
34016         }
34017     },
34018
34019     
34020     getLayoutTarget : function() {
34021         return this.ul;
34022     },
34023
34024     
34025     onRender : function(ct, position){
34026         if(!ct){
34027             ct = Ext.getBody();
34028         }
34029
34030         var dh = {
34031             id: this.getId(),
34032             cls: 'x-menu ' + ((this.floating) ? 'x-menu-floating x-layer ' : '') + (this.cls || '') + (this.plain ? ' x-menu-plain' : '') + (this.showSeparator ? '' : ' x-menu-nosep'),
34033             style: this.style,
34034             cn: [
34035                 {tag: 'a', cls: 'x-menu-focus', href: '#', onclick: 'return false;', tabIndex: '-1'},
34036                 {tag: 'ul', cls: 'x-menu-list'}
34037             ]
34038         };
34039         if(this.floating){
34040             this.el = new Ext.Layer({
34041                 shadow: this.shadow,
34042                 dh: dh,
34043                 constrain: false,
34044                 parentEl: ct,
34045                 zindex:15000
34046             });
34047         }else{
34048             this.el = ct.createChild(dh);
34049         }
34050         Ext.menu.Menu.superclass.onRender.call(this, ct, position);
34051
34052         if(!this.keyNav){
34053             this.keyNav = new Ext.menu.MenuNav(this);
34054         }
34055         
34056         this.focusEl = this.el.child('a.x-menu-focus');
34057         this.ul = this.el.child('ul.x-menu-list');
34058         this.mon(this.ul, {
34059             scope: this,
34060             click: this.onClick,
34061             mouseover: this.onMouseOver,
34062             mouseout: this.onMouseOut
34063         });
34064         if(this.enableScrolling){
34065             this.mon(this.el, {
34066                 scope: this,
34067                 delegate: '.x-menu-scroller',
34068                 click: this.onScroll,
34069                 mouseover: this.deactivateActive
34070             });
34071         }
34072     },
34073
34074     
34075     findTargetItem : function(e){
34076         var t = e.getTarget('.x-menu-list-item', this.ul, true);
34077         if(t && t.menuItemId){
34078             return this.items.get(t.menuItemId);
34079         }
34080     },
34081
34082     
34083     onClick : function(e){
34084         var t = this.findTargetItem(e);
34085         if(t){
34086             if(t.isFormField){
34087                 this.setActiveItem(t);
34088             }else if(t instanceof Ext.menu.BaseItem){
34089                 if(t.menu && this.ignoreParentClicks){
34090                     t.expandMenu();
34091                     e.preventDefault();
34092                 }else if(t.onClick){
34093                     t.onClick(e);
34094                     this.fireEvent('click', this, t, e);
34095                 }
34096             }
34097         }
34098     },
34099
34100     
34101     setActiveItem : function(item, autoExpand){
34102         if(item != this.activeItem){
34103             this.deactivateActive();
34104             if((this.activeItem = item).isFormField){
34105                 item.focus();
34106             }else{
34107                 item.activate(autoExpand);
34108             }
34109         }else if(autoExpand){
34110             item.expandMenu();
34111         }
34112     },
34113
34114     deactivateActive : function(){
34115         var a = this.activeItem;
34116         if(a){
34117             if(a.isFormField){
34118                 
34119                 if(a.collapse){
34120                     a.collapse();
34121                 }
34122             }else{
34123                 a.deactivate();
34124             }
34125             delete this.activeItem;
34126         }
34127     },
34128
34129     
34130     tryActivate : function(start, step){
34131         var items = this.items;
34132         for(var i = start, len = items.length; i >= 0 && i < len; i+= step){
34133             var item = items.get(i);
34134             if(!item.disabled && (item.canActivate || item.isFormField)){
34135                 this.setActiveItem(item, false);
34136                 return item;
34137             }
34138         }
34139         return false;
34140     },
34141
34142     
34143     onMouseOver : function(e){
34144         var t = this.findTargetItem(e);
34145         if(t){
34146             if(t.canActivate && !t.disabled){
34147                 this.setActiveItem(t, true);
34148             }
34149         }
34150         this.over = true;
34151         this.fireEvent('mouseover', this, e, t);
34152     },
34153
34154     
34155     onMouseOut : function(e){
34156         var t = this.findTargetItem(e);
34157         if(t){
34158             if(t == this.activeItem && t.shouldDeactivate && t.shouldDeactivate(e)){
34159                 this.activeItem.deactivate();
34160                 delete this.activeItem;
34161             }
34162         }
34163         this.over = false;
34164         this.fireEvent('mouseout', this, e, t);
34165     },
34166
34167     
34168     onScroll : function(e, t){
34169         if(e){
34170             e.stopEvent();
34171         }
34172         var ul = this.ul.dom, top = Ext.fly(t).is('.x-menu-scroller-top');
34173         ul.scrollTop += this.scrollIncrement * (top ? -1 : 1);
34174         if(top ? ul.scrollTop <= 0 : ul.scrollTop + this.activeMax >= ul.scrollHeight){
34175            this.onScrollerOut(null, t);
34176         }
34177     },
34178
34179     
34180     onScrollerIn : function(e, t){
34181         var ul = this.ul.dom, top = Ext.fly(t).is('.x-menu-scroller-top');
34182         if(top ? ul.scrollTop > 0 : ul.scrollTop + this.activeMax < ul.scrollHeight){
34183             Ext.fly(t).addClass(['x-menu-item-active', 'x-menu-scroller-active']);
34184         }
34185     },
34186
34187     
34188     onScrollerOut : function(e, t){
34189         Ext.fly(t).removeClass(['x-menu-item-active', 'x-menu-scroller-active']);
34190     },
34191
34192     
34193     show : function(el, pos, parentMenu){
34194         if(this.floating){
34195             this.parentMenu = parentMenu;
34196             if(!this.el){
34197                 this.render();
34198                 this.doLayout(false, true);
34199             }
34200             this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign, this.defaultOffsets), parentMenu);
34201         }else{
34202             Ext.menu.Menu.superclass.show.call(this);
34203         }
34204     },
34205
34206     
34207     showAt : function(xy, parentMenu){
34208         if(this.fireEvent('beforeshow', this) !== false){
34209             this.parentMenu = parentMenu;
34210             if(!this.el){
34211                 this.render();
34212             }
34213             if(this.enableScrolling){
34214                 
34215                 this.el.setXY(xy);
34216                 
34217                 this.constrainScroll(xy[1]);
34218                 xy = [this.el.adjustForConstraints(xy)[0], xy[1]];
34219             }else{
34220                 
34221                 xy = this.el.adjustForConstraints(xy);
34222             }
34223             this.el.setXY(xy);
34224             this.el.show();
34225             Ext.menu.Menu.superclass.onShow.call(this);
34226             if(Ext.isIE){
34227                 
34228                 this.fireEvent('autosize', this);
34229                 if(!Ext.isIE8){
34230                     this.el.repaint();
34231                 }
34232             }
34233             this.hidden = false;
34234             this.focus();
34235             this.fireEvent('show', this);
34236         }
34237     },
34238
34239     constrainScroll : function(y){
34240         var max, full = this.ul.setHeight('auto').getHeight();
34241         if(this.floating){
34242             max = this.maxHeight ? this.maxHeight : Ext.fly(this.el.dom.parentNode).getViewSize(false).height - y;
34243         }else{
34244             max = this.getHeight();
34245         }
34246         if(full > max && max > 0){
34247             this.activeMax = max - this.scrollerHeight * 2 - this.el.getFrameWidth('tb') - Ext.num(this.el.shadowOffset, 0);
34248             this.ul.setHeight(this.activeMax);
34249             this.createScrollers();
34250             this.el.select('.x-menu-scroller').setDisplayed('');
34251         }else{
34252             this.ul.setHeight(full);
34253             this.el.select('.x-menu-scroller').setDisplayed('none');
34254         }
34255         this.ul.dom.scrollTop = 0;
34256     },
34257
34258     createScrollers : function(){
34259         if(!this.scroller){
34260             this.scroller = {
34261                 pos: 0,
34262                 top: this.el.insertFirst({
34263                     tag: 'div',
34264                     cls: 'x-menu-scroller x-menu-scroller-top',
34265                     html: '&#160;'
34266                 }),
34267                 bottom: this.el.createChild({
34268                     tag: 'div',
34269                     cls: 'x-menu-scroller x-menu-scroller-bottom',
34270                     html: '&#160;'
34271                 })
34272             };
34273             this.scroller.top.hover(this.onScrollerIn, this.onScrollerOut, this);
34274             this.scroller.topRepeater = new Ext.util.ClickRepeater(this.scroller.top, {
34275                 listeners: {
34276                     click: this.onScroll.createDelegate(this, [null, this.scroller.top], false)
34277                 }
34278             });
34279             this.scroller.bottom.hover(this.onScrollerIn, this.onScrollerOut, this);
34280             this.scroller.bottomRepeater = new Ext.util.ClickRepeater(this.scroller.bottom, {
34281                 listeners: {
34282                     click: this.onScroll.createDelegate(this, [null, this.scroller.bottom], false)
34283                 }
34284             });
34285         }
34286     },
34287
34288     onLayout : function(){
34289         if(this.isVisible()){
34290             if(this.enableScrolling){
34291                 this.constrainScroll(this.el.getTop());
34292             }
34293             if(this.floating){
34294                 this.el.sync();
34295             }
34296         }
34297     },
34298
34299     focus : function(){
34300         if(!this.hidden){
34301             this.doFocus.defer(50, this);
34302         }
34303     },
34304
34305     doFocus : function(){
34306         if(!this.hidden){
34307             this.focusEl.focus();
34308         }
34309     },
34310
34311     
34312     hide : function(deep){
34313         this.deepHide = deep;
34314         Ext.menu.Menu.superclass.hide.call(this);
34315         delete this.deepHide;
34316     },
34317
34318     
34319     onHide : function(){
34320         Ext.menu.Menu.superclass.onHide.call(this);
34321         this.deactivateActive();
34322         if(this.el && this.floating){
34323             this.el.hide();
34324         }
34325         var pm = this.parentMenu;
34326         if(this.deepHide === true && pm){
34327             if(pm.floating){
34328                 pm.hide(true);
34329             }else{
34330                 pm.deactivateActive();
34331             }
34332         }
34333     },
34334
34335     
34336     lookupComponent : function(c){
34337          if(Ext.isString(c)){
34338             c = (c == 'separator' || c == '-') ? new Ext.menu.Separator() : new Ext.menu.TextItem(c);
34339              this.applyDefaults(c);
34340          }else{
34341             if(Ext.isObject(c)){
34342                 c = this.getMenuItem(c);
34343             }else if(c.tagName || c.el){ 
34344                 c = new Ext.BoxComponent({
34345                     el: c
34346                 });
34347             }
34348          }
34349          return c;
34350     },
34351
34352     applyDefaults : function(c){
34353         if(!Ext.isString(c)){
34354             c = Ext.menu.Menu.superclass.applyDefaults.call(this, c);
34355             var d = this.internalDefaults;
34356             if(d){
34357                 if(c.events){
34358                     Ext.applyIf(c.initialConfig, d);
34359                     Ext.apply(c, d);
34360                 }else{
34361                     Ext.applyIf(c, d);
34362                 }
34363             }
34364         }
34365         return c;
34366     },
34367
34368     
34369     getMenuItem : function(config){
34370        if(!config.isXType){
34371             if(!config.xtype && Ext.isBoolean(config.checked)){
34372                 return new Ext.menu.CheckItem(config)
34373             }
34374             return Ext.create(config, this.defaultType);
34375         }
34376         return config;
34377     },
34378
34379     
34380     addSeparator : function(){
34381         return this.add(new Ext.menu.Separator());
34382     },
34383
34384     
34385     addElement : function(el){
34386         return this.add(new Ext.menu.BaseItem(el));
34387     },
34388
34389     
34390     addItem : function(item){
34391         return this.add(item);
34392     },
34393
34394     
34395     addMenuItem : function(config){
34396         return this.add(this.getMenuItem(config));
34397     },
34398
34399     
34400     addText : function(text){
34401         return this.add(new Ext.menu.TextItem(text));
34402     },
34403
34404     
34405     onDestroy : function(){
34406         var pm = this.parentMenu;
34407         if(pm && pm.activeChild == this){
34408             delete pm.activeChild;
34409         }
34410         delete this.parentMenu;
34411         Ext.menu.Menu.superclass.onDestroy.call(this);
34412         Ext.menu.MenuMgr.unregister(this);
34413         Ext.EventManager.removeResizeListener(this.hide, this);
34414         if(this.keyNav) {
34415             this.keyNav.disable();
34416         }
34417         var s = this.scroller;
34418         if(s){
34419             Ext.destroy(s.topRepeater, s.bottomRepeater, s.top, s.bottom);
34420         }
34421         Ext.destroy(
34422             this.el,
34423             this.focusEl,
34424             this.ul
34425         );
34426     }
34427 });
34428
34429 Ext.reg('menu', Ext.menu.Menu);
34430
34431
34432 Ext.menu.MenuNav = Ext.extend(Ext.KeyNav, function(){
34433     function up(e, m){
34434         if(!m.tryActivate(m.items.indexOf(m.activeItem)-1, -1)){
34435             m.tryActivate(m.items.length-1, -1);
34436         }
34437     }
34438     function down(e, m){
34439         if(!m.tryActivate(m.items.indexOf(m.activeItem)+1, 1)){
34440             m.tryActivate(0, 1);
34441         }
34442     }
34443     return {
34444         constructor : function(menu){
34445             Ext.menu.MenuNav.superclass.constructor.call(this, menu.el);
34446             this.scope = this.menu = menu;
34447         },
34448
34449         doRelay : function(e, h){
34450             var k = e.getKey();
34451
34452             if (this.menu.activeItem && this.menu.activeItem.isFormField && k != e.TAB) {
34453                 return false;
34454             }
34455             if(!this.menu.activeItem && e.isNavKeyPress() && k != e.SPACE && k != e.RETURN){
34456                 this.menu.tryActivate(0, 1);
34457                 return false;
34458             }
34459             return h.call(this.scope || this, e, this.menu);
34460         },
34461
34462         tab: function(e, m) {
34463             e.stopEvent();
34464             if (e.shiftKey) {
34465                 up(e, m);
34466             } else {
34467                 down(e, m);
34468             }
34469         },
34470
34471         up : up,
34472
34473         down : down,
34474
34475         right : function(e, m){
34476             if(m.activeItem){
34477                 m.activeItem.expandMenu(true);
34478             }
34479         },
34480
34481         left : function(e, m){
34482             m.hide();
34483             if(m.parentMenu && m.parentMenu.activeItem){
34484                 m.parentMenu.activeItem.activate();
34485             }
34486         },
34487
34488         enter : function(e, m){
34489             if(m.activeItem){
34490                 e.stopPropagation();
34491                 m.activeItem.onClick(e);
34492                 m.fireEvent('click', this, m.activeItem);
34493                 return true;
34494             }
34495         }
34496     };
34497 }());
34498
34499 Ext.menu.MenuMgr = function(){
34500    var menus, active, groups = {}, attached = false, lastShow = new Date();
34501
34502    
34503    function init(){
34504        menus = {};
34505        active = new Ext.util.MixedCollection();
34506        Ext.getDoc().addKeyListener(27, function(){
34507            if(active.length > 0){
34508                hideAll();
34509            }
34510        });
34511    }
34512
34513    
34514    function hideAll(){
34515        if(active && active.length > 0){
34516            var c = active.clone();
34517            c.each(function(m){
34518                m.hide();
34519            });
34520            return true;
34521        }
34522        return false;
34523    }
34524
34525    
34526    function onHide(m){
34527        active.remove(m);
34528        if(active.length < 1){
34529            Ext.getDoc().un("mousedown", onMouseDown);
34530            attached = false;
34531        }
34532    }
34533
34534    
34535    function onShow(m){
34536        var last = active.last();
34537        lastShow = new Date();
34538        active.add(m);
34539        if(!attached){
34540            Ext.getDoc().on("mousedown", onMouseDown);
34541            attached = true;
34542        }
34543        if(m.parentMenu){
34544           m.getEl().setZIndex(parseInt(m.parentMenu.getEl().getStyle("z-index"), 10) + 3);
34545           m.parentMenu.activeChild = m;
34546        }else if(last && last.isVisible()){
34547           m.getEl().setZIndex(parseInt(last.getEl().getStyle("z-index"), 10) + 3);
34548        }
34549    }
34550
34551    
34552    function onBeforeHide(m){
34553        if(m.activeChild){
34554            m.activeChild.hide();
34555        }
34556        if(m.autoHideTimer){
34557            clearTimeout(m.autoHideTimer);
34558            delete m.autoHideTimer;
34559        }
34560    }
34561
34562    
34563    function onBeforeShow(m){
34564        var pm = m.parentMenu;
34565        if(!pm && !m.allowOtherMenus){
34566            hideAll();
34567        }else if(pm && pm.activeChild){
34568            pm.activeChild.hide();
34569        }
34570    }
34571
34572    
34573    function onMouseDown(e){
34574        if(lastShow.getElapsed() > 50 && active.length > 0 && !e.getTarget(".x-menu")){
34575            hideAll();
34576        }
34577    }
34578
34579    
34580    function onBeforeCheck(mi, state){
34581        if(state){
34582            var g = groups[mi.group];
34583            for(var i = 0, l = g.length; i < l; i++){
34584                if(g[i] != mi){
34585                    g[i].setChecked(false);
34586                }
34587            }
34588        }
34589    }
34590
34591    return {
34592
34593        
34594        hideAll : function(){
34595             return hideAll();  
34596        },
34597
34598        
34599        register : function(menu){
34600            if(!menus){
34601                init();
34602            }
34603            menus[menu.id] = menu;
34604            menu.on({
34605                beforehide: onBeforeHide,
34606                hide: onHide,
34607                beforeshow: onBeforeShow,
34608                show: onShow
34609            });
34610        },
34611
34612         
34613        get : function(menu){
34614            if(typeof menu == "string"){ 
34615                if(!menus){  
34616                    return null;
34617                }
34618                return menus[menu];
34619            }else if(menu.events){  
34620                return menu;
34621            }else if(typeof menu.length == 'number'){ 
34622                return new Ext.menu.Menu({items:menu});
34623            }else{ 
34624                return Ext.create(menu, 'menu');
34625            }
34626        },
34627
34628        
34629        unregister : function(menu){
34630            delete menus[menu.id];
34631            menu.un("beforehide", onBeforeHide);
34632            menu.un("hide", onHide);
34633            menu.un("beforeshow", onBeforeShow);
34634            menu.un("show", onShow);
34635        },
34636
34637        
34638        registerCheckable : function(menuItem){
34639            var g = menuItem.group;
34640            if(g){
34641                if(!groups[g]){
34642                    groups[g] = [];
34643                }
34644                groups[g].push(menuItem);
34645                menuItem.on("beforecheckchange", onBeforeCheck);
34646            }
34647        },
34648
34649        
34650        unregisterCheckable : function(menuItem){
34651            var g = menuItem.group;
34652            if(g){
34653                groups[g].remove(menuItem);
34654                menuItem.un("beforecheckchange", onBeforeCheck);
34655            }
34656        },
34657
34658        getCheckedItem : function(groupId){
34659            var g = groups[groupId];
34660            if(g){
34661                for(var i = 0, l = g.length; i < l; i++){
34662                    if(g[i].checked){
34663                        return g[i];
34664                    }
34665                }
34666            }
34667            return null;
34668        },
34669
34670        setCheckedItem : function(groupId, itemId){
34671            var g = groups[groupId];
34672            if(g){
34673                for(var i = 0, l = g.length; i < l; i++){
34674                    if(g[i].id == itemId){
34675                        g[i].setChecked(true);
34676                    }
34677                }
34678            }
34679            return null;
34680        }
34681    };
34682 }();
34683
34684 Ext.menu.BaseItem = Ext.extend(Ext.Component, {
34685     
34686     
34687     
34688     
34689     canActivate : false,
34690     
34691     activeClass : "x-menu-item-active",
34692     
34693     hideOnClick : true,
34694     
34695     clickHideDelay : 1,
34696
34697     
34698     ctype : "Ext.menu.BaseItem",
34699
34700     
34701     actionMode : "container",
34702     
34703     initComponent : function(){
34704         Ext.menu.BaseItem.superclass.initComponent.call(this);
34705         this.addEvents(
34706                 
34707                 'click',
34708                 
34709                 'activate',
34710                 
34711                 'deactivate'
34712             );
34713             if(this.handler){
34714                 this.on("click", this.handler, this.scope);
34715             }
34716     },
34717
34718     
34719     onRender : function(container, position){
34720         Ext.menu.BaseItem.superclass.onRender.apply(this, arguments);
34721         if(this.ownerCt && this.ownerCt instanceof Ext.menu.Menu){
34722             this.parentMenu = this.ownerCt;
34723         }else{
34724             this.container.addClass('x-menu-list-item');
34725             this.mon(this.el, {
34726                 scope: this,
34727                 click: this.onClick,
34728                 mouseenter: this.activate,
34729                 mouseleave: this.deactivate
34730             });
34731         }
34732     },
34733
34734     
34735     setHandler : function(handler, scope){
34736         if(this.handler){
34737             this.un("click", this.handler, this.scope);
34738         }
34739         this.on("click", this.handler = handler, this.scope = scope);
34740     },
34741
34742     
34743     onClick : function(e){
34744         if(!this.disabled && this.fireEvent("click", this, e) !== false
34745                 && (this.parentMenu && this.parentMenu.fireEvent("itemclick", this, e) !== false)){
34746             this.handleClick(e);
34747         }else{
34748             e.stopEvent();
34749         }
34750     },
34751
34752     
34753     activate : function(){
34754         if(this.disabled){
34755             return false;
34756         }
34757         var li = this.container;
34758         li.addClass(this.activeClass);
34759         this.region = li.getRegion().adjust(2, 2, -2, -2);
34760         this.fireEvent("activate", this);
34761         return true;
34762     },
34763
34764     
34765     deactivate : function(){
34766         this.container.removeClass(this.activeClass);
34767         this.fireEvent("deactivate", this);
34768     },
34769
34770     
34771     shouldDeactivate : function(e){
34772         return !this.region || !this.region.contains(e.getPoint());
34773     },
34774
34775     
34776     handleClick : function(e){
34777         var pm = this.parentMenu;
34778         if(this.hideOnClick){
34779             if(pm.floating){
34780                 pm.hide.defer(this.clickHideDelay, pm, [true]);
34781             }else{
34782                 pm.deactivateActive();
34783             }
34784         }
34785     },
34786
34787     
34788     expandMenu : Ext.emptyFn,
34789
34790     
34791     hideMenu : Ext.emptyFn
34792 });
34793 Ext.reg('menubaseitem', Ext.menu.BaseItem);
34794 Ext.menu.TextItem = Ext.extend(Ext.menu.BaseItem, {
34795     
34796     
34797     hideOnClick : false,
34798     
34799     itemCls : "x-menu-text",
34800     
34801     constructor : function(config){
34802         if(typeof config == 'string'){
34803             config = {text: config}
34804         }
34805         Ext.menu.TextItem.superclass.constructor.call(this, config);
34806     },
34807
34808     
34809     onRender : function(){
34810         var s = document.createElement("span");
34811         s.className = this.itemCls;
34812         s.innerHTML = this.text;
34813         this.el = s;
34814         Ext.menu.TextItem.superclass.onRender.apply(this, arguments);
34815     }
34816 });
34817 Ext.reg('menutextitem', Ext.menu.TextItem);
34818 Ext.menu.Separator = Ext.extend(Ext.menu.BaseItem, {
34819     
34820     itemCls : "x-menu-sep",
34821     
34822     hideOnClick : false,
34823     
34824     
34825     activeClass: '',
34826
34827     
34828     onRender : function(li){
34829         var s = document.createElement("span");
34830         s.className = this.itemCls;
34831         s.innerHTML = "&#160;";
34832         this.el = s;
34833         li.addClass("x-menu-sep-li");
34834         Ext.menu.Separator.superclass.onRender.apply(this, arguments);
34835     }
34836 });
34837 Ext.reg('menuseparator', Ext.menu.Separator);
34838 Ext.menu.Item = Ext.extend(Ext.menu.BaseItem, {
34839     
34840     
34841     
34842     
34843     
34844     
34845     
34846     
34847     itemCls : 'x-menu-item',
34848     
34849     canActivate : true,
34850     
34851     showDelay: 200,
34852     
34853     hideDelay: 200,
34854
34855     
34856     ctype: 'Ext.menu.Item',
34857
34858     initComponent : function(){
34859         Ext.menu.Item.superclass.initComponent.call(this);
34860         if(this.menu){
34861             this.menu = Ext.menu.MenuMgr.get(this.menu);
34862             this.menu.ownerCt = this;
34863         }
34864     },
34865
34866     
34867     onRender : function(container, position){
34868         if (!this.itemTpl) {
34869             this.itemTpl = Ext.menu.Item.prototype.itemTpl = new Ext.XTemplate(
34870                 '<a id="{id}" class="{cls}" hidefocus="true" unselectable="on" href="{href}"',
34871                     '<tpl if="hrefTarget">',
34872                         ' target="{hrefTarget}"',
34873                     '</tpl>',
34874                  '>',
34875                      '<img src="{icon}" class="x-menu-item-icon {iconCls}"/>',
34876                      '<span class="x-menu-item-text">{text}</span>',
34877                  '</a>'
34878              );
34879         }
34880         var a = this.getTemplateArgs();
34881         this.el = position ? this.itemTpl.insertBefore(position, a, true) : this.itemTpl.append(container, a, true);
34882         this.iconEl = this.el.child('img.x-menu-item-icon');
34883         this.textEl = this.el.child('.x-menu-item-text');
34884         if(!this.href) { 
34885             this.mon(this.el, 'click', Ext.emptyFn, null, { preventDefault: true });
34886         }
34887         Ext.menu.Item.superclass.onRender.call(this, container, position);
34888     },
34889
34890     getTemplateArgs: function() {
34891         return {
34892             id: this.id,
34893             cls: this.itemCls + (this.menu ?  ' x-menu-item-arrow' : '') + (this.cls ?  ' ' + this.cls : ''),
34894             href: this.href || '#',
34895             hrefTarget: this.hrefTarget,
34896             icon: this.icon || Ext.BLANK_IMAGE_URL,
34897             iconCls: this.iconCls || '',
34898             text: this.itemText||this.text||'&#160;'
34899         };
34900     },
34901
34902     
34903     setText : function(text){
34904         this.text = text||'&#160;';
34905         if(this.rendered){
34906             this.textEl.update(this.text);
34907             this.parentMenu.layout.doAutoSize();
34908         }
34909     },
34910
34911     
34912     setIconClass : function(cls){
34913         var oldCls = this.iconCls;
34914         this.iconCls = cls;
34915         if(this.rendered){
34916             this.iconEl.replaceClass(oldCls, this.iconCls);
34917         }
34918     },
34919
34920     
34921     beforeDestroy: function(){
34922         if (this.menu){
34923             delete this.menu.ownerCt;
34924             this.menu.destroy();
34925         }
34926         Ext.menu.Item.superclass.beforeDestroy.call(this);
34927     },
34928
34929     
34930     handleClick : function(e){
34931         if(!this.href){ 
34932             e.stopEvent();
34933         }
34934         Ext.menu.Item.superclass.handleClick.apply(this, arguments);
34935     },
34936
34937     
34938     activate : function(autoExpand){
34939         if(Ext.menu.Item.superclass.activate.apply(this, arguments)){
34940             this.focus();
34941             if(autoExpand){
34942                 this.expandMenu();
34943             }
34944         }
34945         return true;
34946     },
34947
34948     
34949     shouldDeactivate : function(e){
34950         if(Ext.menu.Item.superclass.shouldDeactivate.call(this, e)){
34951             if(this.menu && this.menu.isVisible()){
34952                 return !this.menu.getEl().getRegion().contains(e.getPoint());
34953             }
34954             return true;
34955         }
34956         return false;
34957     },
34958
34959     
34960     deactivate : function(){
34961         Ext.menu.Item.superclass.deactivate.apply(this, arguments);
34962         this.hideMenu();
34963     },
34964
34965     
34966     expandMenu : function(autoActivate){
34967         if(!this.disabled && this.menu){
34968             clearTimeout(this.hideTimer);
34969             delete this.hideTimer;
34970             if(!this.menu.isVisible() && !this.showTimer){
34971                 this.showTimer = this.deferExpand.defer(this.showDelay, this, [autoActivate]);
34972             }else if (this.menu.isVisible() && autoActivate){
34973                 this.menu.tryActivate(0, 1);
34974             }
34975         }
34976     },
34977
34978     
34979     deferExpand : function(autoActivate){
34980         delete this.showTimer;
34981         this.menu.show(this.container, this.parentMenu.subMenuAlign || 'tl-tr?', this.parentMenu);
34982         if(autoActivate){
34983             this.menu.tryActivate(0, 1);
34984         }
34985     },
34986
34987     
34988     hideMenu : function(){
34989         clearTimeout(this.showTimer);
34990         delete this.showTimer;
34991         if(!this.hideTimer && this.menu && this.menu.isVisible()){
34992             this.hideTimer = this.deferHide.defer(this.hideDelay, this);
34993         }
34994     },
34995
34996     
34997     deferHide : function(){
34998         delete this.hideTimer;
34999         if(this.menu.over){
35000             this.parentMenu.setActiveItem(this, false);
35001         }else{
35002             this.menu.hide();
35003         }
35004     }
35005 });
35006 Ext.reg('menuitem', Ext.menu.Item);
35007 Ext.menu.CheckItem = Ext.extend(Ext.menu.Item, {
35008     
35009     
35010     itemCls : "x-menu-item x-menu-check-item",
35011     
35012     groupClass : "x-menu-group-item",
35013
35014     
35015     checked: false,
35016
35017     
35018     ctype: "Ext.menu.CheckItem",
35019     
35020     initComponent : function(){
35021         Ext.menu.CheckItem.superclass.initComponent.call(this);
35022             this.addEvents(
35023                 
35024                 "beforecheckchange" ,
35025                 
35026                 "checkchange"
35027             );
35028             
35029             if(this.checkHandler){
35030                 this.on('checkchange', this.checkHandler, this.scope);
35031             }
35032             Ext.menu.MenuMgr.registerCheckable(this);
35033     },
35034
35035     
35036     onRender : function(c){
35037         Ext.menu.CheckItem.superclass.onRender.apply(this, arguments);
35038         if(this.group){
35039             this.el.addClass(this.groupClass);
35040         }
35041         if(this.checked){
35042             this.checked = false;
35043             this.setChecked(true, true);
35044         }
35045     },
35046
35047     
35048     destroy : function(){
35049         Ext.menu.MenuMgr.unregisterCheckable(this);
35050         Ext.menu.CheckItem.superclass.destroy.apply(this, arguments);
35051     },
35052
35053     
35054     setChecked : function(state, suppressEvent){
35055         if(this.checked != state && this.fireEvent("beforecheckchange", this, state) !== false){
35056             if(this.container){
35057                 this.container[state ? "addClass" : "removeClass"]("x-menu-item-checked");
35058             }
35059             this.checked = state;
35060             if(suppressEvent !== true){
35061                 this.fireEvent("checkchange", this, state);
35062             }
35063         }
35064     },
35065
35066     
35067     handleClick : function(e){
35068        if(!this.disabled && !(this.checked && this.group)){
35069            this.setChecked(!this.checked);
35070        }
35071        Ext.menu.CheckItem.superclass.handleClick.apply(this, arguments);
35072     }
35073 });
35074 Ext.reg('menucheckitem', Ext.menu.CheckItem);
35075  Ext.menu.DateMenu = Ext.extend(Ext.menu.Menu, {
35076     
35077     enableScrolling : false,
35078     
35079         
35080     
35081     hideOnClick : true,
35082     
35083     
35084     pickerId : null,
35085     
35086     
35087     
35088     
35089     cls : 'x-date-menu',
35090     
35091     
35092     
35093     
35094
35095     initComponent : function(){
35096         this.on('beforeshow', this.onBeforeShow, this);
35097         if(this.strict = (Ext.isIE7 && Ext.isStrict)){
35098             this.on('show', this.onShow, this, {single: true, delay: 20});
35099         }
35100         Ext.apply(this, {
35101             plain: true,
35102             showSeparator: false,
35103             items: this.picker = new Ext.DatePicker(Ext.applyIf({
35104                 internalRender: this.strict || !Ext.isIE,
35105                 ctCls: 'x-menu-date-item',
35106                 id: this.pickerId
35107             }, this.initialConfig))
35108         });
35109         this.picker.purgeListeners();
35110         Ext.menu.DateMenu.superclass.initComponent.call(this);
35111         
35112         this.relayEvents(this.picker, ['select']);
35113         this.on('show', this.picker.focus, this.picker);
35114         this.on('select', this.menuHide, this);
35115         if(this.handler){
35116             this.on('select', this.handler, this.scope || this);
35117         }
35118     },
35119
35120     menuHide : function() {
35121         if(this.hideOnClick){
35122             this.hide(true);
35123         }
35124     },
35125
35126     onBeforeShow : function(){
35127         if(this.picker){
35128             this.picker.hideMonthPicker(true);
35129         }
35130     },
35131
35132     onShow : function(){
35133         var el = this.picker.getEl();
35134         el.setWidth(el.getWidth()); 
35135     }
35136  });
35137  Ext.reg('datemenu', Ext.menu.DateMenu);
35138  
35139  Ext.menu.ColorMenu = Ext.extend(Ext.menu.Menu, {
35140     
35141     enableScrolling : false,
35142     
35143         
35144     
35145     
35146     hideOnClick : true,
35147     
35148     cls : 'x-color-menu',
35149     
35150     
35151     paletteId : null,
35152     
35153     
35154     
35155     
35156     
35157     
35158     
35159     
35160     
35161     
35162     initComponent : function(){
35163         Ext.apply(this, {
35164             plain: true,
35165             showSeparator: false,
35166             items: this.palette = new Ext.ColorPalette(Ext.applyIf({
35167                 id: this.paletteId
35168             }, this.initialConfig))
35169         });
35170         this.palette.purgeListeners();
35171         Ext.menu.ColorMenu.superclass.initComponent.call(this);
35172         
35173         this.relayEvents(this.palette, ['select']);
35174         this.on('select', this.menuHide, this);
35175         if(this.handler){
35176             this.on('select', this.handler, this.scope || this);
35177         }
35178     },
35179
35180     menuHide : function(){
35181         if(this.hideOnClick){
35182             this.hide(true);
35183         }
35184     }
35185 });
35186 Ext.reg('colormenu', Ext.menu.ColorMenu);
35187
35188 Ext.form.Field = Ext.extend(Ext.BoxComponent,  {
35189     
35190     
35191     
35192     
35193     
35194     
35195
35196     
35197     invalidClass : 'x-form-invalid',
35198     
35199     invalidText : 'The value in this field is invalid',
35200     
35201     focusClass : 'x-form-focus',
35202     
35203     
35204     validationEvent : 'keyup',
35205     
35206     validateOnBlur : true,
35207     
35208     validationDelay : 250,
35209     
35210     defaultAutoCreate : {tag: 'input', type: 'text', size: '20', autocomplete: 'off'},
35211     
35212     fieldClass : 'x-form-field',
35213     
35214     msgTarget : 'qtip',
35215     
35216     msgFx : 'normal',
35217     
35218     readOnly : false,
35219     
35220     disabled : false,
35221     
35222     submitValue: true,
35223
35224     
35225     isFormField : true,
35226
35227     
35228     msgDisplay: '',
35229
35230     
35231     hasFocus : false,
35232
35233     
35234     initComponent : function(){
35235         Ext.form.Field.superclass.initComponent.call(this);
35236         this.addEvents(
35237             
35238             'focus',
35239             
35240             'blur',
35241             
35242             'specialkey',
35243             
35244             'change',
35245             
35246             'invalid',
35247             
35248             'valid'
35249         );
35250     },
35251
35252     
35253     getName : function(){
35254         return this.rendered && this.el.dom.name ? this.el.dom.name : this.name || this.id || '';
35255     },
35256
35257     
35258     onRender : function(ct, position){
35259         if(!this.el){
35260             var cfg = this.getAutoCreate();
35261
35262             if(!cfg.name){
35263                 cfg.name = this.name || this.id;
35264             }
35265             if(this.inputType){
35266                 cfg.type = this.inputType;
35267             }
35268             this.autoEl = cfg;
35269         }
35270         Ext.form.Field.superclass.onRender.call(this, ct, position);
35271         if(this.submitValue === false){
35272             this.el.dom.removeAttribute('name');
35273         }
35274         var type = this.el.dom.type;
35275         if(type){
35276             if(type == 'password'){
35277                 type = 'text';
35278             }
35279             this.el.addClass('x-form-'+type);
35280         }
35281         if(this.readOnly){
35282             this.setReadOnly(true);
35283         }
35284         if(this.tabIndex !== undefined){
35285             this.el.dom.setAttribute('tabIndex', this.tabIndex);
35286         }
35287
35288         this.el.addClass([this.fieldClass, this.cls]);
35289     },
35290
35291     
35292     getItemCt : function(){
35293         return this.itemCt;
35294     },
35295
35296     
35297     initValue : function(){
35298         if(this.value !== undefined){
35299             this.setValue(this.value);
35300         }else if(!Ext.isEmpty(this.el.dom.value) && this.el.dom.value != this.emptyText){
35301             this.setValue(this.el.dom.value);
35302         }
35303         
35304         this.originalValue = this.getValue();
35305     },
35306
35307     
35308     isDirty : function() {
35309         if(this.disabled || !this.rendered) {
35310             return false;
35311         }
35312         return String(this.getValue()) !== String(this.originalValue);
35313     },
35314     
35315     
35316     setReadOnly : function(readOnly){
35317         if(this.rendered){
35318             this.el.dom.readOnly = readOnly;
35319         }
35320         this.readOnly = readOnly;
35321     },
35322
35323     
35324     afterRender : function(){
35325         Ext.form.Field.superclass.afterRender.call(this);
35326         this.initEvents();
35327         this.initValue();
35328     },
35329
35330     
35331     fireKey : function(e){
35332         if(e.isSpecialKey()){
35333             this.fireEvent('specialkey', this, e);
35334         }
35335     },
35336
35337     
35338     reset : function(){
35339         this.setValue(this.originalValue);
35340         this.clearInvalid();
35341     },
35342
35343     
35344     initEvents : function(){
35345         this.mon(this.el, Ext.EventManager.useKeydown ? 'keydown' : 'keypress', this.fireKey,  this);
35346         this.mon(this.el, 'focus', this.onFocus, this);
35347
35348         
35349         
35350         this.mon(this.el, 'blur', this.onBlur, this, this.inEditor ? {buffer:10} : null);
35351     },
35352
35353     
35354     preFocus: Ext.emptyFn,
35355
35356     
35357     onFocus : function(){
35358         this.preFocus();
35359         if(this.focusClass){
35360             this.el.addClass(this.focusClass);
35361         }
35362         if(!this.hasFocus){
35363             this.hasFocus = true;
35364             
35365             this.startValue = this.getValue();
35366             this.fireEvent('focus', this);
35367         }
35368     },
35369
35370     
35371     beforeBlur : Ext.emptyFn,
35372
35373     
35374     onBlur : function(){
35375         this.beforeBlur();
35376         if(this.focusClass){
35377             this.el.removeClass(this.focusClass);
35378         }
35379         this.hasFocus = false;
35380         if(this.validationEvent !== false && (this.validateOnBlur || this.validationEvent == 'blur')){
35381             this.validate();
35382         }
35383         var v = this.getValue();
35384         if(String(v) !== String(this.startValue)){
35385             this.fireEvent('change', this, v, this.startValue);
35386         }
35387         this.fireEvent('blur', this);
35388         this.postBlur();
35389     },
35390
35391     
35392     postBlur : Ext.emptyFn,
35393
35394     
35395     isValid : function(preventMark){
35396         if(this.disabled){
35397             return true;
35398         }
35399         var restore = this.preventMark;
35400         this.preventMark = preventMark === true;
35401         var v = this.validateValue(this.processValue(this.getRawValue()));
35402         this.preventMark = restore;
35403         return v;
35404     },
35405
35406     
35407     validate : function(){
35408         if(this.disabled || this.validateValue(this.processValue(this.getRawValue()))){
35409             this.clearInvalid();
35410             return true;
35411         }
35412         return false;
35413     },
35414
35415     
35416     processValue : function(value){
35417         return value;
35418     },
35419
35420     
35421     validateValue : function(value){
35422         return true;
35423     },
35424     
35425     
35426     getActiveError : function(){
35427         return this.activeError || '';    
35428     },
35429
35430     
35431     markInvalid : function(msg){
35432         if(!this.rendered || this.preventMark){ 
35433             return;
35434         }
35435         msg = msg || this.invalidText;
35436
35437         var mt = this.getMessageHandler();
35438         if(mt){
35439             mt.mark(this, msg);
35440         }else if(this.msgTarget){
35441             this.el.addClass(this.invalidClass);
35442             var t = Ext.getDom(this.msgTarget);
35443             if(t){
35444                 t.innerHTML = msg;
35445                 t.style.display = this.msgDisplay;
35446             }
35447         }
35448         this.activeError = msg;
35449         this.fireEvent('invalid', this, msg);
35450     },
35451
35452     
35453     clearInvalid : function(){
35454         if(!this.rendered || this.preventMark){ 
35455             return;
35456         }
35457         this.el.removeClass(this.invalidClass);
35458         var mt = this.getMessageHandler();
35459         if(mt){
35460             mt.clear(this);
35461         }else if(this.msgTarget){
35462             this.el.removeClass(this.invalidClass);
35463             var t = Ext.getDom(this.msgTarget);
35464             if(t){
35465                 t.innerHTML = '';
35466                 t.style.display = 'none';
35467             }
35468         }
35469         delete this.activeError;
35470         this.fireEvent('valid', this);
35471     },
35472
35473     
35474     getMessageHandler : function(){
35475         return Ext.form.MessageTargets[this.msgTarget];
35476     },
35477
35478     
35479     getErrorCt : function(){
35480         return this.el.findParent('.x-form-element', 5, true) || 
35481             this.el.findParent('.x-form-field-wrap', 5, true);   
35482     },
35483
35484     
35485     alignErrorIcon : function(){
35486         this.errorIcon.alignTo(this.el, 'tl-tr', [2, 0]);
35487     },
35488
35489     
35490     getRawValue : function(){
35491         var v = this.rendered ? this.el.getValue() : Ext.value(this.value, '');
35492         if(v === this.emptyText){
35493             v = '';
35494         }
35495         return v;
35496     },
35497
35498     
35499     getValue : function(){
35500         if(!this.rendered) {
35501             return this.value;
35502         }
35503         var v = this.el.getValue();
35504         if(v === this.emptyText || v === undefined){
35505             v = '';
35506         }
35507         return v;
35508     },
35509
35510     
35511     setRawValue : function(v){
35512         return this.rendered ? (this.el.dom.value = (Ext.isEmpty(v) ? '' : v)) : '';
35513     },
35514
35515     
35516     setValue : function(v){
35517         this.value = v;
35518         if(this.rendered){
35519             this.el.dom.value = (Ext.isEmpty(v) ? '' : v);
35520             this.validate();
35521         }
35522         return this;
35523     },
35524
35525     
35526     append : function(v){
35527          this.setValue([this.getValue(), v].join(''));
35528     }
35529
35530     
35531     
35532
35533     
35534 });
35535
35536
35537 Ext.form.MessageTargets = {
35538     'qtip' : {
35539         mark: function(field, msg){
35540             field.el.addClass(field.invalidClass);
35541             field.el.dom.qtip = msg;
35542             field.el.dom.qclass = 'x-form-invalid-tip';
35543             if(Ext.QuickTips){ 
35544                 Ext.QuickTips.enable();
35545             }
35546         },
35547         clear: function(field){
35548             field.el.removeClass(field.invalidClass);
35549             field.el.dom.qtip = '';
35550         }
35551     },
35552     'title' : {
35553         mark: function(field, msg){
35554             field.el.addClass(field.invalidClass);
35555             field.el.dom.title = msg;
35556         },
35557         clear: function(field){
35558             field.el.dom.title = '';
35559         }
35560     },
35561     'under' : {
35562         mark: function(field, msg){
35563             field.el.addClass(field.invalidClass);
35564             if(!field.errorEl){
35565                 var elp = field.getErrorCt();
35566                 if(!elp){ 
35567                     field.el.dom.title = msg;
35568                     return;
35569                 }
35570                 field.errorEl = elp.createChild({cls:'x-form-invalid-msg'});
35571                 field.errorEl.setWidth(elp.getWidth(true)-20);
35572             }
35573             field.errorEl.update(msg);
35574             Ext.form.Field.msgFx[field.msgFx].show(field.errorEl, field);
35575         },
35576         clear: function(field){
35577             field.el.removeClass(field.invalidClass);
35578             if(field.errorEl){
35579                 Ext.form.Field.msgFx[field.msgFx].hide(field.errorEl, field);
35580             }else{
35581                 field.el.dom.title = '';
35582             }
35583         }
35584     },
35585     'side' : {
35586         mark: function(field, msg){
35587             field.el.addClass(field.invalidClass);
35588             if(!field.errorIcon){
35589                 var elp = field.getErrorCt();
35590                 if(!elp){ 
35591                     field.el.dom.title = msg;
35592                     return;
35593                 }
35594                 field.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});
35595             }
35596             field.alignErrorIcon();
35597             field.errorIcon.dom.qtip = msg;
35598             field.errorIcon.dom.qclass = 'x-form-invalid-tip';
35599             field.errorIcon.show();
35600             field.on('resize', field.alignErrorIcon, field);
35601         },
35602         clear: function(field){
35603             field.el.removeClass(field.invalidClass);
35604             if(field.errorIcon){
35605                 field.errorIcon.dom.qtip = '';
35606                 field.errorIcon.hide();
35607                 field.un('resize', field.alignErrorIcon, field);
35608             }else{
35609                 field.el.dom.title = '';
35610             }
35611         }
35612     }
35613 };
35614
35615
35616 Ext.form.Field.msgFx = {
35617     normal : {
35618         show: function(msgEl, f){
35619             msgEl.setDisplayed('block');
35620         },
35621
35622         hide : function(msgEl, f){
35623             msgEl.setDisplayed(false).update('');
35624         }
35625     },
35626
35627     slide : {
35628         show: function(msgEl, f){
35629             msgEl.slideIn('t', {stopFx:true});
35630         },
35631
35632         hide : function(msgEl, f){
35633             msgEl.slideOut('t', {stopFx:true,useDisplay:true});
35634         }
35635     },
35636
35637     slideRight : {
35638         show: function(msgEl, f){
35639             msgEl.fixDisplay();
35640             msgEl.alignTo(f.el, 'tl-tr');
35641             msgEl.slideIn('l', {stopFx:true});
35642         },
35643
35644         hide : function(msgEl, f){
35645             msgEl.slideOut('l', {stopFx:true,useDisplay:true});
35646         }
35647     }
35648 };
35649 Ext.reg('field', Ext.form.Field);
35650
35651 Ext.form.TextField = Ext.extend(Ext.form.Field,  {
35652     
35653     
35654     
35655     grow : false,
35656     
35657     growMin : 30,
35658     
35659     growMax : 800,
35660     
35661     vtype : null,
35662     
35663     maskRe : null,
35664     
35665     disableKeyFilter : false,
35666     
35667     allowBlank : true,
35668     
35669     minLength : 0,
35670     
35671     maxLength : Number.MAX_VALUE,
35672     
35673     minLengthText : 'The minimum length for this field is {0}',
35674     
35675     maxLengthText : 'The maximum length for this field is {0}',
35676     
35677     selectOnFocus : false,
35678     
35679     blankText : 'This field is required',
35680     
35681     validator : null,
35682     
35683     regex : null,
35684     
35685     regexText : '',
35686     
35687     emptyText : null,
35688     
35689     emptyClass : 'x-form-empty-field',
35690
35691     
35692
35693     initComponent : function(){
35694         Ext.form.TextField.superclass.initComponent.call(this);
35695         this.addEvents(
35696             
35697             'autosize',
35698
35699             
35700             'keydown',
35701             
35702             'keyup',
35703             
35704             'keypress'
35705         );
35706     },
35707
35708     
35709     initEvents : function(){
35710         Ext.form.TextField.superclass.initEvents.call(this);
35711         if(this.validationEvent == 'keyup'){
35712             this.validationTask = new Ext.util.DelayedTask(this.validate, this);
35713             this.mon(this.el, 'keyup', this.filterValidation, this);
35714         }
35715         else if(this.validationEvent !== false && this.validationEvent != 'blur'){
35716                 this.mon(this.el, this.validationEvent, this.validate, this, {buffer: this.validationDelay});
35717         }
35718         if(this.selectOnFocus || this.emptyText){            
35719             this.mon(this.el, 'mousedown', this.onMouseDown, this);
35720             
35721             if(this.emptyText){
35722                 this.applyEmptyText();
35723             }
35724         }
35725         if(this.maskRe || (this.vtype && this.disableKeyFilter !== true && (this.maskRe = Ext.form.VTypes[this.vtype+'Mask']))){
35726                 this.mon(this.el, 'keypress', this.filterKeys, this);
35727         }
35728         if(this.grow){
35729                 this.mon(this.el, 'keyup', this.onKeyUpBuffered, this, {buffer: 50});
35730                         this.mon(this.el, 'click', this.autoSize, this);
35731         }
35732         if(this.enableKeyEvents){
35733             this.mon(this.el, {
35734                 scope: this,
35735                 keyup: this.onKeyUp,
35736                 keydown: this.onKeyDown,
35737                 keypress: this.onKeyPress
35738             });
35739         }
35740     },
35741     
35742     onMouseDown: function(e){
35743         if(!this.hasFocus){
35744             this.mon(this.el, 'mouseup', Ext.emptyFn, this, { single: true, preventDefault: true });
35745         }
35746     },
35747
35748     processValue : function(value){
35749         if(this.stripCharsRe){
35750             var newValue = value.replace(this.stripCharsRe, '');
35751             if(newValue !== value){
35752                 this.setRawValue(newValue);
35753                 return newValue;
35754             }
35755         }
35756         return value;
35757     },
35758
35759     filterValidation : function(e){
35760         if(!e.isNavKeyPress()){
35761             this.validationTask.delay(this.validationDelay);
35762         }
35763     },
35764     
35765     
35766     onDisable: function(){
35767         Ext.form.TextField.superclass.onDisable.call(this);
35768         if(Ext.isIE){
35769             this.el.dom.unselectable = 'on';
35770         }
35771     },
35772     
35773     
35774     onEnable: function(){
35775         Ext.form.TextField.superclass.onEnable.call(this);
35776         if(Ext.isIE){
35777             this.el.dom.unselectable = '';
35778         }
35779     },
35780
35781     
35782     onKeyUpBuffered : function(e){
35783         if(this.doAutoSize(e)){
35784             this.autoSize();
35785         }
35786     },
35787     
35788     
35789     doAutoSize : function(e){
35790         return !e.isNavKeyPress();
35791     },
35792
35793     
35794     onKeyUp : function(e){
35795         this.fireEvent('keyup', this, e);
35796     },
35797
35798     
35799     onKeyDown : function(e){
35800         this.fireEvent('keydown', this, e);
35801     },
35802
35803     
35804     onKeyPress : function(e){
35805         this.fireEvent('keypress', this, e);
35806     },
35807
35808     
35809     reset : function(){
35810         Ext.form.TextField.superclass.reset.call(this);
35811         this.applyEmptyText();
35812     },
35813
35814     applyEmptyText : function(){
35815         if(this.rendered && this.emptyText && this.getRawValue().length < 1 && !this.hasFocus){
35816             this.setRawValue(this.emptyText);
35817             this.el.addClass(this.emptyClass);
35818         }
35819     },
35820
35821     
35822     preFocus : function(){
35823         var el = this.el;
35824         if(this.emptyText){
35825             if(el.dom.value == this.emptyText){
35826                 this.setRawValue('');
35827             }
35828             el.removeClass(this.emptyClass);
35829         }
35830         if(this.selectOnFocus){
35831             el.dom.select();
35832         }
35833     },
35834
35835     
35836     postBlur : function(){
35837         this.applyEmptyText();
35838     },
35839
35840     
35841     filterKeys : function(e){
35842         if(e.ctrlKey){
35843             return;
35844         }
35845         var k = e.getKey();
35846         if(Ext.isGecko && (e.isNavKeyPress() || k == e.BACKSPACE || (k == e.DELETE && e.button == -1))){
35847             return;
35848         }
35849         var cc = String.fromCharCode(e.getCharCode());
35850         if(!Ext.isGecko && e.isSpecialKey() && !cc){
35851             return;
35852         }
35853         if(!this.maskRe.test(cc)){
35854             e.stopEvent();
35855         }
35856     },
35857
35858     setValue : function(v){
35859         if(this.emptyText && this.el && !Ext.isEmpty(v)){
35860             this.el.removeClass(this.emptyClass);
35861         }
35862         Ext.form.TextField.superclass.setValue.apply(this, arguments);
35863         this.applyEmptyText();
35864         this.autoSize();
35865         return this;
35866     },
35867
35868     
35869     validateValue : function(value){
35870         if(Ext.isFunction(this.validator)){
35871             var msg = this.validator(value);
35872             if(msg !== true){
35873                 this.markInvalid(msg);
35874                 return false;
35875             }
35876         }
35877         if(value.length < 1 || value === this.emptyText){ 
35878              if(this.allowBlank){
35879                  this.clearInvalid();
35880                  return true;
35881              }else{
35882                  this.markInvalid(this.blankText);
35883                  return false;
35884              }
35885         }
35886         if(value.length < this.minLength){
35887             this.markInvalid(String.format(this.minLengthText, this.minLength));
35888             return false;
35889         }
35890         if(value.length > this.maxLength){
35891             this.markInvalid(String.format(this.maxLengthText, this.maxLength));
35892             return false;
35893         }       
35894         if(this.vtype){
35895             var vt = Ext.form.VTypes;
35896             if(!vt[this.vtype](value, this)){
35897                 this.markInvalid(this.vtypeText || vt[this.vtype +'Text']);
35898                 return false;
35899             }
35900         }
35901         if(this.regex && !this.regex.test(value)){
35902             this.markInvalid(this.regexText);
35903             return false;
35904         }
35905         return true;
35906     },
35907
35908     
35909     selectText : function(start, end){
35910         var v = this.getRawValue();
35911         var doFocus = false;
35912         if(v.length > 0){
35913             start = start === undefined ? 0 : start;
35914             end = end === undefined ? v.length : end;
35915             var d = this.el.dom;
35916             if(d.setSelectionRange){
35917                 d.setSelectionRange(start, end);
35918             }else if(d.createTextRange){
35919                 var range = d.createTextRange();
35920                 range.moveStart('character', start);
35921                 range.moveEnd('character', end-v.length);
35922                 range.select();
35923             }
35924             doFocus = Ext.isGecko || Ext.isOpera;
35925         }else{
35926             doFocus = true;
35927         }
35928         if(doFocus){
35929             this.focus();
35930         }
35931     },
35932
35933     
35934     autoSize : function(){
35935         if(!this.grow || !this.rendered){
35936             return;
35937         }
35938         if(!this.metrics){
35939             this.metrics = Ext.util.TextMetrics.createInstance(this.el);
35940         }
35941         var el = this.el;
35942         var v = el.dom.value;
35943         var d = document.createElement('div');
35944         d.appendChild(document.createTextNode(v));
35945         v = d.innerHTML;
35946         Ext.removeNode(d);
35947         d = null;
35948         v += '&#160;';
35949         var w = Math.min(this.growMax, Math.max(this.metrics.getWidth(v) +  10, this.growMin));
35950         this.el.setWidth(w);
35951         this.fireEvent('autosize', this, w);
35952     },
35953         
35954         onDestroy: function(){
35955                 if(this.validationTask){
35956                         this.validationTask.cancel();
35957                         this.validationTask = null;
35958                 }
35959                 Ext.form.TextField.superclass.onDestroy.call(this);
35960         }
35961 });
35962 Ext.reg('textfield', Ext.form.TextField);
35963
35964 Ext.form.TriggerField = Ext.extend(Ext.form.TextField,  {
35965     
35966     
35967     
35968     defaultAutoCreate : {tag: "input", type: "text", size: "16", autocomplete: "off"},
35969     
35970     hideTrigger:false,
35971     
35972     editable: true,
35973     
35974     readOnly: false,
35975     
35976     wrapFocusClass: 'x-trigger-wrap-focus',
35977     
35978     autoSize: Ext.emptyFn,
35979     
35980     monitorTab : true,
35981     
35982     deferHeight : true,
35983     
35984     mimicing : false,
35985
35986     actionMode: 'wrap',
35987
35988     removeMode: 'container',
35989
35990     defaultTriggerWidth: 17,
35991
35992     
35993     onResize : function(w, h){
35994         Ext.form.TriggerField.superclass.onResize.call(this, w, h);
35995         var tw = this.getTriggerWidth();
35996         if(Ext.isNumber(w)){
35997             this.el.setWidth(w - tw);
35998         }
35999         this.wrap.setWidth(this.el.getWidth() + tw);
36000     },
36001
36002     getTriggerWidth: function(){
36003         var tw = this.trigger.getWidth();
36004         if(!this.hideTrigger && tw === 0){
36005             tw = this.defaultTriggerWidth;
36006         }
36007         return tw;
36008     },
36009
36010     
36011     alignErrorIcon : function(){
36012         if(this.wrap){
36013             this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);
36014         }
36015     },
36016
36017     
36018     onRender : function(ct, position){
36019         this.doc = Ext.isIE ? Ext.getBody() : Ext.getDoc();
36020         Ext.form.TriggerField.superclass.onRender.call(this, ct, position);
36021
36022         this.wrap = this.el.wrap({cls: 'x-form-field-wrap x-form-field-trigger-wrap'});
36023         this.trigger = this.wrap.createChild(this.triggerConfig ||
36024                 {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.triggerClass});
36025         this.initTrigger();
36026         if(!this.width){
36027             this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth());
36028         }
36029         this.resizeEl = this.positionEl = this.wrap;
36030         this.updateEditState();
36031     },
36032
36033     updateEditState: function(){
36034         if(this.rendered){
36035             if (this.readOnly) {
36036                 this.el.dom.readOnly = true;
36037                 this.el.addClass('x-trigger-noedit');
36038                 this.mun(this.el, 'click', this.onTriggerClick, this);
36039                 this.trigger.setDisplayed(false);
36040             } else {
36041                 if (!this.editable) {
36042                     this.el.dom.readOnly = true;
36043                     this.el.addClass('x-trigger-noedit');
36044                     this.mon(this.el, 'click', this.onTriggerClick, this);
36045                 } else {
36046                     this.el.dom.readOnly = false;
36047                     this.el.removeClass('x-trigger-noedit');
36048                     this.mun(this.el, 'click', this.onTriggerClick, this);
36049                 }
36050                 this.trigger.setDisplayed(!this.hideTrigger);
36051             }
36052             this.onResize(this.width || this.wrap.getWidth());
36053         }
36054     },
36055
36056     setHideTrigger: function(hideTrigger){
36057         if(hideTrigger != this.hideTrigger){
36058             this.hideTrigger = hideTrigger;
36059             this.updateEditState();
36060         }
36061     },
36062
36063     
36064     setEditable: function(editable){
36065         if(editable != this.editable){
36066             this.editable = editable;
36067             this.updateEditState();
36068         }
36069     },
36070
36071     
36072     setReadOnly: function(readOnly){
36073         if(readOnly != this.readOnly){
36074             this.readOnly = readOnly;
36075             this.updateEditState();
36076         }
36077     },
36078
36079     afterRender : function(){
36080         Ext.form.TriggerField.superclass.afterRender.call(this);
36081     },
36082
36083     
36084     initTrigger : function(){
36085         this.mon(this.trigger, 'click', this.onTriggerClick, this, {preventDefault:true});
36086         this.trigger.addClassOnOver('x-form-trigger-over');
36087         this.trigger.addClassOnClick('x-form-trigger-click');
36088     },
36089
36090     
36091     onDestroy : function(){
36092         Ext.destroy(this.trigger, this.wrap);
36093         if (this.mimicing){
36094             this.doc.un('mousedown', this.mimicBlur, this);
36095         }
36096         delete this.doc;
36097         Ext.form.TriggerField.superclass.onDestroy.call(this);
36098     },
36099
36100     
36101     onFocus : function(){
36102         Ext.form.TriggerField.superclass.onFocus.call(this);
36103         if(!this.mimicing){
36104             this.wrap.addClass(this.wrapFocusClass);
36105             this.mimicing = true;
36106             this.doc.on('mousedown', this.mimicBlur, this, {delay: 10});
36107             if(this.monitorTab){
36108                 this.on('specialkey', this.checkTab, this);
36109             }
36110         }
36111     },
36112
36113     
36114     checkTab : function(me, e){
36115         if(e.getKey() == e.TAB){
36116             this.triggerBlur();
36117         }
36118     },
36119
36120     
36121     onBlur : Ext.emptyFn,
36122
36123     
36124     mimicBlur : function(e){
36125         if(!this.isDestroyed && !this.wrap.contains(e.target) && this.validateBlur(e)){
36126             this.triggerBlur();
36127         }
36128     },
36129
36130     
36131     triggerBlur : function(){
36132         this.mimicing = false;
36133         this.doc.un('mousedown', this.mimicBlur, this);
36134         if(this.monitorTab && this.el){
36135             this.un('specialkey', this.checkTab, this);
36136         }
36137         Ext.form.TriggerField.superclass.onBlur.call(this);
36138         if(this.wrap){
36139             this.wrap.removeClass(this.wrapFocusClass);
36140         }
36141     },
36142
36143     beforeBlur : Ext.emptyFn,
36144
36145     
36146     
36147     validateBlur : function(e){
36148         return true;
36149     },
36150
36151     
36152     onTriggerClick : Ext.emptyFn
36153
36154     
36155     
36156     
36157 });
36158
36159
36160 Ext.form.TwinTriggerField = Ext.extend(Ext.form.TriggerField, {
36161     
36162     
36163     
36164
36165     initComponent : function(){
36166         Ext.form.TwinTriggerField.superclass.initComponent.call(this);
36167
36168         this.triggerConfig = {
36169             tag:'span', cls:'x-form-twin-triggers', cn:[
36170             {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger1Class},
36171             {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger2Class}
36172         ]};
36173     },
36174
36175     getTrigger : function(index){
36176         return this.triggers[index];
36177     },
36178
36179     initTrigger : function(){
36180         var ts = this.trigger.select('.x-form-trigger', true);
36181         var triggerField = this;
36182         ts.each(function(t, all, index){
36183             var triggerIndex = 'Trigger'+(index+1);
36184             t.hide = function(){
36185                 var w = triggerField.wrap.getWidth();
36186                 this.dom.style.display = 'none';
36187                 triggerField.el.setWidth(w-triggerField.trigger.getWidth());
36188                 this['hidden' + triggerIndex] = true;
36189             };
36190             t.show = function(){
36191                 var w = triggerField.wrap.getWidth();
36192                 this.dom.style.display = '';
36193                 triggerField.el.setWidth(w-triggerField.trigger.getWidth());
36194                 this['hidden' + triggerIndex] = false;
36195             };
36196
36197             if(this['hide'+triggerIndex]){
36198                 t.dom.style.display = 'none';
36199                 this['hidden' + triggerIndex] = true;
36200             }
36201             this.mon(t, 'click', this['on'+triggerIndex+'Click'], this, {preventDefault:true});
36202             t.addClassOnOver('x-form-trigger-over');
36203             t.addClassOnClick('x-form-trigger-click');
36204         }, this);
36205         this.triggers = ts.elements;
36206     },
36207
36208     getTriggerWidth: function(){
36209         var tw = 0;
36210         Ext.each(this.triggers, function(t, index){
36211             var triggerIndex = 'Trigger' + (index + 1),
36212                 w = t.getWidth();
36213             if(w === 0 && !this['hidden' + triggerIndex]){
36214                 tw += this.defaultTriggerWidth;
36215             }else{
36216                 tw += w;
36217             }
36218         }, this);
36219         return tw;
36220     },
36221
36222     
36223     onDestroy : function() {
36224         Ext.destroy(this.triggers);
36225         Ext.form.TwinTriggerField.superclass.onDestroy.call(this);
36226     },
36227
36228     
36229     onTrigger1Click : Ext.emptyFn,
36230     
36231     onTrigger2Click : Ext.emptyFn
36232 });
36233 Ext.reg('trigger', Ext.form.TriggerField);
36234
36235 Ext.form.TextArea = Ext.extend(Ext.form.TextField,  {
36236     
36237     growMin : 60,
36238     
36239     growMax: 1000,
36240     growAppend : '&#160;\n&#160;',
36241
36242     enterIsSpecial : false,
36243
36244     
36245     preventScrollbars: false,
36246     
36247
36248     
36249     onRender : function(ct, position){
36250         if(!this.el){
36251             this.defaultAutoCreate = {
36252                 tag: "textarea",
36253                 style:"width:100px;height:60px;",
36254                 autocomplete: "off"
36255             };
36256         }
36257         Ext.form.TextArea.superclass.onRender.call(this, ct, position);
36258         if(this.grow){
36259             this.textSizeEl = Ext.DomHelper.append(document.body, {
36260                 tag: "pre", cls: "x-form-grow-sizer"
36261             });
36262             if(this.preventScrollbars){
36263                 this.el.setStyle("overflow", "hidden");
36264             }
36265             this.el.setHeight(this.growMin);
36266         }
36267     },
36268
36269     onDestroy : function(){
36270         Ext.removeNode(this.textSizeEl);
36271         Ext.form.TextArea.superclass.onDestroy.call(this);
36272     },
36273
36274     fireKey : function(e){
36275         if(e.isSpecialKey() && (this.enterIsSpecial || (e.getKey() != e.ENTER || e.hasModifier()))){
36276             this.fireEvent("specialkey", this, e);
36277         }
36278     },
36279     
36280     
36281     doAutoSize : function(e){
36282         return !e.isNavKeyPress() || e.getKey() == e.ENTER;
36283     },
36284
36285     
36286     autoSize: function(){
36287         if(!this.grow || !this.textSizeEl){
36288             return;
36289         }
36290         var el = this.el,
36291             v = Ext.util.Format.htmlEncode(el.dom.value),
36292             ts = this.textSizeEl,
36293             h;
36294             
36295         Ext.fly(ts).setWidth(this.el.getWidth());
36296         if(v.length < 1){
36297             v = "&#160;&#160;";
36298         }else{
36299             v += this.growAppend;
36300             if(Ext.isIE){
36301                 v = v.replace(/\n/g, '&#160;<br />');
36302             }
36303         }
36304         ts.innerHTML = v;
36305         h = Math.min(this.growMax, Math.max(ts.offsetHeight, this.growMin));
36306         if(h != this.lastHeight){
36307             this.lastHeight = h;
36308             this.el.setHeight(h);
36309             this.fireEvent("autosize", this, h);
36310         }
36311     }
36312 });
36313 Ext.reg('textarea', Ext.form.TextArea);
36314 Ext.form.NumberField = Ext.extend(Ext.form.TextField,  {
36315     
36316     
36317     
36318     fieldClass: "x-form-field x-form-num-field",
36319     
36320     allowDecimals : true,
36321     
36322     decimalSeparator : ".",
36323     
36324     decimalPrecision : 2,
36325     
36326     allowNegative : true,
36327     
36328     minValue : Number.NEGATIVE_INFINITY,
36329     
36330     maxValue : Number.MAX_VALUE,
36331     
36332     minText : "The minimum value for this field is {0}",
36333     
36334     maxText : "The maximum value for this field is {0}",
36335     
36336     nanText : "{0} is not a valid number",
36337     
36338     baseChars : "0123456789",
36339
36340     
36341     initEvents : function(){
36342         var allowed = this.baseChars + '';
36343         if (this.allowDecimals) {
36344             allowed += this.decimalSeparator;
36345         }
36346         if (this.allowNegative) {
36347             allowed += '-';
36348         }
36349         this.maskRe = new RegExp('[' + Ext.escapeRe(allowed) + ']');
36350         Ext.form.NumberField.superclass.initEvents.call(this);
36351     },
36352
36353     
36354     validateValue : function(value){
36355         if(!Ext.form.NumberField.superclass.validateValue.call(this, value)){
36356             return false;
36357         }
36358         if(value.length < 1){ 
36359              return true;
36360         }
36361         value = String(value).replace(this.decimalSeparator, ".");
36362         if(isNaN(value)){
36363             this.markInvalid(String.format(this.nanText, value));
36364             return false;
36365         }
36366         var num = this.parseValue(value);
36367         if(num < this.minValue){
36368             this.markInvalid(String.format(this.minText, this.minValue));
36369             return false;
36370         }
36371         if(num > this.maxValue){
36372             this.markInvalid(String.format(this.maxText, this.maxValue));
36373             return false;
36374         }
36375         return true;
36376     },
36377
36378     getValue : function(){
36379         return this.fixPrecision(this.parseValue(Ext.form.NumberField.superclass.getValue.call(this)));
36380     },
36381
36382     setValue : function(v){
36383         v = Ext.isNumber(v) ? v : parseFloat(String(v).replace(this.decimalSeparator, "."));
36384         v = isNaN(v) ? '' : String(v).replace(".", this.decimalSeparator);
36385         return Ext.form.NumberField.superclass.setValue.call(this, v);
36386     },
36387     
36388     
36389     setMinValue : function(value){
36390         this.minValue = Ext.num(value, Number.NEGATIVE_INFINITY);
36391     },
36392     
36393     
36394     setMaxValue : function(value){
36395         this.maxValue = Ext.num(value, Number.MAX_VALUE);    
36396     },
36397
36398     
36399     parseValue : function(value){
36400         value = parseFloat(String(value).replace(this.decimalSeparator, "."));
36401         return isNaN(value) ? '' : value;
36402     },
36403
36404     
36405     fixPrecision : function(value){
36406         var nan = isNaN(value);
36407         if(!this.allowDecimals || this.decimalPrecision == -1 || nan || !value){
36408            return nan ? '' : value;
36409         }
36410         return parseFloat(parseFloat(value).toFixed(this.decimalPrecision));
36411     },
36412
36413     beforeBlur : function(){
36414         var v = this.parseValue(this.getRawValue());
36415         if(!Ext.isEmpty(v)){
36416             this.setValue(this.fixPrecision(v));
36417         }
36418     }
36419 });
36420 Ext.reg('numberfield', Ext.form.NumberField);
36421 Ext.form.DateField = Ext.extend(Ext.form.TriggerField,  {
36422     
36423     format : "m/d/Y",
36424     
36425     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",
36426     
36427     disabledDaysText : "Disabled",
36428     
36429     disabledDatesText : "Disabled",
36430     
36431     minText : "The date in this field must be equal to or after {0}",
36432     
36433     maxText : "The date in this field must be equal to or before {0}",
36434     
36435     invalidText : "{0} is not a valid date - it must be in the format {1}",
36436     
36437     triggerClass : 'x-form-date-trigger',
36438     
36439     showToday : true,
36440     
36441     
36442     
36443     
36444     
36445
36446     
36447     defaultAutoCreate : {tag: "input", type: "text", size: "10", autocomplete: "off"},
36448
36449     initComponent : function(){
36450         Ext.form.DateField.superclass.initComponent.call(this);
36451
36452         this.addEvents(
36453             
36454             'select'
36455         );
36456
36457         if(Ext.isString(this.minValue)){
36458             this.minValue = this.parseDate(this.minValue);
36459         }
36460         if(Ext.isString(this.maxValue)){
36461             this.maxValue = this.parseDate(this.maxValue);
36462         }
36463         this.disabledDatesRE = null;
36464         this.initDisabledDays();
36465     },
36466     
36467     initEvents: function() {
36468         Ext.form.DateField.superclass.initEvents.call(this);
36469         this.keyNav = new Ext.KeyNav(this.el, {
36470             "down": function(e) {
36471                 this.onTriggerClick();
36472             },
36473             scope: this,
36474             forceKeyDown: true
36475         });
36476     },
36477
36478
36479     
36480     initDisabledDays : function(){
36481         if(this.disabledDates){
36482             var dd = this.disabledDates,
36483                 len = dd.length - 1, 
36484                 re = "(?:";
36485                 
36486             Ext.each(dd, function(d, i){
36487                 re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];
36488                 if(i != len){
36489                     re += '|';
36490                 }
36491             }, this);
36492             this.disabledDatesRE = new RegExp(re + ')');
36493         }
36494     },
36495
36496     
36497     setDisabledDates : function(dd){
36498         this.disabledDates = dd;
36499         this.initDisabledDays();
36500         if(this.menu){
36501             this.menu.picker.setDisabledDates(this.disabledDatesRE);
36502         }
36503     },
36504
36505     
36506     setDisabledDays : function(dd){
36507         this.disabledDays = dd;
36508         if(this.menu){
36509             this.menu.picker.setDisabledDays(dd);
36510         }
36511     },
36512
36513     
36514     setMinValue : function(dt){
36515         this.minValue = (Ext.isString(dt) ? this.parseDate(dt) : dt);
36516         if(this.menu){
36517             this.menu.picker.setMinDate(this.minValue);
36518         }
36519     },
36520
36521     
36522     setMaxValue : function(dt){
36523         this.maxValue = (Ext.isString(dt) ? this.parseDate(dt) : dt);
36524         if(this.menu){
36525             this.menu.picker.setMaxDate(this.maxValue);
36526         }
36527     },
36528
36529     
36530     validateValue : function(value){
36531         value = this.formatDate(value);
36532         if(!Ext.form.DateField.superclass.validateValue.call(this, value)){
36533             return false;
36534         }
36535         if(value.length < 1){ 
36536              return true;
36537         }
36538         var svalue = value;
36539         value = this.parseDate(value);
36540         if(!value){
36541             this.markInvalid(String.format(this.invalidText, svalue, this.format));
36542             return false;
36543         }
36544         var time = value.getTime();
36545         if(this.minValue && time < this.minValue.getTime()){
36546             this.markInvalid(String.format(this.minText, this.formatDate(this.minValue)));
36547             return false;
36548         }
36549         if(this.maxValue && time > this.maxValue.getTime()){
36550             this.markInvalid(String.format(this.maxText, this.formatDate(this.maxValue)));
36551             return false;
36552         }
36553         if(this.disabledDays){
36554             var day = value.getDay();
36555             for(var i = 0; i < this.disabledDays.length; i++) {
36556                 if(day === this.disabledDays[i]){
36557                     this.markInvalid(this.disabledDaysText);
36558                     return false;
36559                 }
36560             }
36561         }
36562         var fvalue = this.formatDate(value);
36563         if(this.disabledDatesRE && this.disabledDatesRE.test(fvalue)){
36564             this.markInvalid(String.format(this.disabledDatesText, fvalue));
36565             return false;
36566         }
36567         return true;
36568     },
36569
36570     
36571     
36572     validateBlur : function(){
36573         return !this.menu || !this.menu.isVisible();
36574     },
36575
36576     
36577     getValue : function(){
36578         return this.parseDate(Ext.form.DateField.superclass.getValue.call(this)) || "";
36579     },
36580
36581     
36582     setValue : function(date){
36583         return Ext.form.DateField.superclass.setValue.call(this, this.formatDate(this.parseDate(date)));
36584     },
36585
36586     
36587     parseDate : function(value){
36588         if(!value || Ext.isDate(value)){
36589             return value;
36590         }
36591         var v = Date.parseDate(value, this.format);
36592         if(!v && this.altFormats){
36593             if(!this.altFormatsArray){
36594                 this.altFormatsArray = this.altFormats.split("|");
36595             }
36596             for(var i = 0, len = this.altFormatsArray.length; i < len && !v; i++){
36597                 v = Date.parseDate(value, this.altFormatsArray[i]);
36598             }
36599         }
36600         return v;
36601     },
36602
36603     
36604     onDestroy : function(){
36605                 Ext.destroy(this.menu, this.keyNav);
36606         Ext.form.DateField.superclass.onDestroy.call(this);
36607     },
36608
36609     
36610     formatDate : function(date){
36611         return Ext.isDate(date) ? date.dateFormat(this.format) : date;
36612     },
36613
36614     
36615     
36616     
36617     onTriggerClick : function(){
36618         if(this.disabled){
36619             return;
36620         }
36621         if(this.menu == null){
36622             this.menu = new Ext.menu.DateMenu({
36623                 hideOnClick: false,
36624                 focusOnSelect: false
36625             });
36626         }
36627         this.onFocus();
36628         Ext.apply(this.menu.picker,  {
36629             minDate : this.minValue,
36630             maxDate : this.maxValue,
36631             disabledDatesRE : this.disabledDatesRE,
36632             disabledDatesText : this.disabledDatesText,
36633             disabledDays : this.disabledDays,
36634             disabledDaysText : this.disabledDaysText,
36635             format : this.format,
36636             showToday : this.showToday,
36637             minText : String.format(this.minText, this.formatDate(this.minValue)),
36638             maxText : String.format(this.maxText, this.formatDate(this.maxValue))
36639         });
36640         this.menu.picker.setValue(this.getValue() || new Date());
36641         this.menu.show(this.el, "tl-bl?");
36642         this.menuEvents('on');
36643     },
36644     
36645     
36646     menuEvents: function(method){
36647         this.menu[method]('select', this.onSelect, this);
36648         this.menu[method]('hide', this.onMenuHide, this);
36649         this.menu[method]('show', this.onFocus, this);
36650     },
36651     
36652     onSelect: function(m, d){
36653         this.setValue(d);
36654         this.fireEvent('select', this, d);
36655         this.menu.hide();
36656     },
36657     
36658     onMenuHide: function(){
36659         this.focus(false, 60);
36660         this.menuEvents('un');
36661     },
36662
36663     
36664     beforeBlur : function(){
36665         var v = this.parseDate(this.getRawValue());
36666         if(v){
36667             this.setValue(v);
36668         }
36669     }
36670
36671     
36672     
36673     
36674     
36675 });
36676 Ext.reg('datefield', Ext.form.DateField);
36677 Ext.form.DisplayField = Ext.extend(Ext.form.Field,  {
36678     validationEvent : false,
36679     validateOnBlur : false,
36680     defaultAutoCreate : {tag: "div"},
36681     
36682     fieldClass : "x-form-display-field",
36683     
36684     htmlEncode: false,
36685
36686     
36687     initEvents : Ext.emptyFn,
36688
36689     isValid : function(){
36690         return true;
36691     },
36692
36693     validate : function(){
36694         return true;
36695     },
36696
36697     getRawValue : function(){
36698         var v = this.rendered ? this.el.dom.innerHTML : Ext.value(this.value, '');
36699         if(v === this.emptyText){
36700             v = '';
36701         }
36702         if(this.htmlEncode){
36703             v = Ext.util.Format.htmlDecode(v);
36704         }
36705         return v;
36706     },
36707
36708     getValue : function(){
36709         return this.getRawValue();
36710     },
36711     
36712     getName: function() {
36713         return this.name;
36714     },
36715
36716     setRawValue : function(v){
36717         if(this.htmlEncode){
36718             v = Ext.util.Format.htmlEncode(v);
36719         }
36720         return this.rendered ? (this.el.dom.innerHTML = (Ext.isEmpty(v) ? '' : v)) : (this.value = v);
36721     },
36722
36723     setValue : function(v){
36724         this.setRawValue(v);
36725         return this;
36726     }
36727     
36728     
36729     
36730     
36731     
36732     
36733 });
36734
36735 Ext.reg('displayfield', Ext.form.DisplayField);
36736
36737 Ext.form.ComboBox = Ext.extend(Ext.form.TriggerField, {
36738     
36739     
36740     
36741     
36742     
36743
36744     
36745     defaultAutoCreate : {tag: "input", type: "text", size: "24", autocomplete: "off"},
36746     
36747     
36748     
36749     
36750     
36751     
36752     
36753     listClass : '',
36754     
36755     selectedClass : 'x-combo-selected',
36756     
36757     listEmptyText: '',
36758     
36759     triggerClass : 'x-form-arrow-trigger',
36760     
36761     shadow : 'sides',
36762     
36763     listAlign : 'tl-bl?',
36764     
36765     maxHeight : 300,
36766     
36767     minHeight : 90,
36768     
36769     triggerAction : 'query',
36770     
36771     minChars : 4,
36772     
36773     typeAhead : false,
36774     
36775     queryDelay : 500,
36776     
36777     pageSize : 0,
36778     
36779     selectOnFocus : false,
36780     
36781     queryParam : 'query',
36782     
36783     loadingText : 'Loading...',
36784     
36785     resizable : false,
36786     
36787     handleHeight : 8,
36788     
36789     allQuery: '',
36790     
36791     mode: 'remote',
36792     
36793     minListWidth : 70,
36794     
36795     forceSelection : false,
36796     
36797     typeAheadDelay : 250,
36798     
36799
36800     
36801     lazyInit : true,
36802
36803     
36804     clearFilterOnReset : true,
36805
36806     
36807     submitValue: undefined,
36808
36809     
36810
36811     
36812     initComponent : function(){
36813         Ext.form.ComboBox.superclass.initComponent.call(this);
36814         this.addEvents(
36815             
36816             'expand',
36817             
36818             'collapse',
36819             
36820             'beforeselect',
36821             
36822             'select',
36823             
36824             'beforequery'
36825         );
36826         if(this.transform){
36827             var s = Ext.getDom(this.transform);
36828             if(!this.hiddenName){
36829                 this.hiddenName = s.name;
36830             }
36831             if(!this.store){
36832                 this.mode = 'local';
36833                 var d = [], opts = s.options;
36834                 for(var i = 0, len = opts.length;i < len; i++){
36835                     var o = opts[i],
36836                         value = (o.hasAttribute ? o.hasAttribute('value') : o.getAttributeNode('value').specified) ? o.value : o.text;
36837                     if(o.selected && Ext.isEmpty(this.value, true)) {
36838                         this.value = value;
36839                     }
36840                     d.push([value, o.text]);
36841                 }
36842                 this.store = new Ext.data.ArrayStore({
36843                     'id': 0,
36844                     fields: ['value', 'text'],
36845                     data : d,
36846                     autoDestroy: true
36847                 });
36848                 this.valueField = 'value';
36849                 this.displayField = 'text';
36850             }
36851             s.name = Ext.id(); 
36852             if(!this.lazyRender){
36853                 this.target = true;
36854                 this.el = Ext.DomHelper.insertBefore(s, this.autoCreate || this.defaultAutoCreate);
36855                 this.render(this.el.parentNode, s);
36856             }
36857             Ext.removeNode(s);
36858         }
36859         
36860         else if(this.store){
36861             this.store = Ext.StoreMgr.lookup(this.store);
36862             if(this.store.autoCreated){
36863                 this.displayField = this.valueField = 'field1';
36864                 if(!this.store.expandData){
36865                     this.displayField = 'field2';
36866                 }
36867                 this.mode = 'local';
36868             }
36869         }
36870
36871         this.selectedIndex = -1;
36872         if(this.mode == 'local'){
36873             if(!Ext.isDefined(this.initialConfig.queryDelay)){
36874                 this.queryDelay = 10;
36875             }
36876             if(!Ext.isDefined(this.initialConfig.minChars)){
36877                 this.minChars = 0;
36878             }
36879         }
36880     },
36881
36882     
36883     onRender : function(ct, position){
36884         if(this.hiddenName && !Ext.isDefined(this.submitValue)){
36885             this.submitValue = false;
36886         }
36887         Ext.form.ComboBox.superclass.onRender.call(this, ct, position);
36888         if(this.hiddenName){
36889             this.hiddenField = this.el.insertSibling({tag:'input', type:'hidden', name: this.hiddenName,
36890                     id: (this.hiddenId||this.hiddenName)}, 'before', true);
36891
36892         }
36893         if(Ext.isGecko){
36894             this.el.dom.setAttribute('autocomplete', 'off');
36895         }
36896
36897         if(!this.lazyInit){
36898             this.initList();
36899         }else{
36900             this.on('focus', this.initList, this, {single: true});
36901         }
36902     },
36903
36904     
36905     initValue : function(){
36906         Ext.form.ComboBox.superclass.initValue.call(this);
36907         if(this.hiddenField){
36908             this.hiddenField.value =
36909                 Ext.isDefined(this.hiddenValue) ? this.hiddenValue :
36910                 Ext.isDefined(this.value) ? this.value : '';
36911         }
36912     },
36913
36914     
36915     initList : function(){
36916         if(!this.list){
36917             var cls = 'x-combo-list';
36918
36919             this.list = new Ext.Layer({
36920                 parentEl: this.getListParent(),
36921                 shadow: this.shadow,
36922                 cls: [cls, this.listClass].join(' '),
36923                 constrain:false,
36924                 zindex: 12000
36925             });
36926
36927             var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);
36928             this.list.setSize(lw, 0);
36929             this.list.swallowEvent('mousewheel');
36930             this.assetHeight = 0;
36931             if(this.syncFont !== false){
36932                 this.list.setStyle('font-size', this.el.getStyle('font-size'));
36933             }
36934             if(this.title){
36935                 this.header = this.list.createChild({cls:cls+'-hd', html: this.title});
36936                 this.assetHeight += this.header.getHeight();
36937             }
36938
36939             this.innerList = this.list.createChild({cls:cls+'-inner'});
36940             this.mon(this.innerList, 'mouseover', this.onViewOver, this);
36941             this.mon(this.innerList, 'mousemove', this.onViewMove, this);
36942             this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
36943
36944             if(this.pageSize){
36945                 this.footer = this.list.createChild({cls:cls+'-ft'});
36946                 this.pageTb = new Ext.PagingToolbar({
36947                     store: this.store,
36948                     pageSize: this.pageSize,
36949                     renderTo:this.footer
36950                 });
36951                 this.assetHeight += this.footer.getHeight();
36952             }
36953
36954             if(!this.tpl){
36955                 
36956                 this.tpl = '<tpl for="."><div class="'+cls+'-item">{' + this.displayField + '}</div></tpl>';
36957                 
36958             }
36959
36960             
36961             this.view = new Ext.DataView({
36962                 applyTo: this.innerList,
36963                 tpl: this.tpl,
36964                 singleSelect: true,
36965                 selectedClass: this.selectedClass,
36966                 itemSelector: this.itemSelector || '.' + cls + '-item',
36967                 emptyText: this.listEmptyText
36968             });
36969
36970             this.mon(this.view, 'click', this.onViewClick, this);
36971
36972             this.bindStore(this.store, true);
36973
36974             if(this.resizable){
36975                 this.resizer = new Ext.Resizable(this.list,  {
36976                    pinned:true, handles:'se'
36977                 });
36978                 this.mon(this.resizer, 'resize', function(r, w, h){
36979                     this.maxHeight = h-this.handleHeight-this.list.getFrameWidth('tb')-this.assetHeight;
36980                     this.listWidth = w;
36981                     this.innerList.setWidth(w - this.list.getFrameWidth('lr'));
36982                     this.restrictHeight();
36983                 }, this);
36984
36985                 this[this.pageSize?'footer':'innerList'].setStyle('margin-bottom', this.handleHeight+'px');
36986             }
36987         }
36988     },
36989
36990     
36991     getListParent : function() {
36992         return document.body;
36993     },
36994
36995     
36996     getStore : function(){
36997         return this.store;
36998     },
36999
37000     
37001     bindStore : function(store, initial){
37002         if(this.store && !initial){
37003             if(this.store !== store && this.store.autoDestroy){
37004                 this.store.destroy();
37005             }else{
37006                 this.store.un('beforeload', this.onBeforeLoad, this);
37007                 this.store.un('load', this.onLoad, this);
37008                 this.store.un('exception', this.collapse, this);
37009             }
37010             if(!store){
37011                 this.store = null;
37012                 if(this.view){
37013                     this.view.bindStore(null);
37014                 }
37015                 if(this.pageTb){
37016                     this.pageTb.bindStore(null);
37017                 }
37018             }
37019         }
37020         if(store){
37021             if(!initial) {
37022                 this.lastQuery = null;
37023                 if(this.pageTb) {
37024                     this.pageTb.bindStore(store);
37025                 }
37026             }
37027
37028             this.store = Ext.StoreMgr.lookup(store);
37029             this.store.on({
37030                 scope: this,
37031                 beforeload: this.onBeforeLoad,
37032                 load: this.onLoad,
37033                 exception: this.collapse
37034             });
37035
37036             if(this.view){
37037                 this.view.bindStore(store);
37038             }
37039         }
37040     },
37041
37042     reset : function(){
37043         Ext.form.ComboBox.superclass.reset.call(this);
37044         if(this.clearFilterOnReset && this.mode == 'local'){
37045             this.store.clearFilter();
37046         }
37047     },
37048
37049     
37050     initEvents : function(){
37051         Ext.form.ComboBox.superclass.initEvents.call(this);
37052
37053         this.keyNav = new Ext.KeyNav(this.el, {
37054             "up" : function(e){
37055                 this.inKeyMode = true;
37056                 this.selectPrev();
37057             },
37058
37059             "down" : function(e){
37060                 if(!this.isExpanded()){
37061                     this.onTriggerClick();
37062                 }else{
37063                     this.inKeyMode = true;
37064                     this.selectNext();
37065                 }
37066             },
37067
37068             "enter" : function(e){
37069                 this.onViewClick();
37070             },
37071
37072             "esc" : function(e){
37073                 this.collapse();
37074             },
37075
37076             "tab" : function(e){
37077                 this.onViewClick(false);
37078                 return true;
37079             },
37080
37081             scope : this,
37082
37083             doRelay : function(e, h, hname){
37084                 if(hname == 'down' || this.scope.isExpanded()){
37085                     
37086                     var relay = Ext.KeyNav.prototype.doRelay.apply(this, arguments);
37087                     if(!Ext.isIE && Ext.EventManager.useKeydown){
37088                         
37089                         this.scope.fireKey(e);
37090                     }
37091                     return relay;
37092                 }
37093                 return true;
37094             },
37095
37096             forceKeyDown : true,
37097             defaultEventAction: 'stopEvent'
37098         });
37099         this.queryDelay = Math.max(this.queryDelay || 10,
37100                 this.mode == 'local' ? 10 : 250);
37101         this.dqTask = new Ext.util.DelayedTask(this.initQuery, this);
37102         if(this.typeAhead){
37103             this.taTask = new Ext.util.DelayedTask(this.onTypeAhead, this);
37104         }
37105         if(!this.enableKeyEvents){
37106             this.mon(this.el, 'keyup', this.onKeyUp, this);
37107         }
37108     },
37109
37110     
37111     onDestroy : function(){
37112         if (this.dqTask){
37113             this.dqTask.cancel();
37114             this.dqTask = null;
37115         }
37116         this.bindStore(null);
37117         Ext.destroy(
37118             this.resizer,
37119             this.view,
37120             this.pageTb,
37121             this.list
37122         );
37123         Ext.destroyMembers(this, 'hiddenField');
37124         Ext.form.ComboBox.superclass.onDestroy.call(this);
37125     },
37126
37127     
37128     fireKey : function(e){
37129         if (!this.isExpanded()) {
37130             Ext.form.ComboBox.superclass.fireKey.call(this, e);
37131         }
37132     },
37133
37134     
37135     onResize : function(w, h){
37136         Ext.form.ComboBox.superclass.onResize.apply(this, arguments);
37137         if(this.isVisible() && this.list){
37138             this.doResize(w);
37139         }else{
37140             this.bufferSize = w;
37141         }
37142     },
37143
37144     doResize: function(w){
37145         if(!Ext.isDefined(this.listWidth)){
37146             var lw = Math.max(w, this.minListWidth);
37147             this.list.setWidth(lw);
37148             this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
37149         }
37150     },
37151
37152     
37153     onEnable : function(){
37154         Ext.form.ComboBox.superclass.onEnable.apply(this, arguments);
37155         if(this.hiddenField){
37156             this.hiddenField.disabled = false;
37157         }
37158     },
37159
37160     
37161     onDisable : function(){
37162         Ext.form.ComboBox.superclass.onDisable.apply(this, arguments);
37163         if(this.hiddenField){
37164             this.hiddenField.disabled = true;
37165         }
37166     },
37167
37168     
37169     onBeforeLoad : function(){
37170         if(!this.hasFocus){
37171             return;
37172         }
37173         this.innerList.update(this.loadingText ?
37174                '<div class="loading-indicator">'+this.loadingText+'</div>' : '');
37175         this.restrictHeight();
37176         this.selectedIndex = -1;
37177     },
37178
37179     
37180     onLoad : function(){
37181         if(!this.hasFocus){
37182             return;
37183         }
37184         if(this.store.getCount() > 0 || this.listEmptyText){
37185             this.expand();
37186             this.restrictHeight();
37187             if(this.lastQuery == this.allQuery){
37188                 if(this.editable){
37189                     this.el.dom.select();
37190                 }
37191                 if(!this.selectByValue(this.value, true)){
37192                     this.select(0, true);
37193                 }
37194             }else{
37195                 this.selectNext();
37196                 if(this.typeAhead && this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE){
37197                     this.taTask.delay(this.typeAheadDelay);
37198                 }
37199             }
37200         }else{
37201             this.onEmptyResults();
37202         }
37203         
37204     },
37205
37206     
37207     onTypeAhead : function(){
37208         if(this.store.getCount() > 0){
37209             var r = this.store.getAt(0);
37210             var newValue = r.data[this.displayField];
37211             var len = newValue.length;
37212             var selStart = this.getRawValue().length;
37213             if(selStart != len){
37214                 this.setRawValue(newValue);
37215                 this.selectText(selStart, newValue.length);
37216             }
37217         }
37218     },
37219
37220     
37221     onSelect : function(record, index){
37222         if(this.fireEvent('beforeselect', this, record, index) !== false){
37223             this.setValue(record.data[this.valueField || this.displayField]);
37224             this.collapse();
37225             this.fireEvent('select', this, record, index);
37226         }
37227     },
37228
37229     
37230     getName: function(){
37231         var hf = this.hiddenField;
37232         return hf && hf.name ? hf.name : this.hiddenName || Ext.form.ComboBox.superclass.getName.call(this);
37233     },
37234
37235     
37236     getValue : function(){
37237         if(this.valueField){
37238             return Ext.isDefined(this.value) ? this.value : '';
37239         }else{
37240             return Ext.form.ComboBox.superclass.getValue.call(this);
37241         }
37242     },
37243
37244     
37245     clearValue : function(){
37246         if(this.hiddenField){
37247             this.hiddenField.value = '';
37248         }
37249         this.setRawValue('');
37250         this.lastSelectionText = '';
37251         this.applyEmptyText();
37252         this.value = '';
37253     },
37254
37255     
37256     setValue : function(v){
37257         var text = v;
37258         if(this.valueField){
37259             var r = this.findRecord(this.valueField, v);
37260             if(r){
37261                 text = r.data[this.displayField];
37262             }else if(Ext.isDefined(this.valueNotFoundText)){
37263                 text = this.valueNotFoundText;
37264             }
37265         }
37266         this.lastSelectionText = text;
37267         if(this.hiddenField){
37268             this.hiddenField.value = v;
37269         }
37270         Ext.form.ComboBox.superclass.setValue.call(this, text);
37271         this.value = v;
37272         return this;
37273     },
37274
37275     
37276     findRecord : function(prop, value){
37277         var record;
37278         if(this.store.getCount() > 0){
37279             this.store.each(function(r){
37280                 if(r.data[prop] == value){
37281                     record = r;
37282                     return false;
37283                 }
37284             });
37285         }
37286         return record;
37287     },
37288
37289     
37290     onViewMove : function(e, t){
37291         this.inKeyMode = false;
37292     },
37293
37294     
37295     onViewOver : function(e, t){
37296         if(this.inKeyMode){ 
37297             return;
37298         }
37299         var item = this.view.findItemFromChild(t);
37300         if(item){
37301             var index = this.view.indexOf(item);
37302             this.select(index, false);
37303         }
37304     },
37305
37306     
37307     onViewClick : function(doFocus){
37308         var index = this.view.getSelectedIndexes()[0],
37309             s = this.store,
37310             r = s.getAt(index);
37311         if(r){
37312             this.onSelect(r, index);
37313         }else if(s.getCount() === 0){
37314             this.onEmptyResults();
37315         }
37316         if(doFocus !== false){
37317             this.el.focus();
37318         }
37319     },
37320
37321     
37322     restrictHeight : function(){
37323         this.innerList.dom.style.height = '';
37324         var inner = this.innerList.dom,
37325             pad = this.list.getFrameWidth('tb') + (this.resizable ? this.handleHeight : 0) + this.assetHeight,
37326             h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight),
37327             ha = this.getPosition()[1]-Ext.getBody().getScroll().top,
37328             hb = Ext.lib.Dom.getViewHeight()-ha-this.getSize().height,
37329             space = Math.max(ha, hb, this.minHeight || 0)-this.list.shadowOffset-pad-5;
37330
37331         h = Math.min(h, space, this.maxHeight);
37332
37333         this.innerList.setHeight(h);
37334         this.list.beginUpdate();
37335         this.list.setHeight(h+pad);
37336         this.list.alignTo(this.wrap, this.listAlign);
37337         this.list.endUpdate();
37338     },
37339
37340     
37341     onEmptyResults : function(){
37342         this.collapse();
37343     },
37344
37345     
37346     isExpanded : function(){
37347         return this.list && this.list.isVisible();
37348     },
37349
37350     
37351     selectByValue : function(v, scrollIntoView){
37352         if(!Ext.isEmpty(v, true)){
37353             var r = this.findRecord(this.valueField || this.displayField, v);
37354             if(r){
37355                 this.select(this.store.indexOf(r), scrollIntoView);
37356                 return true;
37357             }
37358         }
37359         return false;
37360     },
37361
37362     
37363     select : function(index, scrollIntoView){
37364         this.selectedIndex = index;
37365         this.view.select(index);
37366         if(scrollIntoView !== false){
37367             var el = this.view.getNode(index);
37368             if(el){
37369                 this.innerList.scrollChildIntoView(el, false);
37370             }
37371         }
37372     },
37373
37374     
37375     selectNext : function(){
37376         var ct = this.store.getCount();
37377         if(ct > 0){
37378             if(this.selectedIndex == -1){
37379                 this.select(0);
37380             }else if(this.selectedIndex < ct-1){
37381                 this.select(this.selectedIndex+1);
37382             }
37383         }
37384     },
37385
37386     
37387     selectPrev : function(){
37388         var ct = this.store.getCount();
37389         if(ct > 0){
37390             if(this.selectedIndex == -1){
37391                 this.select(0);
37392             }else if(this.selectedIndex !== 0){
37393                 this.select(this.selectedIndex-1);
37394             }
37395         }
37396     },
37397
37398     
37399     onKeyUp : function(e){
37400         var k = e.getKey();
37401         if(this.editable !== false && this.readOnly !== true && (k == e.BACKSPACE || !e.isSpecialKey())){
37402             this.lastKey = k;
37403             this.dqTask.delay(this.queryDelay);
37404         }
37405         Ext.form.ComboBox.superclass.onKeyUp.call(this, e);
37406     },
37407
37408     
37409     validateBlur : function(){
37410         return !this.list || !this.list.isVisible();
37411     },
37412
37413     
37414     initQuery : function(){
37415         this.doQuery(this.getRawValue());
37416     },
37417
37418     
37419     beforeBlur : function(){
37420         var val = this.getRawValue(),
37421             rec = this.findRecord(this.displayField, val);
37422         if(!rec && this.forceSelection){
37423             if(val.length > 0 && val != this.emptyText){
37424                 this.el.dom.value = Ext.isEmpty(this.lastSelectionText) ? '' : this.lastSelectionText;
37425                 this.applyEmptyText();
37426             }else{
37427                 this.clearValue();
37428             }
37429         }else{
37430             if(rec){
37431                 val = rec.get(this.valueField || this.displayField);
37432             }
37433             this.setValue(val);
37434         }
37435     },
37436
37437     
37438     doQuery : function(q, forceAll){
37439         q = Ext.isEmpty(q) ? '' : q;
37440         var qe = {
37441             query: q,
37442             forceAll: forceAll,
37443             combo: this,
37444             cancel:false
37445         };
37446         if(this.fireEvent('beforequery', qe)===false || qe.cancel){
37447             return false;
37448         }
37449         q = qe.query;
37450         forceAll = qe.forceAll;
37451         if(forceAll === true || (q.length >= this.minChars)){
37452             if(this.lastQuery !== q){
37453                 this.lastQuery = q;
37454                 if(this.mode == 'local'){
37455                     this.selectedIndex = -1;
37456                     if(forceAll){
37457                         this.store.clearFilter();
37458                     }else{
37459                         this.store.filter(this.displayField, q);
37460                     }
37461                     this.onLoad();
37462                 }else{
37463                     this.store.baseParams[this.queryParam] = q;
37464                     this.store.load({
37465                         params: this.getParams(q)
37466                     });
37467                     this.expand();
37468                 }
37469             }else{
37470                 this.selectedIndex = -1;
37471                 this.onLoad();
37472             }
37473         }
37474     },
37475
37476     
37477     getParams : function(q){
37478         var p = {};
37479         
37480         if(this.pageSize){
37481             p.start = 0;
37482             p.limit = this.pageSize;
37483         }
37484         return p;
37485     },
37486
37487     
37488     collapse : function(){
37489         if(!this.isExpanded()){
37490             return;
37491         }
37492         this.list.hide();
37493         Ext.getDoc().un('mousewheel', this.collapseIf, this);
37494         Ext.getDoc().un('mousedown', this.collapseIf, this);
37495         this.fireEvent('collapse', this);
37496     },
37497
37498     
37499     collapseIf : function(e){
37500         if(!e.within(this.wrap) && !e.within(this.list)){
37501             this.collapse();
37502         }
37503     },
37504
37505     
37506     expand : function(){
37507         if(this.isExpanded() || !this.hasFocus){
37508             return;
37509         }
37510         if(this.bufferSize){
37511             this.doResize(this.bufferSize);
37512             delete this.bufferSize;
37513         }
37514         this.list.alignTo(this.wrap, this.listAlign);
37515         this.list.show();
37516         if(Ext.isGecko2){
37517             this.innerList.setOverflow('auto'); 
37518         }
37519         this.mon(Ext.getDoc(), {
37520             scope: this,
37521             mousewheel: this.collapseIf,
37522             mousedown: this.collapseIf
37523         });
37524         this.fireEvent('expand', this);
37525     },
37526
37527     
37528     
37529     
37530     onTriggerClick : function(){
37531         if(this.readOnly || this.disabled){
37532             return;
37533         }
37534         if(this.isExpanded()){
37535             this.collapse();
37536             this.el.focus();
37537         }else {
37538             this.onFocus({});
37539             if(this.triggerAction == 'all') {
37540                 this.doQuery(this.allQuery, true);
37541             } else {
37542                 this.doQuery(this.getRawValue());
37543             }
37544             this.el.focus();
37545         }
37546     }
37547
37548     
37549     
37550     
37551     
37552
37553 });
37554 Ext.reg('combo', Ext.form.ComboBox);
37555
37556 Ext.form.Checkbox = Ext.extend(Ext.form.Field,  {
37557     
37558     focusClass : undefined,
37559     
37560     fieldClass : 'x-form-field',
37561     
37562     checked : false,
37563     
37564     defaultAutoCreate : { tag: 'input', type: 'checkbox', autocomplete: 'off'},
37565     
37566     
37567     
37568     
37569
37570     
37571     actionMode : 'wrap',
37572     
37573         
37574     initComponent : function(){
37575         Ext.form.Checkbox.superclass.initComponent.call(this);
37576         this.addEvents(
37577             
37578             'check'
37579         );
37580     },
37581
37582     
37583     onResize : function(){
37584         Ext.form.Checkbox.superclass.onResize.apply(this, arguments);
37585         if(!this.boxLabel && !this.fieldLabel){
37586             this.el.alignTo(this.wrap, 'c-c');
37587         }
37588     },
37589
37590     
37591     initEvents : function(){
37592         Ext.form.Checkbox.superclass.initEvents.call(this);
37593         this.mon(this.el, {
37594             scope: this,
37595             click: this.onClick,
37596             change: this.onClick
37597         });
37598     },
37599
37600     
37601     markInvalid : Ext.emptyFn,
37602     
37603     clearInvalid : Ext.emptyFn,
37604
37605     
37606     onRender : function(ct, position){
37607         Ext.form.Checkbox.superclass.onRender.call(this, ct, position);
37608         if(this.inputValue !== undefined){
37609             this.el.dom.value = this.inputValue;
37610         }
37611         this.wrap = this.el.wrap({cls: 'x-form-check-wrap'});
37612         if(this.boxLabel){
37613             this.wrap.createChild({tag: 'label', htmlFor: this.el.id, cls: 'x-form-cb-label', html: this.boxLabel});
37614         }
37615         if(this.checked){
37616             this.setValue(true);
37617         }else{
37618             this.checked = this.el.dom.checked;
37619         }
37620         
37621         if(Ext.isIE){
37622             this.wrap.repaint();
37623         }
37624         this.resizeEl = this.positionEl = this.wrap;
37625     },
37626
37627     
37628     onDestroy : function(){
37629         Ext.destroy(this.wrap);
37630         Ext.form.Checkbox.superclass.onDestroy.call(this);
37631     },
37632
37633     
37634     initValue : function() {
37635         this.originalValue = this.getValue();
37636     },
37637
37638     
37639     getValue : function(){
37640         if(this.rendered){
37641             return this.el.dom.checked;
37642         }
37643         return this.checked;
37644     },
37645
37646         
37647     onClick : function(){
37648         if(this.el.dom.checked != this.checked){
37649             this.setValue(this.el.dom.checked);
37650         }
37651     },
37652
37653     
37654     setValue : function(v){
37655         var checked = this.checked ;
37656         this.checked = (v === true || v === 'true' || v == '1' || String(v).toLowerCase() == 'on');
37657         if(this.rendered){
37658             this.el.dom.checked = this.checked;
37659             this.el.dom.defaultChecked = this.checked;
37660         }
37661         if(checked != this.checked){
37662             this.fireEvent('check', this, this.checked);
37663             if(this.handler){
37664                 this.handler.call(this.scope || this, this, this.checked);
37665             }
37666         }
37667         return this;
37668     }
37669 });
37670 Ext.reg('checkbox', Ext.form.Checkbox);
37671
37672 Ext.form.CheckboxGroup = Ext.extend(Ext.form.Field, {
37673     
37674     
37675     columns : 'auto',
37676     
37677     vertical : false,
37678     
37679     allowBlank : true,
37680     
37681     blankText : "You must select at least one item in this group",
37682
37683     
37684     defaultType : 'checkbox',
37685
37686     
37687     groupCls : 'x-form-check-group',
37688
37689     
37690     initComponent: function(){
37691         this.addEvents(
37692             
37693             'change'
37694         );
37695         this.on('change', this.validate, this);
37696         Ext.form.CheckboxGroup.superclass.initComponent.call(this);
37697     },
37698
37699     
37700     onRender : function(ct, position){
37701         if(!this.el){
37702             var panelCfg = {
37703                 autoEl: {
37704                     id: this.id
37705                 },
37706                 cls: this.groupCls,
37707                 layout: 'column',
37708                 renderTo: ct,
37709                 bufferResize: false 
37710             };
37711             var colCfg = {
37712                 xtype: 'container',
37713                 defaultType: this.defaultType,
37714                 layout: 'form',
37715                 defaults: {
37716                     hideLabel: true,
37717                     anchor: '100%'
37718                 }
37719             };
37720
37721             if(this.items[0].items){
37722
37723                 
37724
37725                 Ext.apply(panelCfg, {
37726                     layoutConfig: {columns: this.items.length},
37727                     defaults: this.defaults,
37728                     items: this.items
37729                 });
37730                 for(var i=0, len=this.items.length; i<len; i++){
37731                     Ext.applyIf(this.items[i], colCfg);
37732                 }
37733
37734             }else{
37735
37736                 
37737                 
37738
37739                 var numCols, cols = [];
37740
37741                 if(typeof this.columns == 'string'){ 
37742                     this.columns = this.items.length;
37743                 }
37744                 if(!Ext.isArray(this.columns)){
37745                     var cs = [];
37746                     for(var i=0; i<this.columns; i++){
37747                         cs.push((100/this.columns)*.01); 
37748                     }
37749                     this.columns = cs;
37750                 }
37751
37752                 numCols = this.columns.length;
37753
37754                 
37755                 for(var i=0; i<numCols; i++){
37756                     var cc = Ext.apply({items:[]}, colCfg);
37757                     cc[this.columns[i] <= 1 ? 'columnWidth' : 'width'] = this.columns[i];
37758                     if(this.defaults){
37759                         cc.defaults = Ext.apply(cc.defaults || {}, this.defaults)
37760                     }
37761                     cols.push(cc);
37762                 };
37763
37764                 
37765                 if(this.vertical){
37766                     var rows = Math.ceil(this.items.length / numCols), ri = 0;
37767                     for(var i=0, len=this.items.length; i<len; i++){
37768                         if(i>0 && i%rows==0){
37769                             ri++;
37770                         }
37771                         if(this.items[i].fieldLabel){
37772                             this.items[i].hideLabel = false;
37773                         }
37774                         cols[ri].items.push(this.items[i]);
37775                     };
37776                 }else{
37777                     for(var i=0, len=this.items.length; i<len; i++){
37778                         var ci = i % numCols;
37779                         if(this.items[i].fieldLabel){
37780                             this.items[i].hideLabel = false;
37781                         }
37782                         cols[ci].items.push(this.items[i]);
37783                     };
37784                 }
37785
37786                 Ext.apply(panelCfg, {
37787                     layoutConfig: {columns: numCols},
37788                     items: cols
37789                 });
37790             }
37791
37792             this.panel = new Ext.Container(panelCfg);
37793             this.panel.ownerCt = this;
37794             this.el = this.panel.getEl();
37795
37796             if(this.forId && this.itemCls){
37797                 var l = this.el.up(this.itemCls).child('label', true);
37798                 if(l){
37799                     l.setAttribute('htmlFor', this.forId);
37800                 }
37801             }
37802
37803             var fields = this.panel.findBy(function(c){
37804                 return c.isFormField;
37805             }, this);
37806
37807             this.items = new Ext.util.MixedCollection();
37808             this.items.addAll(fields);
37809         }
37810         Ext.form.CheckboxGroup.superclass.onRender.call(this, ct, position);
37811     },
37812
37813     initValue : function(){
37814         if(this.value){
37815             this.setValue.apply(this, this.buffered ? this.value : [this.value]);
37816             delete this.buffered;
37817             delete this.value;
37818         }
37819     },
37820
37821     afterRender : function(){
37822         Ext.form.CheckboxGroup.superclass.afterRender.call(this);
37823         this.eachItem(function(item){
37824             item.on('check', this.fireChecked, this);
37825             item.inGroup = true;
37826         });
37827     },
37828
37829     
37830     doLayout: function(){
37831         
37832         if(this.rendered){
37833             this.panel.forceLayout = this.ownerCt.forceLayout;
37834             this.panel.doLayout();
37835         }
37836     },
37837
37838     
37839     fireChecked: function(){
37840         var arr = [];
37841         this.eachItem(function(item){
37842             if(item.checked){
37843                 arr.push(item);
37844             }
37845         });
37846         this.fireEvent('change', this, arr);
37847     },
37848
37849     
37850     validateValue : function(value){
37851         if(!this.allowBlank){
37852             var blank = true;
37853             this.eachItem(function(f){
37854                 if(f.checked){
37855                     return (blank = false);
37856                 }
37857             });
37858             if(blank){
37859                 this.markInvalid(this.blankText);
37860                 return false;
37861             }
37862         }
37863         return true;
37864     },
37865
37866     
37867     isDirty: function(){
37868         
37869         if (this.disabled || !this.rendered) {
37870             return false;
37871         }
37872
37873         var dirty = false;
37874         this.eachItem(function(item){
37875             if(item.isDirty()){
37876                 dirty = true;
37877                 return false;
37878             }
37879         });
37880         return dirty;
37881     },
37882
37883     
37884     onDisable : function(){
37885         this.eachItem(function(item){
37886             item.disable();
37887         });
37888     },
37889
37890     
37891     onEnable : function(){
37892         this.eachItem(function(item){
37893             item.enable();
37894         });
37895     },
37896
37897     
37898     doLayout: function(){
37899         if(this.rendered){
37900             this.panel.forceLayout = this.ownerCt.forceLayout;
37901             this.panel.doLayout();
37902         }
37903     },
37904
37905     
37906     onResize : function(w, h){
37907         this.panel.setSize(w, h);
37908         this.panel.doLayout();
37909     },
37910
37911     
37912     reset : function(){
37913         this.eachItem(function(c){
37914             if(c.reset){
37915                 c.reset();
37916             }
37917         });
37918         
37919         
37920         (function() {
37921             this.clearInvalid();
37922         }).defer(50, this);
37923     },
37924
37925     
37926     setValue: function(){
37927         if(this.rendered){
37928             this.onSetValue.apply(this, arguments);
37929         }else{
37930             this.buffered = true;
37931             this.value = arguments;
37932         }
37933         return this;
37934     },
37935
37936     onSetValue: function(id, value){
37937         if(arguments.length == 1){
37938             if(Ext.isArray(id)){
37939                 
37940                 Ext.each(id, function(val, idx){
37941                     var item = this.items.itemAt(idx);
37942                     if(item){
37943                         item.setValue(val);
37944                     }
37945                 }, this);
37946             }else if(Ext.isObject(id)){
37947                 
37948                 for(var i in id){
37949                     var f = this.getBox(i);
37950                     if(f){
37951                         f.setValue(id[i]);
37952                     }
37953                 }
37954             }else{
37955                 this.setValueForItem(id);
37956             }
37957         }else{
37958             var f = this.getBox(id);
37959             if(f){
37960                 f.setValue(value);
37961             }
37962         }
37963     },
37964
37965     
37966     beforeDestroy: function(){
37967         Ext.destroy(this.panel);
37968         Ext.form.CheckboxGroup.superclass.beforeDestroy.call(this);
37969
37970     },
37971
37972     setValueForItem : function(val){
37973         val = String(val).split(',');
37974         this.eachItem(function(item){
37975             if(val.indexOf(item.inputValue)> -1){
37976                 item.setValue(true);
37977             }
37978         });
37979     },
37980
37981     
37982     getBox : function(id){
37983         var box = null;
37984         this.eachItem(function(f){
37985             if(id == f || f.dataIndex == id || f.id == id || f.getName() == id){
37986                 box = f;
37987                 return false;
37988             }
37989         });
37990         return box;
37991     },
37992
37993     
37994     getValue : function(){
37995         var out = [];
37996         this.eachItem(function(item){
37997             if(item.checked){
37998                 out.push(item);
37999             }
38000         });
38001         return out;
38002     },
38003
38004     
38005     eachItem: function(fn){
38006         if(this.items && this.items.each){
38007             this.items.each(fn, this);
38008         }
38009     },
38010
38011     
38012
38013     
38014     getRawValue : Ext.emptyFn,
38015
38016     
38017     setRawValue : Ext.emptyFn
38018
38019 });
38020
38021 Ext.reg('checkboxgroup', Ext.form.CheckboxGroup);
38022
38023 Ext.form.Radio = Ext.extend(Ext.form.Checkbox, {
38024     inputType: 'radio',
38025
38026     
38027     markInvalid : Ext.emptyFn,
38028     
38029     clearInvalid : Ext.emptyFn,
38030
38031     
38032     getGroupValue : function(){
38033         var p = this.el.up('form') || Ext.getBody();
38034         var c = p.child('input[name='+this.el.dom.name+']:checked', true);
38035         return c ? c.value : null;
38036     },
38037
38038     
38039     onClick : function(){
38040         if(this.el.dom.checked != this.checked){
38041                         var els = this.getCheckEl().select('input[name=' + this.el.dom.name + ']');
38042                         els.each(function(el){
38043                                 if(el.dom.id == this.id){
38044                                         this.setValue(true);
38045                                 }else{
38046                                         Ext.getCmp(el.dom.id).setValue(false);
38047                                 }
38048                         }, this);
38049                 }
38050     },
38051
38052     
38053     setValue : function(v){
38054         if (typeof v == 'boolean') {
38055             Ext.form.Radio.superclass.setValue.call(this, v);
38056         } else {
38057             var r = this.getCheckEl().child('input[name=' + this.el.dom.name + '][value=' + v + ']', true);
38058             if(r){
38059                 Ext.getCmp(r.id).setValue(true);
38060             }
38061         }
38062         return this;
38063     },
38064     
38065     
38066     getCheckEl: function(){
38067         if(this.inGroup){
38068             return this.el.up('.x-form-radio-group')
38069         }
38070         return this.el.up('form') || Ext.getBody();
38071     }
38072 });
38073 Ext.reg('radio', Ext.form.Radio);
38074
38075 Ext.form.RadioGroup = Ext.extend(Ext.form.CheckboxGroup, {
38076     
38077     
38078     allowBlank : true,
38079     
38080     blankText : 'You must select one item in this group',
38081     
38082     
38083     defaultType : 'radio',
38084     
38085     
38086     groupCls : 'x-form-radio-group',
38087     
38088     
38089     
38090     
38091     getValue : function(){
38092         var out = null;
38093         this.eachItem(function(item){
38094             if(item.checked){
38095                 out = item;
38096                 return false;
38097             }
38098         });
38099         return out;
38100     },
38101     
38102     
38103     onSetValue : function(id, value){
38104         if(arguments.length > 1){
38105             var f = this.getBox(id);
38106             if(f){
38107                 f.setValue(value);
38108                 if(f.checked){
38109                     this.eachItem(function(item){
38110                         if (item !== f){
38111                             item.setValue(false);
38112                         }
38113                     });
38114                 }
38115             }
38116         }else{
38117             this.setValueForItem(id);
38118         }
38119     },
38120     
38121     setValueForItem : function(val){
38122         val = String(val).split(',')[0];
38123         this.eachItem(function(item){
38124             item.setValue(val == item.inputValue);
38125         });
38126     },
38127     
38128     
38129     fireChecked : function(){
38130         if(!this.checkTask){
38131             this.checkTask = new Ext.util.DelayedTask(this.bufferChecked, this);
38132         }
38133         this.checkTask.delay(10);
38134     },
38135     
38136     
38137     bufferChecked : function(){
38138         var out = null;
38139         this.eachItem(function(item){
38140             if(item.checked){
38141                 out = item;
38142                 return false;
38143             }
38144         });
38145         this.fireEvent('change', this, out);
38146     },
38147     
38148     onDestroy : function(){
38149         if(this.checkTask){
38150             this.checkTask.cancel();
38151             this.checkTask = null;
38152         }
38153         Ext.form.RadioGroup.superclass.onDestroy.call(this);
38154     }
38155
38156 });
38157
38158 Ext.reg('radiogroup', Ext.form.RadioGroup);
38159
38160 Ext.form.Hidden = Ext.extend(Ext.form.Field, {
38161     
38162     inputType : 'hidden',
38163
38164     
38165     onRender : function(){
38166         Ext.form.Hidden.superclass.onRender.apply(this, arguments);
38167     },
38168
38169     
38170     initEvents : function(){
38171         this.originalValue = this.getValue();
38172     },
38173
38174     
38175     setSize : Ext.emptyFn,
38176     setWidth : Ext.emptyFn,
38177     setHeight : Ext.emptyFn,
38178     setPosition : Ext.emptyFn,
38179     setPagePosition : Ext.emptyFn,
38180     markInvalid : Ext.emptyFn,
38181     clearInvalid : Ext.emptyFn
38182 });
38183 Ext.reg('hidden', Ext.form.Hidden);
38184 Ext.form.BasicForm = function(el, config){
38185     Ext.apply(this, config);
38186     if(Ext.isString(this.paramOrder)){
38187         this.paramOrder = this.paramOrder.split(/[\s,|]/);
38188     }
38189     
38190     this.items = new Ext.util.MixedCollection(false, function(o){
38191         return o.getItemId();
38192     });
38193     this.addEvents(
38194         
38195         'beforeaction',
38196         
38197         'actionfailed',
38198         
38199         'actioncomplete'
38200     );
38201
38202     if(el){
38203         this.initEl(el);
38204     }
38205     Ext.form.BasicForm.superclass.constructor.call(this);
38206 };
38207
38208 Ext.extend(Ext.form.BasicForm, Ext.util.Observable, {
38209     
38210     
38211     
38212     
38213     
38214     
38215     
38216     timeout: 30,
38217
38218     
38219
38220     
38221     paramOrder: undefined,
38222
38223     
38224     paramsAsHash: false,
38225     
38226     
38227     waitTitle: 'Please Wait...',
38228
38229     
38230     activeAction : null,
38231
38232     
38233     trackResetOnLoad : false,
38234
38235     
38236     
38237
38238     
38239     initEl : function(el){
38240         this.el = Ext.get(el);
38241         this.id = this.el.id || Ext.id();
38242         if(!this.standardSubmit){
38243             this.el.on('submit', this.onSubmit, this);
38244         }
38245         this.el.addClass('x-form');
38246     },
38247
38248     
38249     getEl: function(){
38250         return this.el;
38251     },
38252
38253     
38254     onSubmit : function(e){
38255         e.stopEvent();
38256     },
38257
38258     
38259     destroy: function() {
38260         this.items.each(function(f){
38261             Ext.destroy(f);
38262         });
38263         if(this.el){
38264             this.el.removeAllListeners();
38265             this.el.remove();
38266         }
38267         this.purgeListeners();
38268     },
38269
38270     
38271     isValid : function(){
38272         var valid = true;
38273         this.items.each(function(f){
38274            if(!f.validate()){
38275                valid = false;
38276            }
38277         });
38278         return valid;
38279     },
38280
38281     
38282     isDirty : function(){
38283         var dirty = false;
38284         this.items.each(function(f){
38285            if(f.isDirty()){
38286                dirty = true;
38287                return false;
38288            }
38289         });
38290         return dirty;
38291     },
38292
38293     
38294     doAction : function(action, options){
38295         if(Ext.isString(action)){
38296             action = new Ext.form.Action.ACTION_TYPES[action](this, options);
38297         }
38298         if(this.fireEvent('beforeaction', this, action) !== false){
38299             this.beforeAction(action);
38300             action.run.defer(100, action);
38301         }
38302         return this;
38303     },
38304
38305     
38306     submit : function(options){
38307         if(this.standardSubmit){
38308             var v = this.isValid();
38309             if(v){
38310                 var el = this.el.dom;
38311                 if(this.url && Ext.isEmpty(el.action)){
38312                     el.action = this.url;
38313                 }
38314                 el.submit();
38315             }
38316             return v;
38317         }
38318         var submitAction = String.format('{0}submit', this.api ? 'direct' : '');
38319         this.doAction(submitAction, options);
38320         return this;
38321     },
38322
38323     
38324     load : function(options){
38325         var loadAction = String.format('{0}load', this.api ? 'direct' : '');
38326         this.doAction(loadAction, options);
38327         return this;
38328     },
38329
38330     
38331     updateRecord : function(record){
38332         record.beginEdit();
38333         var fs = record.fields;
38334         fs.each(function(f){
38335             var field = this.findField(f.name);
38336             if(field){
38337                 record.set(f.name, field.getValue());
38338             }
38339         }, this);
38340         record.endEdit();
38341         return this;
38342     },
38343
38344     
38345     loadRecord : function(record){
38346         this.setValues(record.data);
38347         return this;
38348     },
38349
38350     
38351     beforeAction : function(action){
38352         var o = action.options;
38353         if(o.waitMsg){
38354             if(this.waitMsgTarget === true){
38355                 this.el.mask(o.waitMsg, 'x-mask-loading');
38356             }else if(this.waitMsgTarget){
38357                 this.waitMsgTarget = Ext.get(this.waitMsgTarget);
38358                 this.waitMsgTarget.mask(o.waitMsg, 'x-mask-loading');
38359             }else{
38360                 Ext.MessageBox.wait(o.waitMsg, o.waitTitle || this.waitTitle);
38361             }
38362         }
38363     },
38364
38365     
38366     afterAction : function(action, success){
38367         this.activeAction = null;
38368         var o = action.options;
38369         if(o.waitMsg){
38370             if(this.waitMsgTarget === true){
38371                 this.el.unmask();
38372             }else if(this.waitMsgTarget){
38373                 this.waitMsgTarget.unmask();
38374             }else{
38375                 Ext.MessageBox.updateProgress(1);
38376                 Ext.MessageBox.hide();
38377             }
38378         }
38379         if(success){
38380             if(o.reset){
38381                 this.reset();
38382             }
38383             Ext.callback(o.success, o.scope, [this, action]);
38384             this.fireEvent('actioncomplete', this, action);
38385         }else{
38386             Ext.callback(o.failure, o.scope, [this, action]);
38387             this.fireEvent('actionfailed', this, action);
38388         }
38389     },
38390
38391     
38392     findField : function(id){
38393         var field = this.items.get(id);
38394         if(!Ext.isObject(field)){
38395             this.items.each(function(f){
38396                 if(f.isFormField && (f.dataIndex == id || f.id == id || f.getName() == id)){
38397                     field = f;
38398                     return false;
38399                 }
38400             });
38401         }
38402         return field || null;
38403     },
38404
38405
38406     
38407     markInvalid : function(errors){
38408         if(Ext.isArray(errors)){
38409             for(var i = 0, len = errors.length; i < len; i++){
38410                 var fieldError = errors[i];
38411                 var f = this.findField(fieldError.id);
38412                 if(f){
38413                     f.markInvalid(fieldError.msg);
38414                 }
38415             }
38416         }else{
38417             var field, id;
38418             for(id in errors){
38419                 if(!Ext.isFunction(errors[id]) && (field = this.findField(id))){
38420                     field.markInvalid(errors[id]);
38421                 }
38422             }
38423         }
38424         return this;
38425     },
38426
38427     
38428     setValues : function(values){
38429         if(Ext.isArray(values)){ 
38430             for(var i = 0, len = values.length; i < len; i++){
38431                 var v = values[i];
38432                 var f = this.findField(v.id);
38433                 if(f){
38434                     f.setValue(v.value);
38435                     if(this.trackResetOnLoad){
38436                         f.originalValue = f.getValue();
38437                     }
38438                 }
38439             }
38440         }else{ 
38441             var field, id;
38442             for(id in values){
38443                 if(!Ext.isFunction(values[id]) && (field = this.findField(id))){
38444                     field.setValue(values[id]);
38445                     if(this.trackResetOnLoad){
38446                         field.originalValue = field.getValue();
38447                     }
38448                 }
38449             }
38450         }
38451         return this;
38452     },
38453
38454     
38455     getValues : function(asString){
38456         var fs = Ext.lib.Ajax.serializeForm(this.el.dom);
38457         if(asString === true){
38458             return fs;
38459         }
38460         return Ext.urlDecode(fs);
38461     },
38462
38463     
38464     getFieldValues : function(dirtyOnly){
38465         var o = {},
38466             n,
38467             key,
38468             val;
38469         this.items.each(function(f){
38470             if(dirtyOnly !== true || f.isDirty()){
38471                 n = f.getName();
38472                 key = o[n];
38473                 val = f.getValue();
38474                 
38475                 if(Ext.isDefined(key)){
38476                     if(Ext.isArray(key)){
38477                         o[n].push(val);
38478                     }else{
38479                         o[n] = [key, val];
38480                     }
38481                 }else{
38482                     o[n] = val;
38483                 }
38484             }
38485         });
38486         return o;
38487     },
38488
38489     
38490     clearInvalid : function(){
38491         this.items.each(function(f){
38492            f.clearInvalid();
38493         });
38494         return this;
38495     },
38496
38497     
38498     reset : function(){
38499         this.items.each(function(f){
38500             f.reset();
38501         });
38502         return this;
38503     },
38504
38505     
38506     add : function(){
38507         this.items.addAll(Array.prototype.slice.call(arguments, 0));
38508         return this;
38509     },
38510
38511
38512     
38513     remove : function(field){
38514         this.items.remove(field);
38515         return this;
38516     },
38517
38518     
38519     render : function(){
38520         this.items.each(function(f){
38521             if(f.isFormField && !f.rendered && document.getElementById(f.id)){ 
38522                 f.applyToMarkup(f.id);
38523             }
38524         });
38525         return this;
38526     },
38527
38528     
38529     applyToFields : function(o){
38530         this.items.each(function(f){
38531            Ext.apply(f, o);
38532         });
38533         return this;
38534     },
38535
38536     
38537     applyIfToFields : function(o){
38538         this.items.each(function(f){
38539            Ext.applyIf(f, o);
38540         });
38541         return this;
38542     },
38543
38544     callFieldMethod : function(fnName, args){
38545         args = args || [];
38546         this.items.each(function(f){
38547             if(Ext.isFunction(f[fnName])){
38548                 f[fnName].apply(f, args);
38549             }
38550         });
38551         return this;
38552     }
38553 });
38554
38555
38556 Ext.BasicForm = Ext.form.BasicForm;
38557 Ext.FormPanel = Ext.extend(Ext.Panel, {
38558     
38559     
38560     
38561     
38562     
38563     
38564     
38565
38566
38567     
38568     minButtonWidth : 75,
38569
38570     
38571     labelAlign : 'left',
38572
38573     
38574     monitorValid : false,
38575
38576     
38577     monitorPoll : 200,
38578
38579     
38580     layout : 'form',
38581
38582     
38583     initComponent : function(){
38584         this.form = this.createForm();
38585         Ext.FormPanel.superclass.initComponent.call(this);
38586
38587         this.bodyCfg = {
38588             tag: 'form',
38589             cls: this.baseCls + '-body',
38590             method : this.method || 'POST',
38591             id : this.formId || Ext.id()
38592         };
38593         if(this.fileUpload) {
38594             this.bodyCfg.enctype = 'multipart/form-data';
38595         }
38596         this.initItems();
38597
38598         this.addEvents(
38599             
38600             'clientvalidation'
38601         );
38602
38603         this.relayEvents(this.form, ['beforeaction', 'actionfailed', 'actioncomplete']);
38604     },
38605
38606     
38607     createForm : function(){
38608         var config = Ext.applyIf({listeners: {}}, this.initialConfig);
38609         return new Ext.form.BasicForm(null, config);
38610     },
38611
38612     
38613     initFields : function(){
38614         var f = this.form;
38615         var formPanel = this;
38616         var fn = function(c){
38617             if(formPanel.isField(c)){
38618                 f.add(c);
38619             }else if(c.findBy && c != formPanel){
38620                 formPanel.applySettings(c);
38621                 
38622                 if(c.items && c.items.each){
38623                     c.items.each(fn, this);
38624                 }
38625             }
38626         };
38627         this.items.each(fn, this);
38628     },
38629
38630     
38631     applySettings: function(c){
38632         var ct = c.ownerCt;
38633         Ext.applyIf(c, {
38634             labelAlign: ct.labelAlign,
38635             labelWidth: ct.labelWidth,
38636             itemCls: ct.itemCls
38637         });
38638     },
38639
38640     
38641     getLayoutTarget : function(){
38642         return this.form.el;
38643     },
38644
38645     
38646     getForm : function(){
38647         return this.form;
38648     },
38649
38650     
38651     onRender : function(ct, position){
38652         this.initFields();
38653         Ext.FormPanel.superclass.onRender.call(this, ct, position);
38654         this.form.initEl(this.body);
38655     },
38656
38657     
38658     beforeDestroy : function(){
38659         this.stopMonitoring();
38660         
38661         Ext.destroy(this.form);
38662         this.form.items.clear();
38663         Ext.FormPanel.superclass.beforeDestroy.call(this);
38664     },
38665
38666     
38667     isField : function(c) {
38668         return !!c.setValue && !!c.getValue && !!c.markInvalid && !!c.clearInvalid;
38669     },
38670
38671     
38672     initEvents : function(){
38673         Ext.FormPanel.superclass.initEvents.call(this);
38674         
38675         this.on({
38676             scope: this,
38677             add: this.onAddEvent,
38678             remove: this.onRemoveEvent
38679         });
38680         if(this.monitorValid){ 
38681             this.startMonitoring();
38682         }
38683     },
38684
38685     
38686     onAdd: function(c){
38687         Ext.FormPanel.superclass.onAdd.call(this, c);
38688         this.processAdd(c);
38689     },
38690
38691     
38692     onAddEvent: function(ct, c){
38693         if(ct !== this){
38694             this.processAdd(c);
38695         }
38696     },
38697
38698     
38699     processAdd : function(c){
38700         
38701         if(this.isField(c)){
38702             this.form.add(c);
38703         
38704         }else if(c.findBy){
38705             this.applySettings(c);
38706             this.form.add.apply(this.form, c.findBy(this.isField));
38707         }
38708     },
38709
38710     
38711     onRemove: function(c){
38712         Ext.FormPanel.superclass.onRemove.call(this, c);
38713         this.processRemove(c);
38714     },
38715
38716     onRemoveEvent: function(ct, c){
38717         if(ct !== this){
38718             this.processRemove(c);
38719         }
38720     },
38721
38722     
38723     processRemove : function(c){
38724         
38725         if(this.isField(c)){
38726             this.form.remove(c);
38727         
38728         }else if(c.findBy){
38729             var isDestroyed = function(o) {
38730                 return !!o.isDestroyed;
38731             }
38732             this.form.items.filterBy(isDestroyed, this.form).each(this.form.remove, this.form);
38733         }
38734     },
38735
38736     
38737     startMonitoring : function(){
38738         if(!this.validTask){
38739             this.validTask = new Ext.util.TaskRunner();
38740             this.validTask.start({
38741                 run : this.bindHandler,
38742                 interval : this.monitorPoll || 200,
38743                 scope: this
38744             });
38745         }
38746     },
38747
38748     
38749     stopMonitoring : function(){
38750         if(this.validTask){
38751             this.validTask.stopAll();
38752             this.validTask = null;
38753         }
38754     },
38755
38756     
38757     load : function(){
38758         this.form.load.apply(this.form, arguments);
38759     },
38760
38761     
38762     onDisable : function(){
38763         Ext.FormPanel.superclass.onDisable.call(this);
38764         if(this.form){
38765             this.form.items.each(function(){
38766                  this.disable();
38767             });
38768         }
38769     },
38770
38771     
38772     onEnable : function(){
38773         Ext.FormPanel.superclass.onEnable.call(this);
38774         if(this.form){
38775             this.form.items.each(function(){
38776                  this.enable();
38777             });
38778         }
38779     },
38780
38781     
38782     bindHandler : function(){
38783         var valid = true;
38784         this.form.items.each(function(f){
38785             if(!f.isValid(true)){
38786                 valid = false;
38787                 return false;
38788             }
38789         });
38790         if(this.fbar){
38791             var fitems = this.fbar.items.items;
38792             for(var i = 0, len = fitems.length; i < len; i++){
38793                 var btn = fitems[i];
38794                 if(btn.formBind === true && btn.disabled === valid){
38795                     btn.setDisabled(!valid);
38796                 }
38797             }
38798         }
38799         this.fireEvent('clientvalidation', this, valid);
38800     }
38801 });
38802 Ext.reg('form', Ext.FormPanel);
38803
38804 Ext.form.FormPanel = Ext.FormPanel;
38805
38806 Ext.form.FieldSet = Ext.extend(Ext.Panel, {
38807     
38808     
38809     
38810     
38811     
38812     
38813     baseCls : 'x-fieldset',
38814     
38815     layout : 'form',
38816     
38817     animCollapse : false,
38818
38819     
38820     onRender : function(ct, position){
38821         if(!this.el){
38822             this.el = document.createElement('fieldset');
38823             this.el.id = this.id;
38824             if (this.title || this.header || this.checkboxToggle) {
38825                 this.el.appendChild(document.createElement('legend')).className = 'x-fieldset-header';
38826             }
38827         }
38828
38829         Ext.form.FieldSet.superclass.onRender.call(this, ct, position);
38830
38831         if(this.checkboxToggle){
38832             var o = typeof this.checkboxToggle == 'object' ?
38833                     this.checkboxToggle :
38834                     {tag: 'input', type: 'checkbox', name: this.checkboxName || this.id+'-checkbox'};
38835             this.checkbox = this.header.insertFirst(o);
38836             this.checkbox.dom.checked = !this.collapsed;
38837             this.mon(this.checkbox, 'click', this.onCheckClick, this);
38838         }
38839     },
38840
38841     
38842     onCollapse : function(doAnim, animArg){
38843         if(this.checkbox){
38844             this.checkbox.dom.checked = false;
38845         }
38846         Ext.form.FieldSet.superclass.onCollapse.call(this, doAnim, animArg);
38847
38848     },
38849
38850     
38851     onExpand : function(doAnim, animArg){
38852         if(this.checkbox){
38853             this.checkbox.dom.checked = true;
38854         }
38855         Ext.form.FieldSet.superclass.onExpand.call(this, doAnim, animArg);
38856     },
38857
38858     
38859     onCheckClick : function(){
38860         this[this.checkbox.dom.checked ? 'expand' : 'collapse']();
38861     }
38862
38863     
38864     
38865     
38866     
38867     
38868     
38869     
38870     
38871     
38872     
38873     
38874     
38875     
38876     
38877     
38878     
38879     
38880     
38881     
38882     
38883     
38884     
38885     
38886     
38887     
38888     
38889     
38890     
38891     
38892     
38893     
38894     
38895     
38896     
38897 });
38898 Ext.reg('fieldset', Ext.form.FieldSet);
38899
38900
38901 Ext.form.HtmlEditor = Ext.extend(Ext.form.Field, {
38902     
38903     enableFormat : true,
38904     
38905     enableFontSize : true,
38906     
38907     enableColors : true,
38908     
38909     enableAlignments : true,
38910     
38911     enableLists : true,
38912     
38913     enableSourceEdit : true,
38914     
38915     enableLinks : true,
38916     
38917     enableFont : true,
38918     
38919     createLinkText : 'Please enter the URL for the link:',
38920     
38921     defaultLinkValue : 'http:/'+'/',
38922     
38923     fontFamilies : [
38924         'Arial',
38925         'Courier New',
38926         'Tahoma',
38927         'Times New Roman',
38928         'Verdana'
38929     ],
38930     defaultFont: 'tahoma',
38931     
38932     defaultValue: (Ext.isOpera || Ext.isIE6) ? '&#160;' : '&#8203;',
38933
38934     
38935     actionMode: 'wrap',
38936     validationEvent : false,
38937     deferHeight: true,
38938     initialized : false,
38939     activated : false,
38940     sourceEditMode : false,
38941     onFocus : Ext.emptyFn,
38942     iframePad:3,
38943     hideMode:'offsets',
38944     defaultAutoCreate : {
38945         tag: "textarea",
38946         style:"width:500px;height:300px;",
38947         autocomplete: "off"
38948     },
38949
38950     
38951     initComponent : function(){
38952         this.addEvents(
38953             
38954             'initialize',
38955             
38956             'activate',
38957              
38958             'beforesync',
38959              
38960             'beforepush',
38961              
38962             'sync',
38963              
38964             'push',
38965              
38966             'editmodechange'
38967         )
38968     },
38969
38970     
38971     createFontOptions : function(){
38972         var buf = [], fs = this.fontFamilies, ff, lc;
38973         for(var i = 0, len = fs.length; i< len; i++){
38974             ff = fs[i];
38975             lc = ff.toLowerCase();
38976             buf.push(
38977                 '<option value="',lc,'" style="font-family:',ff,';"',
38978                     (this.defaultFont == lc ? ' selected="true">' : '>'),
38979                     ff,
38980                 '</option>'
38981             );
38982         }
38983         return buf.join('');
38984     },
38985
38986     
38987     createToolbar : function(editor){
38988         var items = [];
38989         var tipsEnabled = Ext.QuickTips && Ext.QuickTips.isEnabled();
38990         
38991
38992         function btn(id, toggle, handler){
38993             return {
38994                 itemId : id,
38995                 cls : 'x-btn-icon',
38996                 iconCls: 'x-edit-'+id,
38997                 enableToggle:toggle !== false,
38998                 scope: editor,
38999                 handler:handler||editor.relayBtnCmd,
39000                 clickEvent:'mousedown',
39001                 tooltip: tipsEnabled ? editor.buttonTips[id] || undefined : undefined,
39002                 overflowText: editor.buttonTips[id].title || undefined,
39003                 tabIndex:-1
39004             };
39005         }
39006
39007
39008         if(this.enableFont && !Ext.isSafari2){
39009             var fontSelectItem = new Ext.Toolbar.Item({
39010                autoEl: {
39011                     tag:'select',
39012                     cls:'x-font-select',
39013                     html: this.createFontOptions()
39014                }
39015             });
39016             
39017             items.push(
39018                 fontSelectItem,
39019                 '-'
39020             );
39021         }
39022
39023         if(this.enableFormat){
39024             items.push(
39025                 btn('bold'),
39026                 btn('italic'),
39027                 btn('underline')
39028             );
39029         }
39030
39031         if(this.enableFontSize){
39032             items.push(
39033                 '-',
39034                 btn('increasefontsize', false, this.adjustFont),
39035                 btn('decreasefontsize', false, this.adjustFont)
39036             );
39037         }
39038
39039         if(this.enableColors){
39040             items.push(
39041                 '-', {
39042                     itemId:'forecolor',
39043                     cls:'x-btn-icon',
39044                     iconCls: 'x-edit-forecolor',
39045                     clickEvent:'mousedown',
39046                     tooltip: tipsEnabled ? editor.buttonTips.forecolor || undefined : undefined,
39047                     tabIndex:-1,
39048                     menu : new Ext.menu.ColorMenu({
39049                         allowReselect: true,
39050                         focus: Ext.emptyFn,
39051                         value:'000000',
39052                         plain:true,
39053                         listeners: {
39054                             scope: this,
39055                             select: function(cp, color){
39056                                 this.execCmd('forecolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
39057                                 this.deferFocus();
39058                             }
39059                         },
39060                         clickEvent:'mousedown'
39061                     })
39062                 }, {
39063                     itemId:'backcolor',
39064                     cls:'x-btn-icon',
39065                     iconCls: 'x-edit-backcolor',
39066                     clickEvent:'mousedown',
39067                     tooltip: tipsEnabled ? editor.buttonTips.backcolor || undefined : undefined,
39068                     tabIndex:-1,
39069                     menu : new Ext.menu.ColorMenu({
39070                         focus: Ext.emptyFn,
39071                         value:'FFFFFF',
39072                         plain:true,
39073                         allowReselect: true,
39074                         listeners: {
39075                             scope: this,
39076                             select: function(cp, color){
39077                                 if(Ext.isGecko){
39078                                     this.execCmd('useCSS', false);
39079                                     this.execCmd('hilitecolor', color);
39080                                     this.execCmd('useCSS', true);
39081                                     this.deferFocus();
39082                                 }else{
39083                                     this.execCmd(Ext.isOpera ? 'hilitecolor' : 'backcolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
39084                                     this.deferFocus();
39085                                 }
39086                             }
39087                         },
39088                         clickEvent:'mousedown'
39089                     })
39090                 }
39091             );
39092         }
39093
39094         if(this.enableAlignments){
39095             items.push(
39096                 '-',
39097                 btn('justifyleft'),
39098                 btn('justifycenter'),
39099                 btn('justifyright')
39100             );
39101         }
39102
39103         if(!Ext.isSafari2){
39104             if(this.enableLinks){
39105                 items.push(
39106                     '-',
39107                     btn('createlink', false, this.createLink)
39108                 );
39109             }
39110
39111             if(this.enableLists){
39112                 items.push(
39113                     '-',
39114                     btn('insertorderedlist'),
39115                     btn('insertunorderedlist')
39116                 );
39117             }
39118             if(this.enableSourceEdit){
39119                 items.push(
39120                     '-',
39121                     btn('sourceedit', true, function(btn){
39122                         this.toggleSourceEdit(!this.sourceEditMode);
39123                     })
39124                 );
39125             }
39126         }
39127  
39128         
39129         var tb = new Ext.Toolbar({
39130             renderTo: this.wrap.dom.firstChild,
39131             items: items
39132         });
39133         
39134         if (fontSelectItem) {
39135             this.fontSelect = fontSelectItem.el;
39136             
39137             this.mon(this.fontSelect, 'change', function(){
39138                 var font = this.fontSelect.dom.value;
39139                 this.relayCmd('fontname', font);
39140                 this.deferFocus();
39141             }, this);
39142         }
39143
39144
39145         
39146         this.mon(tb.el, 'click', function(e){
39147             e.preventDefault();
39148         });
39149        
39150         
39151         
39152         this.tb = tb;
39153     },
39154
39155     onDisable: function(){
39156         this.wrap.mask();
39157         Ext.form.HtmlEditor.superclass.onDisable.call(this);
39158     },
39159
39160     onEnable: function(){
39161         this.wrap.unmask();
39162         Ext.form.HtmlEditor.superclass.onEnable.call(this);
39163     },
39164
39165     setReadOnly: function(readOnly){
39166         if(this.initialized){
39167             var newDM = readOnly ? 'off' : 'on',
39168                 doc = this.getDoc();
39169             if(String(doc.designMode).toLowerCase() != newDM){
39170                 doc.designMode = newDM;
39171             }
39172             this.disableItems(!readOnly);
39173         }
39174         Ext.form.HtmlEditor.superclass.setReadOnly.call(this, readOnly);
39175     },
39176
39177     
39178     getDocMarkup : function(){
39179         return '<html><head><style type="text/css">body{border:0;margin:0;padding:3px;height:98%;cursor:text;}</style></head><body></body></html>';
39180     },
39181
39182     
39183     getEditorBody : function(){
39184         var doc = this.getDoc();
39185         return doc.body || doc.documentElement;
39186     },
39187
39188     
39189     getDoc : function(){
39190         return Ext.isIE ? this.getWin().document : (this.iframe.contentDocument || this.getWin().document);
39191     },
39192
39193     
39194     getWin : function(){
39195         return Ext.isIE ? this.iframe.contentWindow : window.frames[this.iframe.name];
39196     },
39197
39198     
39199     onRender : function(ct, position){
39200         Ext.form.HtmlEditor.superclass.onRender.call(this, ct, position);
39201         this.el.dom.style.border = '0 none';
39202         this.el.dom.setAttribute('tabIndex', -1);
39203         this.el.addClass('x-hidden');
39204         if(Ext.isIE){ 
39205             this.el.applyStyles('margin-top:-1px;margin-bottom:-1px;')
39206         }
39207         this.wrap = this.el.wrap({
39208             cls:'x-html-editor-wrap', cn:{cls:'x-html-editor-tb'}
39209         });
39210
39211         this.createToolbar(this);
39212
39213         this.disableItems(true);
39214         
39215         
39216
39217         this.createIFrame();
39218
39219         if(!this.width){
39220             var sz = this.el.getSize();
39221             this.setSize(sz.width, this.height || sz.height);
39222         }
39223         this.resizeEl = this.positionEl = this.wrap;
39224     },
39225
39226     createIFrame: function(){
39227         var iframe = document.createElement('iframe');
39228         iframe.name = Ext.id();
39229         iframe.frameBorder = '0';
39230         iframe.src = Ext.SSL_SECURE_URL;
39231         this.wrap.dom.appendChild(iframe);
39232
39233         this.iframe = iframe;
39234
39235         this.monitorTask = Ext.TaskMgr.start({
39236             run: this.checkDesignMode,
39237             scope: this,
39238             interval:100
39239         });
39240     },
39241
39242     initFrame : function(){
39243         Ext.TaskMgr.stop(this.monitorTask);
39244         var doc = this.getDoc();
39245         this.win = this.getWin();
39246
39247         doc.open();
39248         doc.write(this.getDocMarkup());
39249         doc.close();
39250
39251         var task = { 
39252             run : function(){
39253                 var doc = this.getDoc();
39254                 if(doc.body || doc.readyState == 'complete'){
39255                     Ext.TaskMgr.stop(task);
39256                     doc.designMode="on";
39257                     this.initEditor.defer(10, this);
39258                 }
39259             },
39260             interval : 10,
39261             duration:10000,
39262             scope: this
39263         };
39264         Ext.TaskMgr.start(task);
39265     },
39266
39267
39268     checkDesignMode : function(){
39269         if(this.wrap && this.wrap.dom.offsetWidth){
39270             var doc = this.getDoc();
39271             if(!doc){
39272                 return;
39273             }
39274             if(!doc.editorInitialized || String(doc.designMode).toLowerCase() != 'on'){
39275                 this.initFrame();
39276             }
39277         }
39278     },
39279
39280     disableItems: function(disabled){
39281         if(this.fontSelect){
39282             this.fontSelect.dom.disabled = disabled;
39283         }
39284         this.tb.items.each(function(item){
39285             if(item.getItemId() != 'sourceedit'){
39286                 item.setDisabled(disabled);
39287             }
39288         });
39289     },
39290
39291     
39292     onResize : function(w, h){
39293         Ext.form.HtmlEditor.superclass.onResize.apply(this, arguments);
39294         if(this.el && this.iframe){
39295             if(Ext.isNumber(w)){
39296                 var aw = w - this.wrap.getFrameWidth('lr');
39297                 this.el.setWidth(aw);
39298                 this.tb.setWidth(aw);
39299                 this.iframe.style.width = Math.max(aw, 0) + 'px';
39300             }
39301             if(Ext.isNumber(h)){
39302                 var ah = h - this.wrap.getFrameWidth('tb') - this.tb.el.getHeight();
39303                 this.el.setHeight(ah);
39304                 this.iframe.style.height = Math.max(ah, 0) + 'px';
39305                 var bd = this.getEditorBody();
39306                 if(bd){
39307                     bd.style.height = Math.max((ah - (this.iframePad*2)), 0) + 'px';
39308                 }
39309             }
39310         }
39311     },
39312
39313     
39314     toggleSourceEdit : function(sourceEditMode){
39315         if(sourceEditMode === undefined){
39316             sourceEditMode = !this.sourceEditMode;
39317         }
39318         this.sourceEditMode = sourceEditMode === true;
39319         var btn = this.tb.getComponent('sourceedit');
39320         
39321         if(btn.pressed !== this.sourceEditMode){
39322             btn.toggle(this.sourceEditMode);
39323             if(!btn.xtbHidden){
39324                 return;
39325             }
39326         }
39327         if(this.sourceEditMode){
39328             this.disableItems(true);
39329             this.syncValue();
39330             this.iframe.className = 'x-hidden';
39331             this.el.removeClass('x-hidden');
39332             this.el.dom.removeAttribute('tabIndex');
39333             this.el.focus();
39334         }else{
39335             if(this.initialized && !this.readOnly){
39336                 this.disableItems(false);
39337             }
39338             this.pushValue();
39339             this.iframe.className = '';
39340             this.el.addClass('x-hidden');
39341             this.el.dom.setAttribute('tabIndex', -1);
39342             this.deferFocus();
39343         }
39344         var lastSize = this.lastSize;
39345         if(lastSize){
39346             delete this.lastSize;
39347             this.setSize(lastSize);
39348         }
39349         this.fireEvent('editmodechange', this, this.sourceEditMode);
39350     },
39351
39352     
39353     createLink : function(){
39354         var url = prompt(this.createLinkText, this.defaultLinkValue);
39355         if(url && url != 'http:/'+'/'){
39356             this.relayCmd('createlink', url);
39357         }
39358     },
39359
39360     
39361     initEvents : function(){
39362         this.originalValue = this.getValue();
39363     },
39364
39365     
39366     markInvalid : Ext.emptyFn,
39367
39368     
39369     clearInvalid : Ext.emptyFn,
39370
39371     
39372     setValue : function(v){
39373         Ext.form.HtmlEditor.superclass.setValue.call(this, v);
39374         this.pushValue();
39375         return this;
39376     },
39377
39378     
39379     cleanHtml: function(html) {
39380         html = String(html);
39381         if(Ext.isWebKit){ 
39382             html = html.replace(/\sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi, '');
39383         }
39384
39385         
39386         if(html.charCodeAt(0) == this.defaultValue.replace(/\D/g, '')){
39387             html = html.substring(1);
39388         }
39389         return html;
39390     },
39391
39392     
39393     syncValue : function(){
39394         if(this.initialized){
39395             var bd = this.getEditorBody();
39396             var html = bd.innerHTML;
39397             if(Ext.isWebKit){
39398                 var bs = bd.getAttribute('style'); 
39399                 var m = bs.match(/text-align:(.*?);/i);
39400                 if(m && m[1]){
39401                     html = '<div style="'+m[0]+'">' + html + '</div>';
39402                 }
39403             }
39404             html = this.cleanHtml(html);
39405             if(this.fireEvent('beforesync', this, html) !== false){
39406                 this.el.dom.value = html;
39407                 this.fireEvent('sync', this, html);
39408             }
39409         }
39410     },
39411
39412     
39413     getValue : function() {
39414         this[this.sourceEditMode ? 'pushValue' : 'syncValue']();
39415         return Ext.form.HtmlEditor.superclass.getValue.call(this);
39416     },
39417
39418     
39419     pushValue : function(){
39420         if(this.initialized){
39421             var v = this.el.dom.value;
39422             if(!this.activated && v.length < 1){
39423                 v = this.defaultValue;
39424             }
39425             if(this.fireEvent('beforepush', this, v) !== false){
39426                 this.getEditorBody().innerHTML = v;
39427                 if(Ext.isGecko){
39428                     
39429                     var d = this.getDoc(),
39430                         mode = d.designMode.toLowerCase();
39431
39432                     d.designMode = mode.toggle('on', 'off');
39433                     d.designMode = mode;
39434                 }
39435                 this.fireEvent('push', this, v);
39436             }
39437         }
39438     },
39439
39440     
39441     deferFocus : function(){
39442         this.focus.defer(10, this);
39443     },
39444
39445     
39446     focus : function(){
39447         if(this.win && !this.sourceEditMode){
39448             this.win.focus();
39449         }else{
39450             this.el.focus();
39451         }
39452     },
39453
39454     
39455     initEditor : function(){
39456         
39457         try{
39458             var dbody = this.getEditorBody(),
39459                 ss = this.el.getStyles('font-size', 'font-family', 'background-image', 'background-repeat'),
39460                 doc,
39461                 fn;
39462                 
39463             ss['background-attachment'] = 'fixed'; 
39464             dbody.bgProperties = 'fixed'; 
39465
39466             Ext.DomHelper.applyStyles(dbody, ss);
39467             
39468             doc = this.getDoc();
39469
39470             if(doc){
39471                 try{
39472                     Ext.EventManager.removeAll(doc);
39473                 }catch(e){}
39474             }
39475
39476             
39477             fn = this.onEditorEvent.createDelegate(this);
39478             Ext.EventManager.on(doc, {
39479                 mousedown: fn,
39480                 dblclick: fn,
39481                 click: fn,
39482                 keyup: fn,
39483                 buffer:100
39484             });
39485
39486             if(Ext.isGecko){
39487                 Ext.EventManager.on(doc, 'keypress', this.applyCommand, this);
39488             }
39489             if(Ext.isIE || Ext.isWebKit || Ext.isOpera){
39490                 Ext.EventManager.on(doc, 'keydown', this.fixKeys, this);
39491             }
39492             doc.editorInitialized = true;
39493             this.initialized = true;
39494             this.pushValue();
39495             this.setReadOnly(this.readOnly);
39496             this.fireEvent('initialize', this);
39497         }catch(e){}
39498     },
39499
39500     
39501     onDestroy : function(){
39502         if(this.monitorTask){
39503             Ext.TaskMgr.stop(this.monitorTask);
39504         }
39505         if(this.rendered){
39506             Ext.destroy(this.tb);
39507             var doc = this.getDoc();
39508             if(doc){
39509                 try{
39510                     Ext.EventManager.removeAll(doc);
39511                     for (var prop in doc){
39512                         delete doc[prop];
39513                     }
39514                 }catch(e){}
39515             }
39516             if(this.wrap){
39517                 this.wrap.dom.innerHTML = '';
39518                 this.wrap.remove();
39519             }
39520         }
39521         
39522         if(this.el){
39523             this.el.removeAllListeners();
39524             this.el.remove();
39525         }
39526         this.purgeListeners();
39527     },
39528
39529     
39530     onFirstFocus : function(){
39531         this.activated = true;
39532         this.disableItems(false);
39533         if(Ext.isGecko){ 
39534             this.win.focus();
39535             var s = this.win.getSelection();
39536             if(!s.focusNode || s.focusNode.nodeType != 3){
39537                 var r = s.getRangeAt(0);
39538                 r.selectNodeContents(this.getEditorBody());
39539                 r.collapse(true);
39540                 this.deferFocus();
39541             }
39542             try{
39543                 this.execCmd('useCSS', true);
39544                 this.execCmd('styleWithCSS', false);
39545             }catch(e){}
39546         }
39547         this.fireEvent('activate', this);
39548     },
39549
39550     
39551     adjustFont: function(btn){
39552         var adjust = btn.getItemId() == 'increasefontsize' ? 1 : -1,
39553             doc = this.getDoc(),
39554             v = parseInt(doc.queryCommandValue('FontSize') || 2, 10);
39555         if((Ext.isSafari && !Ext.isSafari2) || Ext.isChrome || Ext.isAir){
39556             
39557             
39558             if(v <= 10){
39559                 v = 1 + adjust;
39560             }else if(v <= 13){
39561                 v = 2 + adjust;
39562             }else if(v <= 16){
39563                 v = 3 + adjust;
39564             }else if(v <= 18){
39565                 v = 4 + adjust;
39566             }else if(v <= 24){
39567                 v = 5 + adjust;
39568             }else {
39569                 v = 6 + adjust;
39570             }
39571             v = v.constrain(1, 6);
39572         }else{
39573             if(Ext.isSafari){ 
39574                 adjust *= 2;
39575             }
39576             v = Math.max(1, v+adjust) + (Ext.isSafari ? 'px' : 0);
39577         }
39578         this.execCmd('FontSize', v);
39579     },
39580
39581     
39582     onEditorEvent : function(e){
39583         this.updateToolbar();
39584     },
39585
39586
39587     
39588     updateToolbar: function(){
39589
39590         if(this.readOnly){
39591             return;
39592         }
39593
39594         if(!this.activated){
39595             this.onFirstFocus();
39596             return;
39597         }
39598
39599         var btns = this.tb.items.map, 
39600             doc = this.getDoc();
39601
39602         if(this.enableFont && !Ext.isSafari2){
39603             var name = (doc.queryCommandValue('FontName')||this.defaultFont).toLowerCase();
39604             if(name != this.fontSelect.dom.value){
39605                 this.fontSelect.dom.value = name;
39606             }
39607         }
39608         if(this.enableFormat){
39609             btns.bold.toggle(doc.queryCommandState('bold'));
39610             btns.italic.toggle(doc.queryCommandState('italic'));
39611             btns.underline.toggle(doc.queryCommandState('underline'));
39612         }
39613         if(this.enableAlignments){
39614             btns.justifyleft.toggle(doc.queryCommandState('justifyleft'));
39615             btns.justifycenter.toggle(doc.queryCommandState('justifycenter'));
39616             btns.justifyright.toggle(doc.queryCommandState('justifyright'));
39617         }
39618         if(!Ext.isSafari2 && this.enableLists){
39619             btns.insertorderedlist.toggle(doc.queryCommandState('insertorderedlist'));
39620             btns.insertunorderedlist.toggle(doc.queryCommandState('insertunorderedlist'));
39621         }
39622
39623         Ext.menu.MenuMgr.hideAll();
39624
39625         this.syncValue();
39626     },
39627
39628     
39629     relayBtnCmd : function(btn){
39630         this.relayCmd(btn.getItemId());
39631     },
39632
39633     
39634     relayCmd : function(cmd, value){
39635         (function(){
39636             this.focus();
39637             this.execCmd(cmd, value);
39638             this.updateToolbar();
39639         }).defer(10, this);
39640     },
39641
39642     
39643     execCmd : function(cmd, value){
39644         var doc = this.getDoc();
39645         doc.execCommand(cmd, false, value === undefined ? null : value);
39646         this.syncValue();
39647     },
39648
39649     
39650     applyCommand : function(e){
39651         if(e.ctrlKey){
39652             var c = e.getCharCode(), cmd;
39653             if(c > 0){
39654                 c = String.fromCharCode(c);
39655                 switch(c){
39656                     case 'b':
39657                         cmd = 'bold';
39658                     break;
39659                     case 'i':
39660                         cmd = 'italic';
39661                     break;
39662                     case 'u':
39663                         cmd = 'underline';
39664                     break;
39665                 }
39666                 if(cmd){
39667                     this.win.focus();
39668                     this.execCmd(cmd);
39669                     this.deferFocus();
39670                     e.preventDefault();
39671                 }
39672             }
39673         }
39674     },
39675
39676     
39677     insertAtCursor : function(text){
39678         if(!this.activated){
39679             return;
39680         }
39681         if(Ext.isIE){
39682             this.win.focus();
39683             var doc = this.getDoc(),
39684                 r = doc.selection.createRange();
39685             if(r){
39686                 r.pasteHTML(text);
39687                 this.syncValue();
39688                 this.deferFocus();
39689             }
39690         }else{
39691             this.win.focus();
39692             this.execCmd('InsertHTML', text);
39693             this.deferFocus();
39694         }
39695     },
39696
39697     
39698     fixKeys : function(){ 
39699         if(Ext.isIE){
39700             return function(e){
39701                 var k = e.getKey(), 
39702                     doc = this.getDoc(),
39703                         r;
39704                 if(k == e.TAB){
39705                     e.stopEvent();
39706                     r = doc.selection.createRange();
39707                     if(r){
39708                         r.collapse(true);
39709                         r.pasteHTML('&nbsp;&nbsp;&nbsp;&nbsp;');
39710                         this.deferFocus();
39711                     }
39712                 }else if(k == e.ENTER){
39713                     r = doc.selection.createRange();
39714                     if(r){
39715                         var target = r.parentElement();
39716                         if(!target || target.tagName.toLowerCase() != 'li'){
39717                             e.stopEvent();
39718                             r.pasteHTML('<br />');
39719                             r.collapse(false);
39720                             r.select();
39721                         }
39722                     }
39723                 }
39724             };
39725         }else if(Ext.isOpera){
39726             return function(e){
39727                 var k = e.getKey();
39728                 if(k == e.TAB){
39729                     e.stopEvent();
39730                     this.win.focus();
39731                     this.execCmd('InsertHTML','&nbsp;&nbsp;&nbsp;&nbsp;');
39732                     this.deferFocus();
39733                 }
39734             };
39735         }else if(Ext.isWebKit){
39736             return function(e){
39737                 var k = e.getKey();
39738                 if(k == e.TAB){
39739                     e.stopEvent();
39740                     this.execCmd('InsertText','\t');
39741                     this.deferFocus();
39742                 }else if(k == e.ENTER){
39743                     e.stopEvent();
39744                     this.execCmd('InsertHtml','<br /><br />');
39745                     this.deferFocus();
39746                 }
39747              };
39748         }
39749     }(),
39750
39751     
39752     getToolbar : function(){
39753         return this.tb;
39754     },
39755
39756     
39757     buttonTips : {
39758         bold : {
39759             title: 'Bold (Ctrl+B)',
39760             text: 'Make the selected text bold.',
39761             cls: 'x-html-editor-tip'
39762         },
39763         italic : {
39764             title: 'Italic (Ctrl+I)',
39765             text: 'Make the selected text italic.',
39766             cls: 'x-html-editor-tip'
39767         },
39768         underline : {
39769             title: 'Underline (Ctrl+U)',
39770             text: 'Underline the selected text.',
39771             cls: 'x-html-editor-tip'
39772         },
39773         increasefontsize : {
39774             title: 'Grow Text',
39775             text: 'Increase the font size.',
39776             cls: 'x-html-editor-tip'
39777         },
39778         decreasefontsize : {
39779             title: 'Shrink Text',
39780             text: 'Decrease the font size.',
39781             cls: 'x-html-editor-tip'
39782         },
39783         backcolor : {
39784             title: 'Text Highlight Color',
39785             text: 'Change the background color of the selected text.',
39786             cls: 'x-html-editor-tip'
39787         },
39788         forecolor : {
39789             title: 'Font Color',
39790             text: 'Change the color of the selected text.',
39791             cls: 'x-html-editor-tip'
39792         },
39793         justifyleft : {
39794             title: 'Align Text Left',
39795             text: 'Align text to the left.',
39796             cls: 'x-html-editor-tip'
39797         },
39798         justifycenter : {
39799             title: 'Center Text',
39800             text: 'Center text in the editor.',
39801             cls: 'x-html-editor-tip'
39802         },
39803         justifyright : {
39804             title: 'Align Text Right',
39805             text: 'Align text to the right.',
39806             cls: 'x-html-editor-tip'
39807         },
39808         insertunorderedlist : {
39809             title: 'Bullet List',
39810             text: 'Start a bulleted list.',
39811             cls: 'x-html-editor-tip'
39812         },
39813         insertorderedlist : {
39814             title: 'Numbered List',
39815             text: 'Start a numbered list.',
39816             cls: 'x-html-editor-tip'
39817         },
39818         createlink : {
39819             title: 'Hyperlink',
39820             text: 'Make the selected text a hyperlink.',
39821             cls: 'x-html-editor-tip'
39822         },
39823         sourceedit : {
39824             title: 'Source Edit',
39825             text: 'Switch to source editing mode.',
39826             cls: 'x-html-editor-tip'
39827         }
39828     }
39829
39830     
39831     
39832     
39833     
39834     
39835     
39836     
39837     
39838     
39839     
39840     
39841     
39842     
39843     
39844     
39845     
39846     
39847     
39848     
39849     
39850     
39851     
39852     
39853     
39854     
39855     
39856     
39857     
39858     
39859     
39860     
39861     
39862     
39863     
39864 });
39865 Ext.reg('htmleditor', Ext.form.HtmlEditor);
39866 Ext.form.TimeField = Ext.extend(Ext.form.ComboBox, {
39867     
39868     minValue : undefined,
39869     
39870     maxValue : undefined,
39871     
39872     minText : "The time in this field must be equal to or after {0}",
39873     
39874     maxText : "The time in this field must be equal to or before {0}",
39875     
39876     invalidText : "{0} is not a valid time",
39877     
39878     format : "g:i A",
39879     
39880     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",
39881     
39882     increment: 15,
39883
39884     
39885     mode: 'local',
39886     
39887     triggerAction: 'all',
39888     
39889     typeAhead: false,
39890     
39891     
39892     
39893     
39894     initDate: '1/1/2008',
39895
39896     
39897     initComponent : function(){
39898         if(Ext.isDefined(this.minValue)){
39899             this.setMinValue(this.minValue, true);
39900         }
39901         if(Ext.isDefined(this.maxValue)){
39902             this.setMaxValue(this.maxValue, true);
39903         }
39904         if(!this.store){
39905             this.generateStore(true);
39906         }
39907         Ext.form.TimeField.superclass.initComponent.call(this);
39908     },
39909     
39910     
39911     setMinValue: function(value,  initial){
39912         this.setLimit(value, true, initial);
39913         return this;
39914     },
39915
39916     
39917     setMaxValue: function(value,  initial){
39918         this.setLimit(value, false, initial);
39919         return this;
39920     },
39921     
39922     
39923     generateStore: function(initial){
39924         var min = this.minValue || new Date(this.initDate).clearTime(),
39925             max = this.maxValue || new Date(this.initDate).clearTime().add('mi', (24 * 60) - 1),
39926             times = [];
39927             
39928         while(min <= max){
39929             times.push(min.dateFormat(this.format));
39930             min = min.add('mi', this.increment);
39931         }
39932         this.bindStore(times, initial);
39933     },
39934
39935     
39936     setLimit: function(value, isMin, initial){
39937         var d;
39938         if(Ext.isString(value)){
39939             d = this.parseDate(value);
39940         }else if(Ext.isDate(value)){
39941             d = value;
39942         }
39943         if(d){
39944             var val = new Date(this.initDate).clearTime();
39945             val.setHours(d.getHours(), d.getMinutes(), isMin ? 0 : 59, 0);
39946             this[isMin ? 'minValue' : 'maxValue'] = val;
39947             if(!initial){
39948                 this.generateStore();
39949             }
39950         }
39951     },
39952     
39953     
39954     getValue : function(){
39955         var v = Ext.form.TimeField.superclass.getValue.call(this);
39956         return this.formatDate(this.parseDate(v)) || '';
39957     },
39958
39959     
39960     setValue : function(value){
39961         return Ext.form.TimeField.superclass.setValue.call(this, this.formatDate(this.parseDate(value)));
39962     },
39963
39964     
39965     validateValue : Ext.form.DateField.prototype.validateValue,
39966     parseDate : Ext.form.DateField.prototype.parseDate,
39967     formatDate : Ext.form.DateField.prototype.formatDate,
39968
39969     
39970     beforeBlur : function(){
39971         var v = this.parseDate(this.getRawValue());
39972         if(v){
39973             this.setValue(v.dateFormat(this.format));
39974         }
39975         Ext.form.TimeField.superclass.beforeBlur.call(this);
39976     }
39977
39978     
39979     
39980     
39981     
39982 });
39983 Ext.reg('timefield', Ext.form.TimeField);
39984 Ext.form.Label = Ext.extend(Ext.BoxComponent, {
39985     
39986     
39987     
39988
39989     
39990     onRender : function(ct, position){
39991         if(!this.el){
39992             this.el = document.createElement('label');
39993             this.el.id = this.getId();
39994             this.el.innerHTML = this.text ? Ext.util.Format.htmlEncode(this.text) : (this.html || '');
39995             if(this.forId){
39996                 this.el.setAttribute('for', this.forId);
39997             }
39998         }
39999         Ext.form.Label.superclass.onRender.call(this, ct, position);
40000     },
40001
40002     
40003     setText : function(t, encode){
40004         var e = encode === false;
40005         this[!e ? 'text' : 'html'] = t;
40006         delete this[e ? 'text' : 'html'];
40007         if(this.rendered){
40008             this.el.dom.innerHTML = encode !== false ? Ext.util.Format.htmlEncode(t) : t;
40009         }
40010         return this;
40011     }
40012 });
40013
40014 Ext.reg('label', Ext.form.Label);
40015 Ext.form.Action = function(form, options){
40016     this.form = form;
40017     this.options = options || {};
40018 };
40019
40020
40021 Ext.form.Action.CLIENT_INVALID = 'client';
40022
40023 Ext.form.Action.SERVER_INVALID = 'server';
40024
40025 Ext.form.Action.CONNECT_FAILURE = 'connect';
40026
40027 Ext.form.Action.LOAD_FAILURE = 'load';
40028
40029 Ext.form.Action.prototype = {
40030
40031
40032
40033
40034
40035
40036
40037
40038
40039
40040
40041
40042     type : 'default',
40043
40044  
40045  
40046
40047     
40048     run : function(options){
40049
40050     },
40051
40052     
40053     success : function(response){
40054
40055     },
40056
40057     
40058     handleResponse : function(response){
40059
40060     },
40061
40062     
40063     failure : function(response){
40064         this.response = response;
40065         this.failureType = Ext.form.Action.CONNECT_FAILURE;
40066         this.form.afterAction(this, false);
40067     },
40068
40069     
40070     
40071     
40072     processResponse : function(response){
40073         this.response = response;
40074         if(!response.responseText && !response.responseXML){
40075             return true;
40076         }
40077         this.result = this.handleResponse(response);
40078         return this.result;
40079     },
40080
40081     
40082     getUrl : function(appendParams){
40083         var url = this.options.url || this.form.url || this.form.el.dom.action;
40084         if(appendParams){
40085             var p = this.getParams();
40086             if(p){
40087                 url = Ext.urlAppend(url, p);
40088             }
40089         }
40090         return url;
40091     },
40092
40093     
40094     getMethod : function(){
40095         return (this.options.method || this.form.method || this.form.el.dom.method || 'POST').toUpperCase();
40096     },
40097
40098     
40099     getParams : function(){
40100         var bp = this.form.baseParams;
40101         var p = this.options.params;
40102         if(p){
40103             if(typeof p == "object"){
40104                 p = Ext.urlEncode(Ext.applyIf(p, bp));
40105             }else if(typeof p == 'string' && bp){
40106                 p += '&' + Ext.urlEncode(bp);
40107             }
40108         }else if(bp){
40109             p = Ext.urlEncode(bp);
40110         }
40111         return p;
40112     },
40113
40114     
40115     createCallback : function(opts){
40116         var opts = opts || {};
40117         return {
40118             success: this.success,
40119             failure: this.failure,
40120             scope: this,
40121             timeout: (opts.timeout*1000) || (this.form.timeout*1000),
40122             upload: this.form.fileUpload ? this.success : undefined
40123         };
40124     }
40125 };
40126
40127
40128 Ext.form.Action.Submit = function(form, options){
40129     Ext.form.Action.Submit.superclass.constructor.call(this, form, options);
40130 };
40131
40132 Ext.extend(Ext.form.Action.Submit, Ext.form.Action, {
40133     
40134     
40135     type : 'submit',
40136
40137     
40138     run : function(){
40139         var o = this.options;
40140         var method = this.getMethod();
40141         var isGet = method == 'GET';
40142         if(o.clientValidation === false || this.form.isValid()){
40143             Ext.Ajax.request(Ext.apply(this.createCallback(o), {
40144                 form:this.form.el.dom,
40145                 url:this.getUrl(isGet),
40146                 method: method,
40147                 headers: o.headers,
40148                 params:!isGet ? this.getParams() : null,
40149                 isUpload: this.form.fileUpload
40150             }));
40151         }else if (o.clientValidation !== false){ 
40152             this.failureType = Ext.form.Action.CLIENT_INVALID;
40153             this.form.afterAction(this, false);
40154         }
40155     },
40156
40157     
40158     success : function(response){
40159         var result = this.processResponse(response);
40160         if(result === true || result.success){
40161             this.form.afterAction(this, true);
40162             return;
40163         }
40164         if(result.errors){
40165             this.form.markInvalid(result.errors);
40166         }
40167         this.failureType = Ext.form.Action.SERVER_INVALID;
40168         this.form.afterAction(this, false);
40169     },
40170
40171     
40172     handleResponse : function(response){
40173         if(this.form.errorReader){
40174             var rs = this.form.errorReader.read(response);
40175             var errors = [];
40176             if(rs.records){
40177                 for(var i = 0, len = rs.records.length; i < len; i++) {
40178                     var r = rs.records[i];
40179                     errors[i] = r.data;
40180                 }
40181             }
40182             if(errors.length < 1){
40183                 errors = null;
40184             }
40185             return {
40186                 success : rs.success,
40187                 errors : errors
40188             };
40189         }
40190         return Ext.decode(response.responseText);
40191     }
40192 });
40193
40194
40195
40196 Ext.form.Action.Load = function(form, options){
40197     Ext.form.Action.Load.superclass.constructor.call(this, form, options);
40198     this.reader = this.form.reader;
40199 };
40200
40201 Ext.extend(Ext.form.Action.Load, Ext.form.Action, {
40202     
40203     type : 'load',
40204
40205     
40206     run : function(){
40207         Ext.Ajax.request(Ext.apply(
40208                 this.createCallback(this.options), {
40209                     method:this.getMethod(),
40210                     url:this.getUrl(false),
40211                     headers: this.options.headers,
40212                     params:this.getParams()
40213         }));
40214     },
40215
40216     
40217     success : function(response){
40218         var result = this.processResponse(response);
40219         if(result === true || !result.success || !result.data){
40220             this.failureType = Ext.form.Action.LOAD_FAILURE;
40221             this.form.afterAction(this, false);
40222             return;
40223         }
40224         this.form.clearInvalid();
40225         this.form.setValues(result.data);
40226         this.form.afterAction(this, true);
40227     },
40228
40229     
40230     handleResponse : function(response){
40231         if(this.form.reader){
40232             var rs = this.form.reader.read(response);
40233             var data = rs.records && rs.records[0] ? rs.records[0].data : null;
40234             return {
40235                 success : rs.success,
40236                 data : data
40237             };
40238         }
40239         return Ext.decode(response.responseText);
40240     }
40241 });
40242
40243
40244
40245
40246 Ext.form.Action.DirectLoad = Ext.extend(Ext.form.Action.Load, {
40247     constructor: function(form, opts) {
40248         Ext.form.Action.DirectLoad.superclass.constructor.call(this, form, opts);
40249     },
40250     type : 'directload',
40251
40252     run : function(){
40253         var args = this.getParams();
40254         args.push(this.success, this);
40255         this.form.api.load.apply(window, args);
40256     },
40257
40258     getParams : function() {
40259         var buf = [], o = {};
40260         var bp = this.form.baseParams;
40261         var p = this.options.params;
40262         Ext.apply(o, p, bp);
40263         var paramOrder = this.form.paramOrder;
40264         if(paramOrder){
40265             for(var i = 0, len = paramOrder.length; i < len; i++){
40266                 buf.push(o[paramOrder[i]]);
40267             }
40268         }else if(this.form.paramsAsHash){
40269             buf.push(o);
40270         }
40271         return buf;
40272     },
40273     
40274     
40275     
40276     processResponse : function(result) {
40277         this.result = result;
40278         return result;
40279     },
40280     
40281     success : function(response, trans){
40282         if(trans.type == Ext.Direct.exceptions.SERVER){
40283             response = {};
40284         }
40285         Ext.form.Action.DirectLoad.superclass.success.call(this, response);
40286     }
40287 });
40288
40289
40290 Ext.form.Action.DirectSubmit = Ext.extend(Ext.form.Action.Submit, {
40291     constructor : function(form, opts) {
40292         Ext.form.Action.DirectSubmit.superclass.constructor.call(this, form, opts);
40293     },
40294     type : 'directsubmit',
40295     
40296     run : function(){
40297         var o = this.options;
40298         if(o.clientValidation === false || this.form.isValid()){
40299             
40300             
40301             this.success.params = this.getParams();
40302             this.form.api.submit(this.form.el.dom, this.success, this);
40303         }else if (o.clientValidation !== false){ 
40304             this.failureType = Ext.form.Action.CLIENT_INVALID;
40305             this.form.afterAction(this, false);
40306         }
40307     },
40308
40309     getParams : function() {
40310         var o = {};
40311         var bp = this.form.baseParams;
40312         var p = this.options.params;
40313         Ext.apply(o, p, bp);
40314         return o;
40315     },
40316     
40317     
40318     
40319     processResponse : function(result) {
40320         this.result = result;
40321         return result;
40322     },
40323     
40324     success : function(response, trans){
40325         if(trans.type == Ext.Direct.exceptions.SERVER){
40326             response = {};
40327         }
40328         Ext.form.Action.DirectSubmit.superclass.success.call(this, response);
40329     }
40330 });
40331
40332 Ext.form.Action.ACTION_TYPES = {
40333     'load' : Ext.form.Action.Load,
40334     'submit' : Ext.form.Action.Submit,
40335     'directload' : Ext.form.Action.DirectLoad,
40336     'directsubmit' : Ext.form.Action.DirectSubmit
40337 };
40338
40339 Ext.form.VTypes = function(){
40340     
40341     var alpha = /^[a-zA-Z_]+$/,
40342         alphanum = /^[a-zA-Z0-9_]+$/,
40343         email = /^(\w+)([\-+.][\w]+)*@(\w[\-\w]*\.){1,5}([A-Za-z]){2,6}$/,
40344         url = /(((^https?)|(^ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
40345
40346     
40347     return {
40348         
40349         'email' : function(v){
40350             return email.test(v);
40351         },
40352         
40353         'emailText' : 'This field should be an e-mail address in the format "user@example.com"',
40354         
40355         'emailMask' : /[a-z0-9_\.\-@]/i,
40356
40357         
40358         'url' : function(v){
40359             return url.test(v);
40360         },
40361         
40362         'urlText' : 'This field should be a URL in the format "http:/'+'/www.example.com"',
40363         
40364         
40365         'alpha' : function(v){
40366             return alpha.test(v);
40367         },
40368         
40369         'alphaText' : 'This field should only contain letters and _',
40370         
40371         'alphaMask' : /[a-z_]/i,
40372
40373         
40374         'alphanum' : function(v){
40375             return alphanum.test(v);
40376         },
40377         
40378         'alphanumText' : 'This field should only contain letters, numbers and _',
40379         
40380         'alphanumMask' : /[a-z0-9_]/i
40381     };
40382 }();
40383 Ext.grid.GridPanel = Ext.extend(Ext.Panel, {
40384     
40385     autoExpandColumn : false,
40386     
40387     autoExpandMax : 1000,
40388     
40389     autoExpandMin : 50,
40390     
40391     columnLines : false,
40392     
40393     
40394     
40395     
40396     
40397     ddText : '{0} selected row{1}',
40398     
40399     deferRowRender : true,
40400     
40401     
40402     
40403     enableColumnHide : true,
40404     
40405     enableColumnMove : true,
40406     
40407     enableDragDrop : false,
40408     
40409     enableHdMenu : true,
40410     
40411     
40412     loadMask : false,
40413     
40414     
40415     minColumnWidth : 25,
40416     
40417     
40418     
40419     
40420     stripeRows : false,
40421     
40422     trackMouseOver : true,
40423     
40424     stateEvents : ['columnmove', 'columnresize', 'sortchange'],
40425     
40426     view : null,
40427     
40428     
40429     bubbleEvents: [],
40430     
40431     
40432
40433     
40434     rendered : false,
40435     
40436     viewReady : false,
40437
40438     
40439     initComponent : function(){
40440         Ext.grid.GridPanel.superclass.initComponent.call(this);
40441
40442         if(this.columnLines){
40443             this.cls = (this.cls || '') + ' x-grid-with-col-lines';
40444         }
40445         
40446         
40447         this.autoScroll = false;
40448         this.autoWidth = false;
40449
40450         if(Ext.isArray(this.columns)){
40451             this.colModel = new Ext.grid.ColumnModel(this.columns);
40452             delete this.columns;
40453         }
40454
40455         
40456         if(this.ds){
40457             this.store = this.ds;
40458             delete this.ds;
40459         }
40460         if(this.cm){
40461             this.colModel = this.cm;
40462             delete this.cm;
40463         }
40464         if(this.sm){
40465             this.selModel = this.sm;
40466             delete this.sm;
40467         }
40468         this.store = Ext.StoreMgr.lookup(this.store);
40469
40470         this.addEvents(
40471             
40472             
40473             'click',
40474             
40475             'dblclick',
40476             
40477             'contextmenu',
40478             
40479             'mousedown',
40480             
40481             'mouseup',
40482             
40483             'mouseover',
40484             
40485             'mouseout',
40486             
40487             'keypress',
40488             
40489             'keydown',
40490
40491             
40492             
40493             'cellmousedown',
40494             
40495             'rowmousedown',
40496             
40497             'headermousedown',
40498             
40499             
40500             'groupmousedown',
40501             
40502             
40503             'rowbodymousedown',
40504             
40505             
40506             'containermousedown',
40507
40508             
40509             'cellclick',
40510             
40511             'celldblclick',
40512             
40513             'rowclick',
40514             
40515             'rowdblclick',
40516             
40517             'headerclick',
40518             
40519             'headerdblclick',
40520             
40521             'groupclick',
40522             
40523             'groupdblclick',
40524             
40525             'containerclick',
40526             
40527             'containerdblclick',
40528             
40529             
40530             'rowbodyclick',
40531             
40532             'rowbodydblclick',
40533             
40534             
40535             'rowcontextmenu',
40536             
40537             'cellcontextmenu',
40538             
40539             'headercontextmenu',
40540             
40541             'groupcontextmenu',
40542             
40543             'containercontextmenu',
40544             
40545             'rowbodycontextmenu',
40546             
40547             'bodyscroll',
40548             
40549             'columnresize',
40550             
40551             'columnmove',
40552             
40553             'sortchange',
40554             
40555             'reconfigure',
40556             
40557             'viewready'
40558         );
40559     },
40560
40561     
40562     onRender : function(ct, position){
40563         Ext.grid.GridPanel.superclass.onRender.apply(this, arguments);
40564
40565         var c = this.getGridEl();
40566
40567         this.el.addClass('x-grid-panel');
40568
40569         this.mon(c, {
40570             scope: this,
40571             mousedown: this.onMouseDown,
40572             click: this.onClick,
40573             dblclick: this.onDblClick,
40574             contextmenu: this.onContextMenu
40575         });
40576
40577         this.relayEvents(c, ['mousedown','mouseup','mouseover','mouseout','keypress', 'keydown']);
40578
40579         var view = this.getView();
40580         view.init(this);
40581         view.render();
40582         this.getSelectionModel().init(this);
40583     },
40584
40585     
40586     initEvents : function(){
40587         Ext.grid.GridPanel.superclass.initEvents.call(this);
40588
40589         if(this.loadMask){
40590             this.loadMask = new Ext.LoadMask(this.bwrap,
40591                     Ext.apply({store:this.store}, this.loadMask));
40592         }
40593     },
40594
40595     initStateEvents : function(){
40596         Ext.grid.GridPanel.superclass.initStateEvents.call(this);
40597         this.mon(this.colModel, 'hiddenchange', this.saveState, this, {delay: 100});
40598     },
40599
40600     applyState : function(state){
40601         var cm = this.colModel,
40602             cs = state.columns;
40603         if(cs){
40604             for(var i = 0, len = cs.length; i < len; i++){
40605                 var s = cs[i],
40606                     c = cm.getColumnById(s.id);
40607                 if(c){
40608                     c.hidden = s.hidden;
40609                     c.width = s.width;
40610                     var oldIndex = cm.getIndexById(s.id);
40611                     if(oldIndex != i){
40612                         cm.moveColumn(oldIndex, i);
40613                     }
40614                 }
40615             }
40616         }
40617         if(state.sort && this.store){
40618             this.store[this.store.remoteSort ? 'setDefaultSort' : 'sort'](state.sort.field, state.sort.direction);
40619         }
40620         var o = Ext.apply({}, state);
40621         delete o.columns;
40622         delete o.sort;
40623         Ext.grid.GridPanel.superclass.applyState.call(this, o);
40624     },
40625
40626     getState : function(){
40627         var o = {columns: []};
40628         for(var i = 0, c; (c = this.colModel.config[i]); i++){
40629             o.columns[i] = {
40630                 id: c.id,
40631                 width: c.width
40632             };
40633             if(c.hidden){
40634                 o.columns[i].hidden = true;
40635             }
40636         }
40637         if(this.store){
40638             var ss = this.store.getSortState();
40639             if(ss){
40640                 o.sort = ss;
40641             }
40642         }
40643         return o;
40644     },
40645
40646     
40647     afterRender : function(){
40648         Ext.grid.GridPanel.superclass.afterRender.call(this);
40649         var v = this.view;
40650         this.on('bodyresize', v.layout, v);
40651         v.layout();
40652         if(this.deferRowRender){
40653             v.afterRender.defer(10, this.view);
40654         }else{
40655             v.afterRender();
40656         }
40657         this.viewReady = true;
40658     },
40659
40660     
40661     reconfigure : function(store, colModel){
40662         var rendered = this.rendered;
40663         if(rendered){
40664             if(this.loadMask){
40665                 this.loadMask.destroy();
40666                 this.loadMask = new Ext.LoadMask(this.bwrap,
40667                         Ext.apply({}, {store:store}, this.initialConfig.loadMask));
40668             }
40669         }
40670         if(this.view){
40671             this.view.initData(store, colModel);
40672         }
40673         this.store = store;
40674         this.colModel = colModel;
40675         if(rendered){
40676             this.view.refresh(true);
40677         }
40678         this.fireEvent('reconfigure', this, store, colModel);
40679     },
40680
40681     
40682     onDestroy : function(){
40683         if(this.rendered){
40684             Ext.destroy(this.view, this.loadMask);
40685         }else if(this.store && this.store.autoDestroy){
40686             this.store.destroy();
40687         }
40688         Ext.destroy(this.colModel, this.selModel);
40689         this.store = this.selModel = this.colModel = this.view = this.loadMask = null;
40690         Ext.grid.GridPanel.superclass.onDestroy.call(this);
40691     },
40692
40693     
40694     processEvent : function(name, e){
40695         this.fireEvent(name, e);
40696         var t = e.getTarget(),
40697             v = this.view,
40698             header = v.findHeaderIndex(t);
40699             
40700         if(header !== false){
40701             this.fireEvent('header' + name, this, header, e);
40702         }else{
40703             var row = v.findRowIndex(t),
40704                 cell,
40705                 body;
40706             if(row !== false){
40707                 this.fireEvent('row' + name, this, row, e);
40708                 cell = v.findCellIndex(t);
40709                 body = v.findRowBody(t);
40710                 if(cell !== false){
40711                     this.fireEvent('cell' + name, this, row, cell, e);
40712                 }
40713                 if(body){
40714                     this.fireEvent('rowbody' + name, this, row, e);
40715                 }
40716             }else{
40717                 this.fireEvent('container' + name, this, e);
40718             }
40719         }
40720         this.view.processEvent(name, e);
40721     },
40722
40723     
40724     onClick : function(e){
40725         this.processEvent('click', e);
40726     },
40727
40728     
40729     onMouseDown : function(e){
40730         this.processEvent('mousedown', e);
40731     },
40732
40733     
40734     onContextMenu : function(e, t){
40735         this.processEvent('contextmenu', e);
40736     },
40737
40738     
40739     onDblClick : function(e){
40740         this.processEvent('dblclick', e);
40741     },
40742
40743     
40744     walkCells : function(row, col, step, fn, scope){
40745         var cm = this.colModel, 
40746             clen = cm.getColumnCount(),
40747             ds = this.store, 
40748             rlen = ds.getCount(), 
40749             first = true;
40750         if(step < 0){
40751             if(col < 0){
40752                 row--;
40753                 first = false;
40754             }
40755             while(row >= 0){
40756                 if(!first){
40757                     col = clen-1;
40758                 }
40759                 first = false;
40760                 while(col >= 0){
40761                     if(fn.call(scope || this, row, col, cm) === true){
40762                         return [row, col];
40763                     }
40764                     col--;
40765                 }
40766                 row--;
40767             }
40768         } else {
40769             if(col >= clen){
40770                 row++;
40771                 first = false;
40772             }
40773             while(row < rlen){
40774                 if(!first){
40775                     col = 0;
40776                 }
40777                 first = false;
40778                 while(col < clen){
40779                     if(fn.call(scope || this, row, col, cm) === true){
40780                         return [row, col];
40781                     }
40782                     col++;
40783                 }
40784                 row++;
40785             }
40786         }
40787         return null;
40788     },
40789
40790     
40791     onResize : function(){
40792         Ext.grid.GridPanel.superclass.onResize.apply(this, arguments);
40793         if(this.viewReady){
40794             this.view.layout();
40795         }
40796     },
40797
40798     
40799     getGridEl : function(){
40800         return this.body;
40801     },
40802
40803     
40804     stopEditing : Ext.emptyFn,
40805
40806     
40807     getSelectionModel : function(){
40808         if(!this.selModel){
40809             this.selModel = new Ext.grid.RowSelectionModel(
40810                     this.disableSelection ? {selectRow: Ext.emptyFn} : null);
40811         }
40812         return this.selModel;
40813     },
40814
40815     
40816     getStore : function(){
40817         return this.store;
40818     },
40819
40820     
40821     getColumnModel : function(){
40822         return this.colModel;
40823     },
40824
40825     
40826     getView : function(){
40827         if(!this.view){
40828             this.view = new Ext.grid.GridView(this.viewConfig);
40829         }
40830         return this.view;
40831     },
40832     
40833     getDragDropText : function(){
40834         var count = this.selModel.getCount();
40835         return String.format(this.ddText, count, count == 1 ? '' : 's');
40836     }
40837
40838     
40839     
40840     
40841     
40842     
40843     
40844     
40845     
40846     
40847     
40848     
40849     
40850     
40851     
40852     
40853     
40854     
40855     
40856     
40857     
40858     
40859     
40860     
40861     
40862     
40863     
40864     
40865     
40866     
40867     
40868     
40869
40870
40871
40872     
40873     
40874     
40875     
40876     
40877     
40878     
40879     
40880     
40881     
40882     
40883     
40884     
40885     
40886     
40887     
40888 });
40889 Ext.reg('grid', Ext.grid.GridPanel);
40890 Ext.grid.GridView = Ext.extend(Ext.util.Observable, {
40891     
40892     
40893     
40894     
40895     
40896     
40897     deferEmptyText : true,
40898     
40899     scrollOffset : undefined,
40900     
40901     autoFill : false,
40902     
40903     forceFit : false,
40904     
40905     sortClasses : ['sort-asc', 'sort-desc'],
40906     
40907     sortAscText : 'Sort Ascending',
40908     
40909     sortDescText : 'Sort Descending',
40910     
40911     columnsText : 'Columns',
40912
40913     
40914     selectedRowClass : 'x-grid3-row-selected',
40915
40916     
40917     borderWidth : 2,
40918     tdClass : 'x-grid3-cell',
40919     hdCls : 'x-grid3-hd',
40920     markDirty : true,
40921
40922     
40923     cellSelectorDepth : 4,
40924     
40925     rowSelectorDepth : 10,
40926     
40927     
40928     rowBodySelectorDepth : 10,
40929
40930     
40931     cellSelector : 'td.x-grid3-cell',
40932     
40933     rowSelector : 'div.x-grid3-row',
40934     
40935     
40936     rowBodySelector : 'div.x-grid3-row-body',
40937     
40938     
40939     firstRowCls: 'x-grid3-row-first',
40940     lastRowCls: 'x-grid3-row-last',
40941     rowClsRe: /(?:^|\s+)x-grid3-row-(first|last|alt)(?:\s+|$)/g,
40942     
40943     constructor : function(config){
40944         Ext.apply(this, config);
40945             
40946             this.addEvents(
40947                 
40948                 'beforerowremoved',
40949                 
40950                 'beforerowsinserted',
40951                 
40952                 'beforerefresh',
40953                 
40954                 'rowremoved',
40955                 
40956                 'rowsinserted',
40957                 
40958                 'rowupdated',
40959                 
40960                 'refresh'
40961             );
40962             Ext.grid.GridView.superclass.constructor.call(this);    
40963     },
40964
40965     
40966
40967     
40968     initTemplates : function(){
40969         var ts = this.templates || {};
40970         if(!ts.master){
40971             ts.master = new Ext.Template(
40972                     '<div class="x-grid3" hidefocus="true">',
40973                         '<div class="x-grid3-viewport">',
40974                             '<div class="x-grid3-header"><div class="x-grid3-header-inner"><div class="x-grid3-header-offset" style="{ostyle}">{header}</div></div><div class="x-clear"></div></div>',
40975                             '<div class="x-grid3-scroller"><div class="x-grid3-body" style="{bstyle}">{body}</div><a href="#" class="x-grid3-focus" tabIndex="-1"></a></div>',
40976                         '</div>',
40977                         '<div class="x-grid3-resize-marker">&#160;</div>',
40978                         '<div class="x-grid3-resize-proxy">&#160;</div>',
40979                     '</div>'
40980                     );
40981         }
40982
40983         if(!ts.header){
40984             ts.header = new Ext.Template(
40985                     '<table border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',
40986                     '<thead><tr class="x-grid3-hd-row">{cells}</tr></thead>',
40987                     '</table>'
40988                     );
40989         }
40990
40991         if(!ts.hcell){
40992             ts.hcell = new Ext.Template(
40993                     '<td class="x-grid3-hd x-grid3-cell x-grid3-td-{id} {css}" style="{style}"><div {tooltip} {attr} class="x-grid3-hd-inner x-grid3-hd-{id}" unselectable="on" style="{istyle}">', this.grid.enableHdMenu ? '<a class="x-grid3-hd-btn" href="#"></a>' : '',
40994                     '{value}<img class="x-grid3-sort-icon" src="', Ext.BLANK_IMAGE_URL, '" />',
40995                     '</div></td>'
40996                     );
40997         }
40998
40999         if(!ts.body){
41000             ts.body = new Ext.Template('{rows}');
41001         }
41002
41003         if(!ts.row){
41004             ts.row = new Ext.Template(
41005                     '<div class="x-grid3-row {alt}" style="{tstyle}"><table class="x-grid3-row-table" border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',
41006                     '<tbody><tr>{cells}</tr>',
41007                     (this.enableRowBody ? '<tr class="x-grid3-row-body-tr" style="{bodyStyle}"><td colspan="{cols}" class="x-grid3-body-cell" tabIndex="0" hidefocus="on"><div class="x-grid3-row-body">{body}</div></td></tr>' : ''),
41008                     '</tbody></table></div>'
41009                     );
41010         }
41011
41012         if(!ts.cell){
41013             ts.cell = new Ext.Template(
41014                     '<td class="x-grid3-col x-grid3-cell x-grid3-td-{id} {css}" style="{style}" tabIndex="0" {cellAttr}>',
41015                     '<div class="x-grid3-cell-inner x-grid3-col-{id}" unselectable="on" {attr}>{value}</div>',
41016                     '</td>'
41017                     );
41018         }
41019
41020         for(var k in ts){
41021             var t = ts[k];
41022             if(t && Ext.isFunction(t.compile) && !t.compiled){
41023                 t.disableFormats = true;
41024                 t.compile();
41025             }
41026         }
41027
41028         this.templates = ts;
41029         this.colRe = new RegExp('x-grid3-td-([^\\s]+)', '');
41030     },
41031
41032     
41033     fly : function(el){
41034         if(!this._flyweight){
41035             this._flyweight = new Ext.Element.Flyweight(document.body);
41036         }
41037         this._flyweight.dom = el;
41038         return this._flyweight;
41039     },
41040
41041     
41042     getEditorParent : function(){
41043         return this.scroller.dom;
41044     },
41045
41046     
41047     initElements : function(){
41048         var E = Ext.Element;
41049
41050         var el = this.grid.getGridEl().dom.firstChild;
41051         var cs = el.childNodes;
41052
41053         this.el = new E(el);
41054
41055         this.mainWrap = new E(cs[0]);
41056         this.mainHd = new E(this.mainWrap.dom.firstChild);
41057
41058         if(this.grid.hideHeaders){
41059             this.mainHd.setDisplayed(false);
41060         }
41061
41062         this.innerHd = this.mainHd.dom.firstChild;
41063         this.scroller = new E(this.mainWrap.dom.childNodes[1]);
41064         if(this.forceFit){
41065             this.scroller.setStyle('overflow-x', 'hidden');
41066         }
41067         
41068         this.mainBody = new E(this.scroller.dom.firstChild);
41069
41070         this.focusEl = new E(this.scroller.dom.childNodes[1]);
41071         this.focusEl.swallowEvent('click', true);
41072
41073         this.resizeMarker = new E(cs[1]);
41074         this.resizeProxy = new E(cs[2]);
41075     },
41076
41077     
41078     getRows : function(){
41079         return this.hasRows() ? this.mainBody.dom.childNodes : [];
41080     },
41081
41082     
41083
41084     
41085     findCell : function(el){
41086         if(!el){
41087             return false;
41088         }
41089         return this.fly(el).findParent(this.cellSelector, this.cellSelectorDepth);
41090     },
41091
41092     
41093     findCellIndex : function(el, requiredCls){
41094         var cell = this.findCell(el);
41095         if(cell && (!requiredCls || this.fly(cell).hasClass(requiredCls))){
41096             return this.getCellIndex(cell);
41097         }
41098         return false;
41099     },
41100
41101     
41102     getCellIndex : function(el){
41103         if(el){
41104             var m = el.className.match(this.colRe);
41105             if(m && m[1]){
41106                 return this.cm.getIndexById(m[1]);
41107             }
41108         }
41109         return false;
41110     },
41111
41112     
41113     findHeaderCell : function(el){
41114         var cell = this.findCell(el);
41115         return cell && this.fly(cell).hasClass(this.hdCls) ? cell : null;
41116     },
41117
41118     
41119     findHeaderIndex : function(el){
41120         return this.findCellIndex(el, this.hdCls);
41121     },
41122
41123     
41124     findRow : function(el){
41125         if(!el){
41126             return false;
41127         }
41128         return this.fly(el).findParent(this.rowSelector, this.rowSelectorDepth);
41129     },
41130
41131     
41132     findRowIndex : function(el){
41133         var r = this.findRow(el);
41134         return r ? r.rowIndex : false;
41135     },
41136     
41137     
41138     findRowBody : function(el){
41139         if(!el){
41140             return false;
41141         }
41142         return this.fly(el).findParent(this.rowBodySelector, this.rowBodySelectorDepth);
41143     },
41144
41145     
41146
41147     
41148     getRow : function(row){
41149         return this.getRows()[row];
41150     },
41151
41152     
41153     getCell : function(row, col){
41154         return this.getRow(row).getElementsByTagName('td')[col];
41155     },
41156
41157     
41158     getHeaderCell : function(index){
41159       return this.mainHd.dom.getElementsByTagName('td')[index];
41160     },
41161
41162     
41163
41164     
41165     addRowClass : function(row, cls){
41166         var r = this.getRow(row);
41167         if(r){
41168             this.fly(r).addClass(cls);
41169         }
41170     },
41171
41172     
41173     removeRowClass : function(row, cls){
41174         var r = this.getRow(row);
41175         if(r){
41176             this.fly(r).removeClass(cls);
41177         }
41178     },
41179
41180     
41181     removeRow : function(row){
41182         Ext.removeNode(this.getRow(row));
41183         this.syncFocusEl(row);
41184     },
41185     
41186     
41187     removeRows : function(firstRow, lastRow){
41188         var bd = this.mainBody.dom;
41189         for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){
41190             Ext.removeNode(bd.childNodes[firstRow]);
41191         }
41192         this.syncFocusEl(firstRow);
41193     },
41194
41195     
41196
41197     
41198     getScrollState : function(){
41199         var sb = this.scroller.dom;
41200         return {left: sb.scrollLeft, top: sb.scrollTop};
41201     },
41202
41203     
41204     restoreScroll : function(state){
41205         var sb = this.scroller.dom;
41206         sb.scrollLeft = state.left;
41207         sb.scrollTop = state.top;
41208     },
41209
41210     
41211     scrollToTop : function(){
41212         this.scroller.dom.scrollTop = 0;
41213         this.scroller.dom.scrollLeft = 0;
41214     },
41215
41216     
41217     syncScroll : function(){
41218       this.syncHeaderScroll();
41219       var mb = this.scroller.dom;
41220         this.grid.fireEvent('bodyscroll', mb.scrollLeft, mb.scrollTop);
41221     },
41222
41223     
41224     syncHeaderScroll : function(){
41225         var mb = this.scroller.dom;
41226         this.innerHd.scrollLeft = mb.scrollLeft;
41227         this.innerHd.scrollLeft = mb.scrollLeft; 
41228     },
41229
41230     
41231     updateSortIcon : function(col, dir){
41232         var sc = this.sortClasses;
41233         var hds = this.mainHd.select('td').removeClass(sc);
41234         hds.item(col).addClass(sc[dir == 'DESC' ? 1 : 0]);
41235     },
41236
41237     
41238     updateAllColumnWidths : function(){
41239         var tw = this.getTotalWidth(),
41240             clen = this.cm.getColumnCount(),
41241             ws = [],
41242             len,
41243             i;
41244         for(i = 0; i < clen; i++){
41245             ws[i] = this.getColumnWidth(i);
41246         }
41247         this.innerHd.firstChild.style.width = this.getOffsetWidth();
41248         this.innerHd.firstChild.firstChild.style.width = tw;
41249         this.mainBody.dom.style.width = tw;
41250         for(i = 0; i < clen; i++){
41251             var hd = this.getHeaderCell(i);
41252             hd.style.width = ws[i];
41253         }
41254
41255         var ns = this.getRows(), row, trow;
41256         for(i = 0, len = ns.length; i < len; i++){
41257             row = ns[i];
41258             row.style.width = tw;
41259             if(row.firstChild){
41260                 row.firstChild.style.width = tw;
41261                 trow = row.firstChild.rows[0];
41262                 for (var j = 0; j < clen; j++) {
41263                    trow.childNodes[j].style.width = ws[j];
41264                 }
41265             }
41266         }
41267
41268         this.onAllColumnWidthsUpdated(ws, tw);
41269     },
41270
41271     
41272     updateColumnWidth : function(col, width){
41273         var w = this.getColumnWidth(col);
41274         var tw = this.getTotalWidth();
41275         this.innerHd.firstChild.style.width = this.getOffsetWidth();
41276         this.innerHd.firstChild.firstChild.style.width = tw;
41277         this.mainBody.dom.style.width = tw;
41278         var hd = this.getHeaderCell(col);
41279         hd.style.width = w;
41280
41281         var ns = this.getRows(), row;
41282         for(var i = 0, len = ns.length; i < len; i++){
41283             row = ns[i];
41284             row.style.width = tw;
41285             if(row.firstChild){
41286                 row.firstChild.style.width = tw;
41287                 row.firstChild.rows[0].childNodes[col].style.width = w;
41288             }
41289         }
41290
41291         this.onColumnWidthUpdated(col, w, tw);
41292     },
41293
41294     
41295     updateColumnHidden : function(col, hidden){
41296         var tw = this.getTotalWidth();
41297         this.innerHd.firstChild.style.width = this.getOffsetWidth();
41298         this.innerHd.firstChild.firstChild.style.width = tw;
41299         this.mainBody.dom.style.width = tw;
41300         var display = hidden ? 'none' : '';
41301
41302         var hd = this.getHeaderCell(col);
41303         hd.style.display = display;
41304
41305         var ns = this.getRows(), row;
41306         for(var i = 0, len = ns.length; i < len; i++){
41307             row = ns[i];
41308             row.style.width = tw;
41309             if(row.firstChild){
41310                 row.firstChild.style.width = tw;
41311                 row.firstChild.rows[0].childNodes[col].style.display = display;
41312             }
41313         }
41314
41315         this.onColumnHiddenUpdated(col, hidden, tw);
41316         delete this.lastViewWidth; 
41317         this.layout();
41318     },
41319
41320     
41321     doRender : function(cs, rs, ds, startRow, colCount, stripe){
41322         var ts = this.templates, ct = ts.cell, rt = ts.row, last = colCount-1;
41323         var tstyle = 'width:'+this.getTotalWidth()+';';
41324         
41325         var buf = [], cb, c, p = {}, rp = {tstyle: tstyle}, r;
41326         for(var j = 0, len = rs.length; j < len; j++){
41327             r = rs[j]; cb = [];
41328             var rowIndex = (j+startRow);
41329             for(var i = 0; i < colCount; i++){
41330                 c = cs[i];
41331                 p.id = c.id;
41332                 p.css = i === 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');
41333                 p.attr = p.cellAttr = '';
41334                 p.value = c.renderer.call(c.scope, r.data[c.name], p, r, rowIndex, i, ds);
41335                 p.style = c.style;
41336                 if(Ext.isEmpty(p.value)){
41337                     p.value = '&#160;';
41338                 }
41339                 if(this.markDirty && r.dirty && Ext.isDefined(r.modified[c.name])){
41340                     p.css += ' x-grid3-dirty-cell';
41341                 }
41342                 cb[cb.length] = ct.apply(p);
41343             }
41344             var alt = [];
41345             if(stripe && ((rowIndex+1) % 2 === 0)){
41346                 alt[0] = 'x-grid3-row-alt';
41347             }
41348             if(r.dirty){
41349                 alt[1] = ' x-grid3-dirty-row';
41350             }
41351             rp.cols = colCount;
41352             if(this.getRowClass){
41353                 alt[2] = this.getRowClass(r, rowIndex, rp, ds);
41354             }
41355             rp.alt = alt.join(' ');
41356             rp.cells = cb.join('');
41357             buf[buf.length] =  rt.apply(rp);
41358         }
41359         return buf.join('');
41360     },
41361
41362     
41363     processRows : function(startRow, skipStripe){
41364         if(!this.ds || this.ds.getCount() < 1){
41365             return;
41366         }
41367         var rows = this.getRows(),
41368             len = rows.length,
41369             i, r;
41370             
41371         skipStripe = skipStripe || !this.grid.stripeRows;
41372         startRow = startRow || 0;
41373         for(i = 0; i<len; i++) {
41374             r = rows[i];
41375             if(r) {
41376                 r.rowIndex = i;
41377                 if(!skipStripe){
41378                     r.className = r.className.replace(this.rowClsRe, ' ');
41379                     if ((i + 1) % 2 === 0){
41380                         r.className += ' x-grid3-row-alt';
41381                     }
41382                 }   
41383             }          
41384         }
41385         
41386         if(startRow === 0){
41387             Ext.fly(rows[0]).addClass(this.firstRowCls);
41388         }
41389         Ext.fly(rows[rows.length - 1]).addClass(this.lastRowCls);
41390     },
41391
41392     afterRender : function(){
41393         if(!this.ds || !this.cm){
41394             return;
41395         }
41396         this.mainBody.dom.innerHTML = this.renderRows() || '&#160;';
41397         this.processRows(0, true);
41398
41399         if(this.deferEmptyText !== true){
41400             this.applyEmptyText();
41401         }
41402         this.grid.fireEvent('viewready', this.grid);
41403     },
41404
41405     
41406     renderUI : function(){
41407
41408         var header = this.renderHeaders();
41409         var body = this.templates.body.apply({rows:'&#160;'});
41410
41411
41412         var html = this.templates.master.apply({
41413             body: body,
41414             header: header,
41415             ostyle: 'width:'+this.getOffsetWidth()+';',
41416             bstyle: 'width:'+this.getTotalWidth()+';'
41417         });
41418
41419         var g = this.grid;
41420
41421         g.getGridEl().dom.innerHTML = html;
41422
41423         this.initElements();
41424
41425         
41426         Ext.fly(this.innerHd).on('click', this.handleHdDown, this);
41427         this.mainHd.on({
41428             scope: this,
41429             mouseover: this.handleHdOver,
41430             mouseout: this.handleHdOut,
41431             mousemove: this.handleHdMove
41432         });
41433
41434         this.scroller.on('scroll', this.syncScroll,  this);
41435         if(g.enableColumnResize !== false){
41436             this.splitZone = new Ext.grid.GridView.SplitDragZone(g, this.mainHd.dom);
41437         }
41438
41439         if(g.enableColumnMove){
41440             this.columnDrag = new Ext.grid.GridView.ColumnDragZone(g, this.innerHd);
41441             this.columnDrop = new Ext.grid.HeaderDropZone(g, this.mainHd.dom);
41442         }
41443
41444         if(g.enableHdMenu !== false){
41445             this.hmenu = new Ext.menu.Menu({id: g.id + '-hctx'});
41446             this.hmenu.add(
41447                 {itemId:'asc', text: this.sortAscText, cls: 'xg-hmenu-sort-asc'},
41448                 {itemId:'desc', text: this.sortDescText, cls: 'xg-hmenu-sort-desc'}
41449             );
41450             if(g.enableColumnHide !== false){
41451                 this.colMenu = new Ext.menu.Menu({id:g.id + '-hcols-menu'});
41452                 this.colMenu.on({
41453                     scope: this,
41454                     beforeshow: this.beforeColMenuShow,
41455                     itemclick: this.handleHdMenuClick
41456                 });
41457                 this.hmenu.add('-', {
41458                     itemId:'columns',
41459                     hideOnClick: false,
41460                     text: this.columnsText,
41461                     menu: this.colMenu,
41462                     iconCls: 'x-cols-icon'
41463                 });
41464             }
41465             this.hmenu.on('itemclick', this.handleHdMenuClick, this);
41466         }
41467
41468         if(g.trackMouseOver){
41469             this.mainBody.on({
41470                 scope: this,
41471                 mouseover: this.onRowOver,
41472                 mouseout: this.onRowOut
41473             });
41474         }
41475
41476         if(g.enableDragDrop || g.enableDrag){
41477             this.dragZone = new Ext.grid.GridDragZone(g, {
41478                 ddGroup : g.ddGroup || 'GridDD'
41479             });
41480         }
41481
41482         this.updateHeaderSortState();
41483
41484     },
41485     
41486     
41487     processEvent: Ext.emptyFn,
41488
41489     
41490     layout : function(){
41491         if(!this.mainBody){
41492             return; 
41493         }
41494         var g = this.grid;
41495         var c = g.getGridEl();
41496         var csize = c.getSize(true);
41497         var vw = csize.width;
41498
41499         if(!g.hideHeaders && (vw < 20 || csize.height < 20)){ 
41500             return;
41501         }
41502         
41503         if(g.autoHeight){
41504             this.scroller.dom.style.overflow = 'visible';
41505             if(Ext.isWebKit){
41506                 this.scroller.dom.style.position = 'static';
41507             }
41508         }else{
41509             this.el.setSize(csize.width, csize.height);
41510
41511             var hdHeight = this.mainHd.getHeight();
41512             var vh = csize.height - (hdHeight);
41513
41514             this.scroller.setSize(vw, vh);
41515             if(this.innerHd){
41516                 this.innerHd.style.width = (vw)+'px';
41517             }
41518         }
41519         if(this.forceFit){
41520             if(this.lastViewWidth != vw){
41521                 this.fitColumns(false, false);
41522                 this.lastViewWidth = vw;
41523             }
41524         }else {
41525             this.autoExpand();
41526             this.syncHeaderScroll();
41527         }
41528         this.onLayout(vw, vh);
41529     },
41530
41531     
41532     
41533     onLayout : function(vw, vh){
41534         
41535     },
41536
41537     onColumnWidthUpdated : function(col, w, tw){
41538         
41539     },
41540
41541     onAllColumnWidthsUpdated : function(ws, tw){
41542         
41543     },
41544
41545     onColumnHiddenUpdated : function(col, hidden, tw){
41546         
41547     },
41548
41549     updateColumnText : function(col, text){
41550         
41551     },
41552
41553     afterMove : function(colIndex){
41554         
41555     },
41556
41557     
41558     
41559     init : function(grid){
41560         this.grid = grid;
41561
41562         this.initTemplates();
41563         this.initData(grid.store, grid.colModel);
41564         this.initUI(grid);
41565     },
41566
41567     
41568     getColumnId : function(index){
41569       return this.cm.getColumnId(index);
41570     },
41571     
41572     
41573     getOffsetWidth : function() {
41574         return (this.cm.getTotalWidth() + this.getScrollOffset()) + 'px';
41575     },
41576     
41577     getScrollOffset: function(){
41578         return Ext.num(this.scrollOffset, Ext.getScrollBarWidth());
41579     },
41580
41581     
41582     renderHeaders : function(){
41583         var cm = this.cm, 
41584             ts = this.templates,
41585             ct = ts.hcell,
41586             cb = [], 
41587             p = {},
41588             len = cm.getColumnCount(),
41589             last = len - 1;
41590             
41591         for(var i = 0; i < len; i++){
41592             p.id = cm.getColumnId(i);
41593             p.value = cm.getColumnHeader(i) || '';
41594             p.style = this.getColumnStyle(i, true);
41595             p.tooltip = this.getColumnTooltip(i);
41596             p.css = i === 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');
41597             if(cm.config[i].align == 'right'){
41598                 p.istyle = 'padding-right:16px';
41599             } else {
41600                 delete p.istyle;
41601             }
41602             cb[cb.length] = ct.apply(p);
41603         }
41604         return ts.header.apply({cells: cb.join(''), tstyle:'width:'+this.getTotalWidth()+';'});
41605     },
41606
41607     
41608     getColumnTooltip : function(i){
41609         var tt = this.cm.getColumnTooltip(i);
41610         if(tt){
41611             if(Ext.QuickTips.isEnabled()){
41612                 return 'ext:qtip="'+tt+'"';
41613             }else{
41614                 return 'title="'+tt+'"';
41615             }
41616         }
41617         return '';
41618     },
41619
41620     
41621     beforeUpdate : function(){
41622         this.grid.stopEditing(true);
41623     },
41624
41625     
41626     updateHeaders : function(){
41627         this.innerHd.firstChild.innerHTML = this.renderHeaders();
41628         this.innerHd.firstChild.style.width = this.getOffsetWidth();
41629         this.innerHd.firstChild.firstChild.style.width = this.getTotalWidth();
41630     },
41631
41632     
41633     focusRow : function(row){
41634         this.focusCell(row, 0, false);
41635     },
41636
41637     
41638     focusCell : function(row, col, hscroll){
41639         this.syncFocusEl(this.ensureVisible(row, col, hscroll));
41640         if(Ext.isGecko){
41641             this.focusEl.focus();
41642         }else{
41643             this.focusEl.focus.defer(1, this.focusEl);
41644         }
41645     },
41646
41647     resolveCell : function(row, col, hscroll){
41648         if(!Ext.isNumber(row)){
41649             row = row.rowIndex;
41650         }
41651         if(!this.ds){
41652             return null;
41653         }
41654         if(row < 0 || row >= this.ds.getCount()){
41655             return null;
41656         }
41657         col = (col !== undefined ? col : 0);
41658
41659         var rowEl = this.getRow(row),
41660             cm = this.cm,
41661             colCount = cm.getColumnCount(),
41662             cellEl;
41663         if(!(hscroll === false && col === 0)){
41664             while(col < colCount && cm.isHidden(col)){
41665                 col++;
41666             }
41667             cellEl = this.getCell(row, col);
41668         }
41669
41670         return {row: rowEl, cell: cellEl};
41671     },
41672
41673     getResolvedXY : function(resolved){
41674         if(!resolved){
41675             return null;
41676         }
41677         var s = this.scroller.dom, c = resolved.cell, r = resolved.row;
41678         return c ? Ext.fly(c).getXY() : [this.el.getX(), Ext.fly(r).getY()];
41679     },
41680
41681     syncFocusEl : function(row, col, hscroll){
41682         var xy = row;
41683         if(!Ext.isArray(xy)){
41684             row = Math.min(row, Math.max(0, this.getRows().length-1));
41685             xy = this.getResolvedXY(this.resolveCell(row, col, hscroll));
41686         }
41687         this.focusEl.setXY(xy||this.scroller.getXY());
41688     },
41689
41690     ensureVisible : function(row, col, hscroll){
41691         var resolved = this.resolveCell(row, col, hscroll);
41692         if(!resolved || !resolved.row){
41693             return;
41694         }
41695
41696         var rowEl = resolved.row, 
41697             cellEl = resolved.cell,
41698             c = this.scroller.dom,
41699             ctop = 0,
41700             p = rowEl, 
41701             stop = this.el.dom;
41702             
41703         while(p && p != stop){
41704             ctop += p.offsetTop;
41705             p = p.offsetParent;
41706         }
41707         
41708         ctop -= this.mainHd.dom.offsetHeight;
41709         stop = parseInt(c.scrollTop, 10);
41710         
41711         var cbot = ctop + rowEl.offsetHeight,
41712             ch = c.clientHeight,
41713             sbot = stop + ch;
41714         
41715
41716         if(ctop < stop){
41717           c.scrollTop = ctop;
41718         }else if(cbot > sbot){
41719             c.scrollTop = cbot-ch;
41720         }
41721
41722         if(hscroll !== false){
41723             var cleft = parseInt(cellEl.offsetLeft, 10);
41724             var cright = cleft + cellEl.offsetWidth;
41725
41726             var sleft = parseInt(c.scrollLeft, 10);
41727             var sright = sleft + c.clientWidth;
41728             if(cleft < sleft){
41729                 c.scrollLeft = cleft;
41730             }else if(cright > sright){
41731                 c.scrollLeft = cright-c.clientWidth;
41732             }
41733         }
41734         return this.getResolvedXY(resolved);
41735     },
41736
41737     
41738     insertRows : function(dm, firstRow, lastRow, isUpdate){
41739         var last = dm.getCount() - 1;
41740         if(!isUpdate && firstRow === 0 && lastRow >= last){
41741             this.fireEvent('beforerowsinserted', this, firstRow, lastRow);
41742             this.refresh();
41743             this.fireEvent('rowsinserted', this, firstRow, lastRow);
41744         }else{
41745             if(!isUpdate){
41746                 this.fireEvent('beforerowsinserted', this, firstRow, lastRow);
41747             }
41748             var html = this.renderRows(firstRow, lastRow),
41749                 before = this.getRow(firstRow);
41750             if(before){
41751                 if(firstRow === 0){
41752                     Ext.fly(this.getRow(0)).removeClass(this.firstRowCls);
41753                 }
41754                 Ext.DomHelper.insertHtml('beforeBegin', before, html);
41755             }else{
41756                 var r = this.getRow(last - 1);
41757                 if(r){
41758                     Ext.fly(r).removeClass(this.lastRowCls);
41759                 }
41760                 Ext.DomHelper.insertHtml('beforeEnd', this.mainBody.dom, html);
41761             }
41762             if(!isUpdate){
41763                 this.fireEvent('rowsinserted', this, firstRow, lastRow);
41764                 this.processRows(firstRow);
41765             }else if(firstRow === 0 || firstRow >= last){
41766                 
41767                 Ext.fly(this.getRow(firstRow)).addClass(firstRow === 0 ? this.firstRowCls : this.lastRowCls);
41768             }
41769         }
41770         this.syncFocusEl(firstRow);
41771     },
41772
41773     
41774     deleteRows : function(dm, firstRow, lastRow){
41775         if(dm.getRowCount()<1){
41776             this.refresh();
41777         }else{
41778             this.fireEvent('beforerowsdeleted', this, firstRow, lastRow);
41779
41780             this.removeRows(firstRow, lastRow);
41781
41782             this.processRows(firstRow);
41783             this.fireEvent('rowsdeleted', this, firstRow, lastRow);
41784         }
41785     },
41786
41787     
41788     getColumnStyle : function(col, isHeader){
41789         var style = !isHeader ? (this.cm.config[col].css || '') : '';
41790         style += 'width:'+this.getColumnWidth(col)+';';
41791         if(this.cm.isHidden(col)){
41792             style += 'display:none;';
41793         }
41794         var align = this.cm.config[col].align;
41795         if(align){
41796             style += 'text-align:'+align+';';
41797         }
41798         return style;
41799     },
41800
41801     
41802     getColumnWidth : function(col){
41803         var w = this.cm.getColumnWidth(col);
41804         if(Ext.isNumber(w)){
41805             return (Ext.isBorderBox || (Ext.isWebKit && !Ext.isSafari2) ? w : (w - this.borderWidth > 0 ? w - this.borderWidth : 0)) + 'px';
41806         }
41807         return w;
41808     },
41809
41810     
41811     getTotalWidth : function(){
41812         return this.cm.getTotalWidth()+'px';
41813     },
41814
41815     
41816     fitColumns : function(preventRefresh, onlyExpand, omitColumn){
41817         var cm = this.cm, i;
41818         var tw = cm.getTotalWidth(false);
41819         var aw = this.grid.getGridEl().getWidth(true)-this.getScrollOffset();
41820
41821         if(aw < 20){ 
41822             return;
41823         }
41824         var extra = aw - tw;
41825
41826         if(extra === 0){
41827             return false;
41828         }
41829
41830         var vc = cm.getColumnCount(true);
41831         var ac = vc-(Ext.isNumber(omitColumn) ? 1 : 0);
41832         if(ac === 0){
41833             ac = 1;
41834             omitColumn = undefined;
41835         }
41836         var colCount = cm.getColumnCount();
41837         var cols = [];
41838         var extraCol = 0;
41839         var width = 0;
41840         var w;
41841         for (i = 0; i < colCount; i++){
41842             if(!cm.isHidden(i) && !cm.isFixed(i) && i !== omitColumn){
41843                 w = cm.getColumnWidth(i);
41844                 cols.push(i);
41845                 extraCol = i;
41846                 cols.push(w);
41847                 width += w;
41848             }
41849         }
41850         var frac = (aw - cm.getTotalWidth())/width;
41851         while (cols.length){
41852             w = cols.pop();
41853             i = cols.pop();
41854             cm.setColumnWidth(i, Math.max(this.grid.minColumnWidth, Math.floor(w + w*frac)), true);
41855         }
41856
41857         if((tw = cm.getTotalWidth(false)) > aw){
41858             var adjustCol = ac != vc ? omitColumn : extraCol;
41859              cm.setColumnWidth(adjustCol, Math.max(1,
41860                      cm.getColumnWidth(adjustCol)- (tw-aw)), true);
41861         }
41862
41863         if(preventRefresh !== true){
41864             this.updateAllColumnWidths();
41865         }
41866
41867
41868         return true;
41869     },
41870
41871     
41872     autoExpand : function(preventUpdate){
41873         var g = this.grid, cm = this.cm;
41874         if(!this.userResized && g.autoExpandColumn){
41875             var tw = cm.getTotalWidth(false);
41876             var aw = this.grid.getGridEl().getWidth(true)-this.getScrollOffset();
41877             if(tw != aw){
41878                 var ci = cm.getIndexById(g.autoExpandColumn);
41879                 var currentWidth = cm.getColumnWidth(ci);
41880                 var cw = Math.min(Math.max(((aw-tw)+currentWidth), g.autoExpandMin), g.autoExpandMax);
41881                 if(cw != currentWidth){
41882                     cm.setColumnWidth(ci, cw, true);
41883                     if(preventUpdate !== true){
41884                         this.updateColumnWidth(ci, cw);
41885                     }
41886                 }
41887             }
41888         }
41889     },
41890
41891     
41892     getColumnData : function(){
41893         
41894         var cs = [], cm = this.cm, colCount = cm.getColumnCount();
41895         for(var i = 0; i < colCount; i++){
41896             var name = cm.getDataIndex(i);
41897             cs[i] = {
41898                 name : (!Ext.isDefined(name) ? this.ds.fields.get(i).name : name),
41899                 renderer : cm.getRenderer(i),
41900                 scope: cm.getRendererScope(i),
41901                 id : cm.getColumnId(i),
41902                 style : this.getColumnStyle(i)
41903             };
41904         }
41905         return cs;
41906     },
41907
41908     
41909     renderRows : function(startRow, endRow){
41910         
41911         var g = this.grid, cm = g.colModel, ds = g.store, stripe = g.stripeRows;
41912         var colCount = cm.getColumnCount();
41913
41914         if(ds.getCount() < 1){
41915             return '';
41916         }
41917
41918         var cs = this.getColumnData();
41919
41920         startRow = startRow || 0;
41921         endRow = !Ext.isDefined(endRow) ? ds.getCount()-1 : endRow;
41922
41923         
41924         var rs = ds.getRange(startRow, endRow);
41925
41926         return this.doRender(cs, rs, ds, startRow, colCount, stripe);
41927     },
41928
41929     
41930     renderBody : function(){
41931         var markup = this.renderRows() || '&#160;';
41932         return this.templates.body.apply({rows: markup});
41933     },
41934
41935     
41936     refreshRow : function(record){
41937         var ds = this.ds, index;
41938         if(Ext.isNumber(record)){
41939             index = record;
41940             record = ds.getAt(index);
41941             if(!record){
41942                 return;
41943             }
41944         }else{
41945             index = ds.indexOf(record);
41946             if(index < 0){
41947                 return;
41948             }
41949         }
41950         this.insertRows(ds, index, index, true);
41951         this.getRow(index).rowIndex = index;
41952         this.onRemove(ds, record, index+1, true);
41953         this.fireEvent('rowupdated', this, index, record);
41954     },
41955
41956     
41957     refresh : function(headersToo){
41958         this.fireEvent('beforerefresh', this);
41959         this.grid.stopEditing(true);
41960
41961         var result = this.renderBody();
41962         this.mainBody.update(result).setWidth(this.getTotalWidth());
41963         if(headersToo === true){
41964             this.updateHeaders();
41965             this.updateHeaderSortState();
41966         }
41967         this.processRows(0, true);
41968         this.layout();
41969         this.applyEmptyText();
41970         this.fireEvent('refresh', this);
41971     },
41972
41973     
41974     applyEmptyText : function(){
41975         if(this.emptyText && !this.hasRows()){
41976             this.mainBody.update('<div class="x-grid-empty">' + this.emptyText + '</div>');
41977         }
41978     },
41979
41980     
41981     updateHeaderSortState : function(){
41982         var state = this.ds.getSortState();
41983         if(!state){
41984             return;
41985         }
41986         if(!this.sortState || (this.sortState.field != state.field || this.sortState.direction != state.direction)){
41987             this.grid.fireEvent('sortchange', this.grid, state);
41988         }
41989         this.sortState = state;
41990         var sortColumn = this.cm.findColumnIndex(state.field);
41991         if(sortColumn != -1){
41992             var sortDir = state.direction;
41993             this.updateSortIcon(sortColumn, sortDir);
41994         }
41995     },
41996
41997     
41998     clearHeaderSortState : function(){
41999         if(!this.sortState){
42000             return;
42001         }
42002         this.grid.fireEvent('sortchange', this.grid, null);
42003         this.mainHd.select('td').removeClass(this.sortClasses);
42004         delete this.sortState;
42005     },
42006
42007     
42008     destroy : function(){
42009         if(this.colMenu){
42010             Ext.menu.MenuMgr.unregister(this.colMenu);
42011             this.colMenu.destroy();
42012             delete this.colMenu;
42013         }
42014         if(this.hmenu){
42015             Ext.menu.MenuMgr.unregister(this.hmenu);
42016             this.hmenu.destroy();
42017             delete this.hmenu;
42018         }
42019
42020         this.initData(null, null);
42021         this.purgeListeners();
42022         Ext.fly(this.innerHd).un("click", this.handleHdDown, this);
42023
42024         if(this.grid.enableColumnMove){
42025             Ext.destroy(
42026                 this.columnDrag.el,
42027                 this.columnDrag.proxy.ghost,
42028                 this.columnDrag.proxy.el,
42029                 this.columnDrop.el,
42030                 this.columnDrop.proxyTop,
42031                 this.columnDrop.proxyBottom,
42032                 this.columnDrag.dragData.ddel,
42033                 this.columnDrag.dragData.header
42034             );
42035             if (this.columnDrag.proxy.anim) {
42036                 Ext.destroy(this.columnDrag.proxy.anim);
42037             }
42038             delete this.columnDrag.proxy.ghost;
42039             delete this.columnDrag.dragData.ddel;
42040             delete this.columnDrag.dragData.header;
42041             this.columnDrag.destroy();
42042             delete Ext.dd.DDM.locationCache[this.columnDrag.id];
42043             delete this.columnDrag._domRef;
42044
42045             delete this.columnDrop.proxyTop;
42046             delete this.columnDrop.proxyBottom;
42047             this.columnDrop.destroy();
42048             delete Ext.dd.DDM.locationCache["gridHeader" + this.grid.getGridEl().id];
42049             delete this.columnDrop._domRef;
42050             delete Ext.dd.DDM.ids[this.columnDrop.ddGroup];
42051         }
42052
42053         if (this.splitZone){ 
42054             this.splitZone.destroy();
42055             delete this.splitZone._domRef;
42056             delete Ext.dd.DDM.ids["gridSplitters" + this.grid.getGridEl().id];
42057         }
42058
42059         Ext.fly(this.innerHd).removeAllListeners();
42060         Ext.removeNode(this.innerHd);
42061         delete this.innerHd;
42062
42063         Ext.destroy(
42064             this.el,
42065             this.mainWrap,
42066             this.mainHd,
42067             this.scroller,
42068             this.mainBody,
42069             this.focusEl,
42070             this.resizeMarker,
42071             this.resizeProxy,
42072             this.activeHdBtn,
42073             this.dragZone,
42074             this.splitZone,
42075             this._flyweight
42076         );
42077
42078         delete this.grid.container;
42079
42080         if(this.dragZone){
42081             this.dragZone.destroy();
42082         }
42083
42084         Ext.dd.DDM.currentTarget = null;
42085         delete Ext.dd.DDM.locationCache[this.grid.getGridEl().id];
42086
42087         Ext.EventManager.removeResizeListener(this.onWindowResize, this);
42088     },
42089
42090     
42091     onDenyColumnHide : function(){
42092
42093     },
42094
42095     
42096     render : function(){
42097         if(this.autoFill){
42098             var ct = this.grid.ownerCt;
42099             if (ct && ct.getLayout()){
42100                 ct.on('afterlayout', function(){ 
42101                     this.fitColumns(true, true);
42102                     this.updateHeaders(); 
42103                 }, this, {single: true}); 
42104             }else{ 
42105                 this.fitColumns(true, true); 
42106             }
42107         }else if(this.forceFit){
42108             this.fitColumns(true, false);
42109         }else if(this.grid.autoExpandColumn){
42110             this.autoExpand(true);
42111         }
42112
42113         this.renderUI();
42114     },
42115
42116     
42117     
42118     initData : function(ds, cm){
42119         if(this.ds){
42120             this.ds.un('load', this.onLoad, this);
42121             this.ds.un('datachanged', this.onDataChange, this);
42122             this.ds.un('add', this.onAdd, this);
42123             this.ds.un('remove', this.onRemove, this);
42124             this.ds.un('update', this.onUpdate, this);
42125             this.ds.un('clear', this.onClear, this);
42126             if(this.ds !== ds && this.ds.autoDestroy){
42127                 this.ds.destroy();
42128             }
42129         }
42130         if(ds){
42131             ds.on({
42132                 scope: this,
42133                 load: this.onLoad,
42134                 datachanged: this.onDataChange,
42135                 add: this.onAdd,
42136                 remove: this.onRemove,
42137                 update: this.onUpdate,
42138                 clear: this.onClear
42139             });
42140         }
42141         this.ds = ds;
42142
42143         if(this.cm){
42144             this.cm.un('configchange', this.onColConfigChange, this);
42145             this.cm.un('widthchange', this.onColWidthChange, this);
42146             this.cm.un('headerchange', this.onHeaderChange, this);
42147             this.cm.un('hiddenchange', this.onHiddenChange, this);
42148             this.cm.un('columnmoved', this.onColumnMove, this);
42149         }
42150         if(cm){
42151             delete this.lastViewWidth;
42152             cm.on({
42153                 scope: this,
42154                 configchange: this.onColConfigChange,
42155                 widthchange: this.onColWidthChange,
42156                 headerchange: this.onHeaderChange,
42157                 hiddenchange: this.onHiddenChange,
42158                 columnmoved: this.onColumnMove
42159             });
42160         }
42161         this.cm = cm;
42162     },
42163
42164     
42165     onDataChange : function(){
42166         this.refresh();
42167         this.updateHeaderSortState();
42168         this.syncFocusEl(0);
42169     },
42170
42171     
42172     onClear : function(){
42173         this.refresh();
42174         this.syncFocusEl(0);
42175     },
42176
42177     
42178     onUpdate : function(ds, record){
42179         this.refreshRow(record);
42180     },
42181
42182     
42183     onAdd : function(ds, records, index){
42184         
42185         this.insertRows(ds, index, index + (records.length-1));
42186     },
42187
42188     
42189     onRemove : function(ds, record, index, isUpdate){
42190         if(isUpdate !== true){
42191             this.fireEvent('beforerowremoved', this, index, record);
42192         }
42193         this.removeRow(index);
42194         if(isUpdate !== true){
42195             this.processRows(index);
42196             this.applyEmptyText();
42197             this.fireEvent('rowremoved', this, index, record);
42198         }
42199     },
42200
42201     
42202     onLoad : function(){
42203         this.scrollToTop.defer(Ext.isGecko ? 1 : 0, this);
42204     },
42205
42206     
42207     onColWidthChange : function(cm, col, width){
42208         this.updateColumnWidth(col, width);
42209     },
42210
42211     
42212     onHeaderChange : function(cm, col, text){
42213         this.updateHeaders();
42214     },
42215
42216     
42217     onHiddenChange : function(cm, col, hidden){
42218         this.updateColumnHidden(col, hidden);
42219     },
42220
42221     
42222     onColumnMove : function(cm, oldIndex, newIndex){
42223         this.indexMap = null;
42224         var s = this.getScrollState();
42225         this.refresh(true);
42226         this.restoreScroll(s);
42227         this.afterMove(newIndex);
42228         this.grid.fireEvent('columnmove', oldIndex, newIndex);
42229     },
42230
42231     
42232     onColConfigChange : function(){
42233         delete this.lastViewWidth;
42234         this.indexMap = null;
42235         this.refresh(true);
42236     },
42237
42238     
42239     
42240     initUI : function(grid){
42241         grid.on('headerclick', this.onHeaderClick, this);
42242     },
42243
42244     
42245     initEvents : function(){
42246     },
42247
42248     
42249     onHeaderClick : function(g, index){
42250         if(this.headersDisabled || !this.cm.isSortable(index)){
42251             return;
42252         }
42253         g.stopEditing(true);
42254         g.store.sort(this.cm.getDataIndex(index));
42255     },
42256
42257     
42258     onRowOver : function(e, t){
42259         var row;
42260         if((row = this.findRowIndex(t)) !== false){
42261             this.addRowClass(row, 'x-grid3-row-over');
42262         }
42263     },
42264
42265     
42266     onRowOut : function(e, t){
42267         var row;
42268         if((row = this.findRowIndex(t)) !== false && !e.within(this.getRow(row), true)){
42269             this.removeRowClass(row, 'x-grid3-row-over');
42270         }
42271     },
42272
42273     
42274     handleWheel : function(e){
42275         e.stopPropagation();
42276     },
42277
42278     
42279     onRowSelect : function(row){
42280         this.addRowClass(row, this.selectedRowClass);
42281     },
42282
42283     
42284     onRowDeselect : function(row){
42285         this.removeRowClass(row, this.selectedRowClass);
42286     },
42287
42288     
42289     onCellSelect : function(row, col){
42290         var cell = this.getCell(row, col);
42291         if(cell){
42292             this.fly(cell).addClass('x-grid3-cell-selected');
42293         }
42294     },
42295
42296     
42297     onCellDeselect : function(row, col){
42298         var cell = this.getCell(row, col);
42299         if(cell){
42300             this.fly(cell).removeClass('x-grid3-cell-selected');
42301         }
42302     },
42303
42304     
42305     onColumnSplitterMoved : function(i, w){
42306         this.userResized = true;
42307         var cm = this.grid.colModel;
42308         cm.setColumnWidth(i, w, true);
42309
42310         if(this.forceFit){
42311             this.fitColumns(true, false, i);
42312             this.updateAllColumnWidths();
42313         }else{
42314             this.updateColumnWidth(i, w);
42315             this.syncHeaderScroll();
42316         }
42317
42318         this.grid.fireEvent('columnresize', i, w);
42319     },
42320
42321     
42322     handleHdMenuClick : function(item){
42323         var index = this.hdCtxIndex,
42324             cm = this.cm, 
42325             ds = this.ds,
42326             id = item.getItemId();
42327         switch(id){
42328             case 'asc':
42329                 ds.sort(cm.getDataIndex(index), 'ASC');
42330                 break;
42331             case 'desc':
42332                 ds.sort(cm.getDataIndex(index), 'DESC');
42333                 break;
42334             default:
42335                 index = cm.getIndexById(id.substr(4));
42336                 if(index != -1){
42337                     if(item.checked && cm.getColumnsBy(this.isHideableColumn, this).length <= 1){
42338                         this.onDenyColumnHide();
42339                         return false;
42340                     }
42341                     cm.setHidden(index, item.checked);
42342                 }
42343         }
42344         return true;
42345     },
42346
42347     
42348     isHideableColumn : function(c){
42349         return !c.hidden && !c.fixed;
42350     },
42351
42352     
42353     beforeColMenuShow : function(){
42354         var cm = this.cm,  colCount = cm.getColumnCount();
42355         this.colMenu.removeAll();
42356         for(var i = 0; i < colCount; i++){
42357             if(cm.config[i].fixed !== true && cm.config[i].hideable !== false){
42358                 this.colMenu.add(new Ext.menu.CheckItem({
42359                     itemId: 'col-'+cm.getColumnId(i),
42360                     text: cm.getColumnHeader(i),
42361                     checked: !cm.isHidden(i),
42362                     hideOnClick:false,
42363                     disabled: cm.config[i].hideable === false
42364                 }));
42365             }
42366         }
42367     },
42368
42369     
42370     handleHdDown : function(e, t){
42371         if(Ext.fly(t).hasClass('x-grid3-hd-btn')){
42372             e.stopEvent();
42373             var hd = this.findHeaderCell(t);
42374             Ext.fly(hd).addClass('x-grid3-hd-menu-open');
42375             var index = this.getCellIndex(hd);
42376             this.hdCtxIndex = index;
42377             var ms = this.hmenu.items, cm = this.cm;
42378             ms.get('asc').setDisabled(!cm.isSortable(index));
42379             ms.get('desc').setDisabled(!cm.isSortable(index));
42380             this.hmenu.on('hide', function(){
42381                 Ext.fly(hd).removeClass('x-grid3-hd-menu-open');
42382             }, this, {single:true});
42383             this.hmenu.show(t, 'tl-bl?');
42384         }
42385     },
42386
42387     
42388     handleHdOver : function(e, t){
42389         var hd = this.findHeaderCell(t);
42390         if(hd && !this.headersDisabled){
42391             this.activeHdRef = t;
42392             this.activeHdIndex = this.getCellIndex(hd);
42393             var fly = this.fly(hd);
42394             this.activeHdRegion = fly.getRegion();
42395             if(!this.cm.isMenuDisabled(this.activeHdIndex)){
42396                 fly.addClass('x-grid3-hd-over');
42397                 this.activeHdBtn = fly.child('.x-grid3-hd-btn');
42398                 if(this.activeHdBtn){
42399                     this.activeHdBtn.dom.style.height = (hd.firstChild.offsetHeight-1)+'px';
42400                 }
42401             }
42402         }
42403     },
42404
42405     
42406     handleHdMove : function(e, t){
42407         var hd = this.findHeaderCell(this.activeHdRef);
42408         if(hd && !this.headersDisabled){
42409             var hw = this.splitHandleWidth || 5,
42410                 r = this.activeHdRegion,
42411                 x = e.getPageX(),
42412                 ss = hd.style,
42413                 cur = '';
42414             if(this.grid.enableColumnResize !== false){
42415                 if(x - r.left <= hw && this.cm.isResizable(this.activeHdIndex-1)){
42416                     cur = Ext.isAir ? 'move' : Ext.isWebKit ? 'e-resize' : 'col-resize'; 
42417                 }else if(r.right - x <= (!this.activeHdBtn ? hw : 2) && this.cm.isResizable(this.activeHdIndex)){
42418                     cur = Ext.isAir ? 'move' : Ext.isWebKit ? 'w-resize' : 'col-resize';
42419                 }
42420             }
42421             ss.cursor = cur;
42422         }
42423     },
42424
42425     
42426     handleHdOut : function(e, t){
42427         var hd = this.findHeaderCell(t);
42428         if(hd && (!Ext.isIE || !e.within(hd, true))){
42429             this.activeHdRef = null;
42430             this.fly(hd).removeClass('x-grid3-hd-over');
42431             hd.style.cursor = '';
42432         }
42433     },
42434
42435     
42436     hasRows : function(){
42437         var fc = this.mainBody.dom.firstChild;
42438         return fc && fc.nodeType == 1 && fc.className != 'x-grid-empty';
42439     },
42440
42441     
42442     bind : function(d, c){
42443         this.initData(d, c);
42444     }
42445 });
42446
42447
42448
42449
42450 Ext.grid.GridView.SplitDragZone = function(grid, hd){
42451     this.grid = grid;
42452     this.view = grid.getView();
42453     this.marker = this.view.resizeMarker;
42454     this.proxy = this.view.resizeProxy;
42455     Ext.grid.GridView.SplitDragZone.superclass.constructor.call(this, hd,
42456         'gridSplitters' + this.grid.getGridEl().id, {
42457         dragElId : Ext.id(this.proxy.dom), resizeFrame:false
42458     });
42459     this.scroll = false;
42460     this.hw = this.view.splitHandleWidth || 5;
42461 };
42462 Ext.extend(Ext.grid.GridView.SplitDragZone, Ext.dd.DDProxy, {
42463
42464     b4StartDrag : function(x, y){
42465         this.view.headersDisabled = true;
42466         var h = this.view.mainWrap.getHeight();
42467         this.marker.setHeight(h);
42468         this.marker.show();
42469         this.marker.alignTo(this.view.getHeaderCell(this.cellIndex), 'tl-tl', [-2, 0]);
42470         this.proxy.setHeight(h);
42471         var w = this.cm.getColumnWidth(this.cellIndex);
42472         var minw = Math.max(w-this.grid.minColumnWidth, 0);
42473         this.resetConstraints();
42474         this.setXConstraint(minw, 1000);
42475         this.setYConstraint(0, 0);
42476         this.minX = x - minw;
42477         this.maxX = x + 1000;
42478         this.startPos = x;
42479         Ext.dd.DDProxy.prototype.b4StartDrag.call(this, x, y);
42480     },
42481     
42482     allowHeaderDrag : function(e){
42483         return true;
42484     },
42485
42486
42487     handleMouseDown : function(e){
42488         var t = this.view.findHeaderCell(e.getTarget());
42489         if(t && this.allowHeaderDrag(e)){
42490             var xy = this.view.fly(t).getXY(), x = xy[0], y = xy[1];
42491             var exy = e.getXY(), ex = exy[0];
42492             var w = t.offsetWidth, adjust = false;
42493             if((ex - x) <= this.hw){
42494                 adjust = -1;
42495             }else if((x+w) - ex <= this.hw){
42496                 adjust = 0;
42497             }
42498             if(adjust !== false){
42499                 this.cm = this.grid.colModel;
42500                 var ci = this.view.getCellIndex(t);
42501                 if(adjust == -1){
42502                   if (ci + adjust < 0) {
42503                     return;
42504                   }
42505                     while(this.cm.isHidden(ci+adjust)){
42506                         --adjust;
42507                         if(ci+adjust < 0){
42508                             return;
42509                         }
42510                     }
42511                 }
42512                 this.cellIndex = ci+adjust;
42513                 this.split = t.dom;
42514                 if(this.cm.isResizable(this.cellIndex) && !this.cm.isFixed(this.cellIndex)){
42515                     Ext.grid.GridView.SplitDragZone.superclass.handleMouseDown.apply(this, arguments);
42516                 }
42517             }else if(this.view.columnDrag){
42518                 this.view.columnDrag.callHandleMouseDown(e);
42519             }
42520         }
42521     },
42522
42523     endDrag : function(e){
42524         this.marker.hide();
42525         var v = this.view;
42526         var endX = Math.max(this.minX, e.getPageX());
42527         var diff = endX - this.startPos;
42528         v.onColumnSplitterMoved(this.cellIndex, this.cm.getColumnWidth(this.cellIndex)+diff);
42529         setTimeout(function(){
42530             v.headersDisabled = false;
42531         }, 50);
42532     },
42533
42534     autoOffset : function(){
42535         this.setDelta(0,0);
42536     }
42537 });
42538
42539
42540 Ext.grid.HeaderDragZone = Ext.extend(Ext.dd.DragZone, {
42541     maxDragWidth: 120,
42542     
42543     constructor : function(grid, hd, hd2){
42544         this.grid = grid;
42545         this.view = grid.getView();
42546         this.ddGroup = "gridHeader" + this.grid.getGridEl().id;
42547         Ext.grid.HeaderDragZone.superclass.constructor.call(this, hd);
42548         if(hd2){
42549             this.setHandleElId(Ext.id(hd));
42550             this.setOuterHandleElId(Ext.id(hd2));
42551         }
42552         this.scroll = false;
42553     },
42554     
42555     getDragData : function(e){
42556         var t = Ext.lib.Event.getTarget(e);
42557         var h = this.view.findHeaderCell(t);
42558         if(h){
42559             return {ddel: h.firstChild, header:h};
42560         }
42561         return false;
42562     },
42563
42564     onInitDrag : function(e){
42565         this.view.headersDisabled = true;
42566         var clone = this.dragData.ddel.cloneNode(true);
42567         clone.id = Ext.id();
42568         clone.style.width = Math.min(this.dragData.header.offsetWidth,this.maxDragWidth) + "px";
42569         this.proxy.update(clone);
42570         return true;
42571     },
42572
42573     afterValidDrop : function(){
42574         var v = this.view;
42575         setTimeout(function(){
42576             v.headersDisabled = false;
42577         }, 50);
42578     },
42579
42580     afterInvalidDrop : function(){
42581         var v = this.view;
42582         setTimeout(function(){
42583             v.headersDisabled = false;
42584         }, 50);
42585     }
42586 });
42587
42588
42589
42590 Ext.grid.HeaderDropZone = Ext.extend(Ext.dd.DropZone, {
42591     proxyOffsets : [-4, -9],
42592     fly: Ext.Element.fly,
42593     
42594     constructor : function(grid, hd, hd2){
42595         this.grid = grid;
42596         this.view = grid.getView();
42597         
42598         this.proxyTop = Ext.DomHelper.append(document.body, {
42599             cls:"col-move-top", html:"&#160;"
42600         }, true);
42601         this.proxyBottom = Ext.DomHelper.append(document.body, {
42602             cls:"col-move-bottom", html:"&#160;"
42603         }, true);
42604         this.proxyTop.hide = this.proxyBottom.hide = function(){
42605             this.setLeftTop(-100,-100);
42606             this.setStyle("visibility", "hidden");
42607         };
42608         this.ddGroup = "gridHeader" + this.grid.getGridEl().id;
42609         
42610         
42611         Ext.grid.HeaderDropZone.superclass.constructor.call(this, grid.getGridEl().dom);
42612     },
42613
42614     getTargetFromEvent : function(e){
42615         var t = Ext.lib.Event.getTarget(e);
42616         var cindex = this.view.findCellIndex(t);
42617         if(cindex !== false){
42618             return this.view.getHeaderCell(cindex);
42619         }
42620     },
42621
42622     nextVisible : function(h){
42623         var v = this.view, cm = this.grid.colModel;
42624         h = h.nextSibling;
42625         while(h){
42626             if(!cm.isHidden(v.getCellIndex(h))){
42627                 return h;
42628             }
42629             h = h.nextSibling;
42630         }
42631         return null;
42632     },
42633
42634     prevVisible : function(h){
42635         var v = this.view, cm = this.grid.colModel;
42636         h = h.prevSibling;
42637         while(h){
42638             if(!cm.isHidden(v.getCellIndex(h))){
42639                 return h;
42640             }
42641             h = h.prevSibling;
42642         }
42643         return null;
42644     },
42645
42646     positionIndicator : function(h, n, e){
42647         var x = Ext.lib.Event.getPageX(e);
42648         var r = Ext.lib.Dom.getRegion(n.firstChild);
42649         var px, pt, py = r.top + this.proxyOffsets[1];
42650         if((r.right - x) <= (r.right-r.left)/2){
42651             px = r.right+this.view.borderWidth;
42652             pt = "after";
42653         }else{
42654             px = r.left;
42655             pt = "before";
42656         }
42657
42658         if(this.grid.colModel.isFixed(this.view.getCellIndex(n))){
42659             return false;
42660         }
42661
42662         px +=  this.proxyOffsets[0];
42663         this.proxyTop.setLeftTop(px, py);
42664         this.proxyTop.show();
42665         if(!this.bottomOffset){
42666             this.bottomOffset = this.view.mainHd.getHeight();
42667         }
42668         this.proxyBottom.setLeftTop(px, py+this.proxyTop.dom.offsetHeight+this.bottomOffset);
42669         this.proxyBottom.show();
42670         return pt;
42671     },
42672
42673     onNodeEnter : function(n, dd, e, data){
42674         if(data.header != n){
42675             this.positionIndicator(data.header, n, e);
42676         }
42677     },
42678
42679     onNodeOver : function(n, dd, e, data){
42680         var result = false;
42681         if(data.header != n){
42682             result = this.positionIndicator(data.header, n, e);
42683         }
42684         if(!result){
42685             this.proxyTop.hide();
42686             this.proxyBottom.hide();
42687         }
42688         return result ? this.dropAllowed : this.dropNotAllowed;
42689     },
42690
42691     onNodeOut : function(n, dd, e, data){
42692         this.proxyTop.hide();
42693         this.proxyBottom.hide();
42694     },
42695
42696     onNodeDrop : function(n, dd, e, data){
42697         var h = data.header;
42698         if(h != n){
42699             var cm = this.grid.colModel;
42700             var x = Ext.lib.Event.getPageX(e);
42701             var r = Ext.lib.Dom.getRegion(n.firstChild);
42702             var pt = (r.right - x) <= ((r.right-r.left)/2) ? "after" : "before";
42703             var oldIndex = this.view.getCellIndex(h);
42704             var newIndex = this.view.getCellIndex(n);
42705             if(pt == "after"){
42706                 newIndex++;
42707             }
42708             if(oldIndex < newIndex){
42709                 newIndex--;
42710             }
42711             cm.moveColumn(oldIndex, newIndex);
42712             return true;
42713         }
42714         return false;
42715     }
42716 });
42717
42718 Ext.grid.GridView.ColumnDragZone = Ext.extend(Ext.grid.HeaderDragZone, {
42719     
42720     constructor : function(grid, hd){
42721         Ext.grid.GridView.ColumnDragZone.superclass.constructor.call(this, grid, hd, null);
42722         this.proxy.el.addClass('x-grid3-col-dd');
42723     },
42724     
42725     handleMouseDown : function(e){
42726     },
42727
42728     callHandleMouseDown : function(e){
42729         Ext.grid.GridView.ColumnDragZone.superclass.handleMouseDown.call(this, e);
42730     }
42731 });
42732
42733 Ext.grid.SplitDragZone = Ext.extend(Ext.dd.DDProxy, {
42734     fly: Ext.Element.fly,
42735     
42736     constructor : function(grid, hd, hd2){
42737         this.grid = grid;
42738         this.view = grid.getView();
42739         this.proxy = this.view.resizeProxy;
42740         Ext.grid.SplitDragZone.superclass.constructor.call(this, hd,
42741             "gridSplitters" + this.grid.getGridEl().id, {
42742             dragElId : Ext.id(this.proxy.dom), resizeFrame:false
42743         });
42744         this.setHandleElId(Ext.id(hd));
42745         this.setOuterHandleElId(Ext.id(hd2));
42746         this.scroll = false;
42747     },
42748
42749     b4StartDrag : function(x, y){
42750         this.view.headersDisabled = true;
42751         this.proxy.setHeight(this.view.mainWrap.getHeight());
42752         var w = this.cm.getColumnWidth(this.cellIndex);
42753         var minw = Math.max(w-this.grid.minColumnWidth, 0);
42754         this.resetConstraints();
42755         this.setXConstraint(minw, 1000);
42756         this.setYConstraint(0, 0);
42757         this.minX = x - minw;
42758         this.maxX = x + 1000;
42759         this.startPos = x;
42760         Ext.dd.DDProxy.prototype.b4StartDrag.call(this, x, y);
42761     },
42762
42763
42764     handleMouseDown : function(e){
42765         var ev = Ext.EventObject.setEvent(e);
42766         var t = this.fly(ev.getTarget());
42767         if(t.hasClass("x-grid-split")){
42768             this.cellIndex = this.view.getCellIndex(t.dom);
42769             this.split = t.dom;
42770             this.cm = this.grid.colModel;
42771             if(this.cm.isResizable(this.cellIndex) && !this.cm.isFixed(this.cellIndex)){
42772                 Ext.grid.SplitDragZone.superclass.handleMouseDown.apply(this, arguments);
42773             }
42774         }
42775     },
42776
42777     endDrag : function(e){
42778         this.view.headersDisabled = false;
42779         var endX = Math.max(this.minX, Ext.lib.Event.getPageX(e));
42780         var diff = endX - this.startPos;
42781         this.view.onColumnSplitterMoved(this.cellIndex, this.cm.getColumnWidth(this.cellIndex)+diff);
42782     },
42783
42784     autoOffset : function(){
42785         this.setDelta(0,0);
42786     }
42787 });
42788 Ext.grid.GridDragZone = function(grid, config){
42789     this.view = grid.getView();
42790     Ext.grid.GridDragZone.superclass.constructor.call(this, this.view.mainBody.dom, config);
42791     this.scroll = false;
42792     this.grid = grid;
42793     this.ddel = document.createElement('div');
42794     this.ddel.className = 'x-grid-dd-wrap';
42795 };
42796
42797 Ext.extend(Ext.grid.GridDragZone, Ext.dd.DragZone, {
42798     ddGroup : "GridDD",
42799
42800     
42801     getDragData : function(e){
42802         var t = Ext.lib.Event.getTarget(e);
42803         var rowIndex = this.view.findRowIndex(t);
42804         if(rowIndex !== false){
42805             var sm = this.grid.selModel;
42806             if(!sm.isSelected(rowIndex) || e.hasModifier()){
42807                 sm.handleMouseDown(this.grid, rowIndex, e);
42808             }
42809             return {grid: this.grid, ddel: this.ddel, rowIndex: rowIndex, selections:sm.getSelections()};
42810         }
42811         return false;
42812     },
42813
42814     
42815     onInitDrag : function(e){
42816         var data = this.dragData;
42817         this.ddel.innerHTML = this.grid.getDragDropText();
42818         this.proxy.update(this.ddel);
42819         
42820     },
42821
42822     
42823     afterRepair : function(){
42824         this.dragging = false;
42825     },
42826
42827     
42828     getRepairXY : function(e, data){
42829         return false;
42830     },
42831
42832     onEndDrag : function(data, e){
42833         
42834     },
42835
42836     onValidDrop : function(dd, e, id){
42837         
42838         this.hideProxy();
42839     },
42840
42841     beforeInvalidDrop : function(e, id){
42842
42843     }
42844 });
42845
42846 Ext.grid.ColumnModel = Ext.extend(Ext.util.Observable, {
42847     
42848     defaultWidth: 100,
42849     
42850     defaultSortable: false,
42851     
42852     
42853     
42854     constructor : function(config){
42855         
42856             if(config.columns){
42857                 Ext.apply(this, config);
42858                 this.setConfig(config.columns, true);
42859             }else{
42860                 this.setConfig(config, true);
42861             }
42862             this.addEvents(
42863                 
42864                 "widthchange",
42865                 
42866                 "headerchange",
42867                 
42868                 "hiddenchange",
42869                 
42870                 "columnmoved",
42871                 
42872                 "configchange"
42873             );
42874             Ext.grid.ColumnModel.superclass.constructor.call(this);
42875     },
42876
42877     
42878     getColumnId : function(index){
42879         return this.config[index].id;
42880     },
42881
42882     getColumnAt : function(index){
42883         return this.config[index];
42884     },
42885
42886     
42887     setConfig : function(config, initial){
42888         var i, c, len;
42889         if(!initial){ 
42890             delete this.totalWidth;
42891             for(i = 0, len = this.config.length; i < len; i++){
42892                 c = this.config[i];
42893                 if(c.editor){
42894                     c.editor.destroy();
42895                 }
42896             }
42897         }
42898
42899         
42900         this.defaults = Ext.apply({
42901             width: this.defaultWidth,
42902             sortable: this.defaultSortable
42903         }, this.defaults);
42904
42905         this.config = config;
42906         this.lookup = {};
42907
42908         for(i = 0, len = config.length; i < len; i++){
42909             c = Ext.applyIf(config[i], this.defaults);
42910             
42911             if(typeof c.id == 'undefined'){
42912                 c.id = i;
42913             }
42914             if(!c.isColumn){
42915                 var Cls = Ext.grid.Column.types[c.xtype || 'gridcolumn'];
42916                 c = new Cls(c);
42917                 config[i] = c;
42918             }
42919             this.lookup[c.id] = c;
42920         }
42921         if(!initial){
42922             this.fireEvent('configchange', this);
42923         }
42924     },
42925
42926     
42927     getColumnById : function(id){
42928         return this.lookup[id];
42929     },
42930
42931     
42932     getIndexById : function(id){
42933         for(var i = 0, len = this.config.length; i < len; i++){
42934             if(this.config[i].id == id){
42935                 return i;
42936             }
42937         }
42938         return -1;
42939     },
42940
42941     
42942     moveColumn : function(oldIndex, newIndex){
42943         var c = this.config[oldIndex];
42944         this.config.splice(oldIndex, 1);
42945         this.config.splice(newIndex, 0, c);
42946         this.dataMap = null;
42947         this.fireEvent("columnmoved", this, oldIndex, newIndex);
42948     },
42949
42950     
42951     getColumnCount : function(visibleOnly){
42952         if(visibleOnly === true){
42953             var c = 0;
42954             for(var i = 0, len = this.config.length; i < len; i++){
42955                 if(!this.isHidden(i)){
42956                     c++;
42957                 }
42958             }
42959             return c;
42960         }
42961         return this.config.length;
42962     },
42963
42964     
42965     getColumnsBy : function(fn, scope){
42966         var r = [];
42967         for(var i = 0, len = this.config.length; i < len; i++){
42968             var c = this.config[i];
42969             if(fn.call(scope||this, c, i) === true){
42970                 r[r.length] = c;
42971             }
42972         }
42973         return r;
42974     },
42975
42976     
42977     isSortable : function(col){
42978         return !!this.config[col].sortable;
42979     },
42980
42981     
42982     isMenuDisabled : function(col){
42983         return !!this.config[col].menuDisabled;
42984     },
42985
42986     
42987     getRenderer : function(col){
42988         if(!this.config[col].renderer){
42989             return Ext.grid.ColumnModel.defaultRenderer;
42990         }
42991         return this.config[col].renderer;
42992     },
42993     
42994     getRendererScope : function(col){
42995         return this.config[col].scope;
42996     },
42997
42998     
42999     setRenderer : function(col, fn){
43000         this.config[col].renderer = fn;
43001     },
43002
43003     
43004     getColumnWidth : function(col){
43005         return this.config[col].width;
43006     },
43007
43008     
43009     setColumnWidth : function(col, width, suppressEvent){
43010         this.config[col].width = width;
43011         this.totalWidth = null;
43012         if(!suppressEvent){
43013              this.fireEvent("widthchange", this, col, width);
43014         }
43015     },
43016
43017     
43018     getTotalWidth : function(includeHidden){
43019         if(!this.totalWidth){
43020             this.totalWidth = 0;
43021             for(var i = 0, len = this.config.length; i < len; i++){
43022                 if(includeHidden || !this.isHidden(i)){
43023                     this.totalWidth += this.getColumnWidth(i);
43024                 }
43025             }
43026         }
43027         return this.totalWidth;
43028     },
43029
43030     
43031     getColumnHeader : function(col){
43032         return this.config[col].header;
43033     },
43034
43035     
43036     setColumnHeader : function(col, header){
43037         this.config[col].header = header;
43038         this.fireEvent("headerchange", this, col, header);
43039     },
43040
43041     
43042     getColumnTooltip : function(col){
43043             return this.config[col].tooltip;
43044     },
43045     
43046     setColumnTooltip : function(col, tooltip){
43047             this.config[col].tooltip = tooltip;
43048     },
43049
43050     
43051     getDataIndex : function(col){
43052         return this.config[col].dataIndex;
43053     },
43054
43055     
43056     setDataIndex : function(col, dataIndex){
43057         this.config[col].dataIndex = dataIndex;
43058     },
43059
43060     
43061     findColumnIndex : function(dataIndex){
43062         var c = this.config;
43063         for(var i = 0, len = c.length; i < len; i++){
43064             if(c[i].dataIndex == dataIndex){
43065                 return i;
43066             }
43067         }
43068         return -1;
43069     },
43070
43071     
43072     isCellEditable : function(colIndex, rowIndex){
43073         return (this.config[colIndex].editable || (typeof this.config[colIndex].editable == "undefined" && this.config[colIndex].editor)) ? true : false;
43074     },
43075
43076     
43077     getCellEditor : function(colIndex, rowIndex){
43078         return this.config[colIndex].getCellEditor(rowIndex);
43079     },
43080
43081     
43082     setEditable : function(col, editable){
43083         this.config[col].editable = editable;
43084     },
43085
43086     
43087     isHidden : function(colIndex){
43088         return !!this.config[colIndex].hidden; 
43089     },
43090
43091     
43092     isFixed : function(colIndex){
43093         return !!this.config[colIndex].fixed;
43094     },
43095
43096     
43097     isResizable : function(colIndex){
43098         return colIndex >= 0 && this.config[colIndex].resizable !== false && this.config[colIndex].fixed !== true;
43099     },
43100     
43101     setHidden : function(colIndex, hidden){
43102         var c = this.config[colIndex];
43103         if(c.hidden !== hidden){
43104             c.hidden = hidden;
43105             this.totalWidth = null;
43106             this.fireEvent("hiddenchange", this, colIndex, hidden);
43107         }
43108     },
43109
43110     
43111     setEditor : function(col, editor){
43112         Ext.destroy(this.config[col].editor);
43113         this.config[col].editor = editor;
43114     },
43115
43116     
43117     destroy : function(){
43118         for(var i = 0, c = this.config, len = c.length; i < len; i++){
43119             Ext.destroy(c[i].editor);
43120         }
43121         this.purgeListeners();
43122     }
43123 });
43124
43125
43126 Ext.grid.ColumnModel.defaultRenderer = function(value){
43127     if(typeof value == "string" && value.length < 1){
43128         return "&#160;";
43129     }
43130     return value;
43131 };
43132 Ext.grid.AbstractSelectionModel = Ext.extend(Ext.util.Observable,  {
43133     
43134     
43135     constructor : function(){
43136         this.locked = false;
43137         Ext.grid.AbstractSelectionModel.superclass.constructor.call(this);
43138     },
43139
43140     
43141     init : function(grid){
43142         this.grid = grid;
43143         this.initEvents();
43144     },
43145
43146     
43147     lock : function(){
43148         this.locked = true;
43149     },
43150
43151     
43152     unlock : function(){
43153         this.locked = false;
43154     },
43155
43156     
43157     isLocked : function(){
43158         return this.locked;
43159     },
43160     
43161     destroy: function(){
43162         this.purgeListeners();
43163     }
43164 });
43165 Ext.grid.RowSelectionModel = Ext.extend(Ext.grid.AbstractSelectionModel,  {
43166     
43167     singleSelect : false,
43168     
43169     constructor : function(config){
43170         Ext.apply(this, config);
43171         this.selections = new Ext.util.MixedCollection(false, function(o){
43172             return o.id;
43173         });
43174
43175         this.last = false;
43176         this.lastActive = false;
43177
43178         this.addEvents(
43179                 
43180                 'selectionchange',
43181                 
43182                 'beforerowselect',
43183                 
43184                 'rowselect',
43185                 
43186                 'rowdeselect'
43187         );
43188         Ext.grid.RowSelectionModel.superclass.constructor.call(this);
43189     },
43190
43191     
43192     
43193     initEvents : function(){
43194
43195         if(!this.grid.enableDragDrop && !this.grid.enableDrag){
43196             this.grid.on('rowmousedown', this.handleMouseDown, this);
43197         }
43198
43199         this.rowNav = new Ext.KeyNav(this.grid.getGridEl(), {
43200             'up' : function(e){
43201                 if(!e.shiftKey || this.singleSelect){
43202                     this.selectPrevious(false);
43203                 }else if(this.last !== false && this.lastActive !== false){
43204                     var last = this.last;
43205                     this.selectRange(this.last,  this.lastActive-1);
43206                     this.grid.getView().focusRow(this.lastActive);
43207                     if(last !== false){
43208                         this.last = last;
43209                     }
43210                 }else{
43211                     this.selectFirstRow();
43212                 }
43213             },
43214             'down' : function(e){
43215                 if(!e.shiftKey || this.singleSelect){
43216                     this.selectNext(false);
43217                 }else if(this.last !== false && this.lastActive !== false){
43218                     var last = this.last;
43219                     this.selectRange(this.last,  this.lastActive+1);
43220                     this.grid.getView().focusRow(this.lastActive);
43221                     if(last !== false){
43222                         this.last = last;
43223                     }
43224                 }else{
43225                     this.selectFirstRow();
43226                 }
43227             },
43228             scope: this
43229         });
43230
43231         this.grid.getView().on({
43232             scope: this,
43233             refresh: this.onRefresh,
43234             rowupdated: this.onRowUpdated,
43235             rowremoved: this.onRemove
43236         });
43237     },
43238
43239     
43240     onRefresh : function(){
43241         var ds = this.grid.store, index;
43242         var s = this.getSelections();
43243         this.clearSelections(true);
43244         for(var i = 0, len = s.length; i < len; i++){
43245             var r = s[i];
43246             if((index = ds.indexOfId(r.id)) != -1){
43247                 this.selectRow(index, true);
43248             }
43249         }
43250         if(s.length != this.selections.getCount()){
43251             this.fireEvent('selectionchange', this);
43252         }
43253     },
43254
43255     
43256     onRemove : function(v, index, r){
43257         if(this.selections.remove(r) !== false){
43258             this.fireEvent('selectionchange', this);
43259         }
43260     },
43261
43262     
43263     onRowUpdated : function(v, index, r){
43264         if(this.isSelected(r)){
43265             v.onRowSelect(index);
43266         }
43267     },
43268
43269     
43270     selectRecords : function(records, keepExisting){
43271         if(!keepExisting){
43272             this.clearSelections();
43273         }
43274         var ds = this.grid.store;
43275         for(var i = 0, len = records.length; i < len; i++){
43276             this.selectRow(ds.indexOf(records[i]), true);
43277         }
43278     },
43279
43280     
43281     getCount : function(){
43282         return this.selections.length;
43283     },
43284
43285     
43286     selectFirstRow : function(){
43287         this.selectRow(0);
43288     },
43289
43290     
43291     selectLastRow : function(keepExisting){
43292         this.selectRow(this.grid.store.getCount() - 1, keepExisting);
43293     },
43294
43295     
43296     selectNext : function(keepExisting){
43297         if(this.hasNext()){
43298             this.selectRow(this.last+1, keepExisting);
43299             this.grid.getView().focusRow(this.last);
43300             return true;
43301         }
43302         return false;
43303     },
43304
43305     
43306     selectPrevious : function(keepExisting){
43307         if(this.hasPrevious()){
43308             this.selectRow(this.last-1, keepExisting);
43309             this.grid.getView().focusRow(this.last);
43310             return true;
43311         }
43312         return false;
43313     },
43314
43315     
43316     hasNext : function(){
43317         return this.last !== false && (this.last+1) < this.grid.store.getCount();
43318     },
43319
43320     
43321     hasPrevious : function(){
43322         return !!this.last;
43323     },
43324
43325
43326     
43327     getSelections : function(){
43328         return [].concat(this.selections.items);
43329     },
43330
43331     
43332     getSelected : function(){
43333         return this.selections.itemAt(0);
43334     },
43335
43336     
43337     each : function(fn, scope){
43338         var s = this.getSelections();
43339         for(var i = 0, len = s.length; i < len; i++){
43340             if(fn.call(scope || this, s[i], i) === false){
43341                 return false;
43342             }
43343         }
43344         return true;
43345     },
43346
43347     
43348     clearSelections : function(fast){
43349         if(this.isLocked()){
43350             return;
43351         }
43352         if(fast !== true){
43353             var ds = this.grid.store;
43354             var s = this.selections;
43355             s.each(function(r){
43356                 this.deselectRow(ds.indexOfId(r.id));
43357             }, this);
43358             s.clear();
43359         }else{
43360             this.selections.clear();
43361         }
43362         this.last = false;
43363     },
43364
43365
43366     
43367     selectAll : function(){
43368         if(this.isLocked()){
43369             return;
43370         }
43371         this.selections.clear();
43372         for(var i = 0, len = this.grid.store.getCount(); i < len; i++){
43373             this.selectRow(i, true);
43374         }
43375     },
43376
43377     
43378     hasSelection : function(){
43379         return this.selections.length > 0;
43380     },
43381
43382     
43383     isSelected : function(index){
43384         var r = Ext.isNumber(index) ? this.grid.store.getAt(index) : index;
43385         return (r && this.selections.key(r.id) ? true : false);
43386     },
43387
43388     
43389     isIdSelected : function(id){
43390         return (this.selections.key(id) ? true : false);
43391     },
43392
43393     
43394     handleMouseDown : function(g, rowIndex, e){
43395         if(e.button !== 0 || this.isLocked()){
43396             return;
43397         }
43398         var view = this.grid.getView();
43399         if(e.shiftKey && !this.singleSelect && this.last !== false){
43400             var last = this.last;
43401             this.selectRange(last, rowIndex, e.ctrlKey);
43402             this.last = last; 
43403             view.focusRow(rowIndex);
43404         }else{
43405             var isSelected = this.isSelected(rowIndex);
43406             if(e.ctrlKey && isSelected){
43407                 this.deselectRow(rowIndex);
43408             }else if(!isSelected || this.getCount() > 1){
43409                 this.selectRow(rowIndex, e.ctrlKey || e.shiftKey);
43410                 view.focusRow(rowIndex);
43411             }
43412         }
43413     },
43414
43415     
43416     selectRows : function(rows, keepExisting){
43417         if(!keepExisting){
43418             this.clearSelections();
43419         }
43420         for(var i = 0, len = rows.length; i < len; i++){
43421             this.selectRow(rows[i], true);
43422         }
43423     },
43424
43425     
43426     selectRange : function(startRow, endRow, keepExisting){
43427         var i;
43428         if(this.isLocked()){
43429             return;
43430         }
43431         if(!keepExisting){
43432             this.clearSelections();
43433         }
43434         if(startRow <= endRow){
43435             for(i = startRow; i <= endRow; i++){
43436                 this.selectRow(i, true);
43437             }
43438         }else{
43439             for(i = startRow; i >= endRow; i--){
43440                 this.selectRow(i, true);
43441             }
43442         }
43443     },
43444
43445     
43446     deselectRange : function(startRow, endRow, preventViewNotify){
43447         if(this.isLocked()){
43448             return;
43449         }
43450         for(var i = startRow; i <= endRow; i++){
43451             this.deselectRow(i, preventViewNotify);
43452         }
43453     },
43454
43455     
43456     selectRow : function(index, keepExisting, preventViewNotify){
43457         if(this.isLocked() || (index < 0 || index >= this.grid.store.getCount()) || (keepExisting && this.isSelected(index))){
43458             return;
43459         }
43460         var r = this.grid.store.getAt(index);
43461         if(r && this.fireEvent('beforerowselect', this, index, keepExisting, r) !== false){
43462             if(!keepExisting || this.singleSelect){
43463                 this.clearSelections();
43464             }
43465             this.selections.add(r);
43466             this.last = this.lastActive = index;
43467             if(!preventViewNotify){
43468                 this.grid.getView().onRowSelect(index);
43469             }
43470             this.fireEvent('rowselect', this, index, r);
43471             this.fireEvent('selectionchange', this);
43472         }
43473     },
43474
43475     
43476     deselectRow : function(index, preventViewNotify){
43477         if(this.isLocked()){
43478             return;
43479         }
43480         if(this.last == index){
43481             this.last = false;
43482         }
43483         if(this.lastActive == index){
43484             this.lastActive = false;
43485         }
43486         var r = this.grid.store.getAt(index);
43487         if(r){
43488             this.selections.remove(r);
43489             if(!preventViewNotify){
43490                 this.grid.getView().onRowDeselect(index);
43491             }
43492             this.fireEvent('rowdeselect', this, index, r);
43493             this.fireEvent('selectionchange', this);
43494         }
43495     },
43496
43497     
43498     restoreLast : function(){
43499         if(this._last){
43500             this.last = this._last;
43501         }
43502     },
43503
43504     
43505     acceptsNav : function(row, col, cm){
43506         return !cm.isHidden(col) && cm.isCellEditable(col, row);
43507     },
43508
43509     
43510     onEditorKey : function(field, e){
43511         var k = e.getKey(), 
43512             newCell, 
43513             g = this.grid, 
43514             last = g.lastEdit,
43515             ed = g.activeEditor,
43516             ae, last, r, c;
43517         var shift = e.shiftKey;
43518         if(k == e.TAB){
43519             e.stopEvent();
43520             ed.completeEdit();
43521             if(shift){
43522                 newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
43523             }else{
43524                 newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
43525             }
43526         }else if(k == e.ENTER){
43527             if(this.moveEditorOnEnter !== false){
43528                 if(shift){
43529                     newCell = g.walkCells(last.row - 1, last.col, -1, this.acceptsNav, this);
43530                 }else{
43531                     newCell = g.walkCells(last.row + 1, last.col, 1, this.acceptsNav, this);
43532                 }
43533             }
43534         }
43535         if(newCell){
43536             r = newCell[0];
43537             c = newCell[1];
43538
43539             if(last.row != r){
43540                 this.selectRow(r); 
43541             }
43542
43543             if(g.isEditor && g.editing){ 
43544                 ae = g.activeEditor;
43545                 if(ae && ae.field.triggerBlur){
43546                     
43547                     ae.field.triggerBlur();
43548                 }
43549             }
43550             g.startEditing(r, c);
43551         }
43552     },
43553     
43554     destroy : function(){
43555         if(this.rowNav){
43556             this.rowNav.disable();
43557             this.rowNav = null;
43558         }
43559         Ext.grid.RowSelectionModel.superclass.destroy.call(this);
43560     }
43561 });
43562 Ext.grid.Column = Ext.extend(Object, {
43563     
43564     
43565     
43566     
43567     
43568     
43569     
43570     
43571     
43572     
43573     
43574     
43575     
43576     
43577     
43578     
43579     
43580     
43581     
43582     
43583     
43584     
43585
43586     
43587     isColumn : true,
43588     
43589     constructor : function(config){
43590         Ext.apply(this, config);
43591
43592         if(Ext.isString(this.renderer)){
43593             this.renderer = Ext.util.Format[this.renderer];
43594         }else if(Ext.isObject(this.renderer)){
43595             this.scope = this.renderer.scope;
43596             this.renderer = this.renderer.fn;
43597         }
43598         if(!this.scope){
43599             this.scope = this;
43600         }
43601
43602         if(this.editor){
43603             this.editor = Ext.create(this.editor, 'textfield');
43604         }
43605     },
43606
43607     
43608     renderer : function(value){
43609         if(Ext.isString(value) && value.length < 1){
43610             return '&#160;';
43611         }
43612         return value;
43613     },
43614
43615     
43616     getEditor: function(rowIndex){
43617         return this.editable !== false ? this.editor : null;
43618     },
43619
43620     
43621     getCellEditor: function(rowIndex){
43622         var editor = this.getEditor(rowIndex);
43623         if(editor){
43624             if(!editor.startEdit){
43625                 if(!editor.gridEditor){
43626                     editor.gridEditor = new Ext.grid.GridEditor(editor);
43627                 }
43628                 return editor.gridEditor;
43629             }else if(editor.startEdit){
43630                 return editor;
43631             }
43632         }
43633         return null;
43634     }
43635 });
43636
43637
43638 Ext.grid.BooleanColumn = Ext.extend(Ext.grid.Column, {
43639     
43640     trueText: 'true',
43641     
43642     falseText: 'false',
43643     
43644     undefinedText: '&#160;',
43645
43646     constructor: function(cfg){
43647         Ext.grid.BooleanColumn.superclass.constructor.call(this, cfg);
43648         var t = this.trueText, f = this.falseText, u = this.undefinedText;
43649         this.renderer = function(v){
43650             if(v === undefined){
43651                 return u;
43652             }
43653             if(!v || v === 'false'){
43654                 return f;
43655             }
43656             return t;
43657         };
43658     }
43659 });
43660
43661
43662 Ext.grid.NumberColumn = Ext.extend(Ext.grid.Column, {
43663     
43664     format : '0,000.00',
43665     constructor: function(cfg){
43666         Ext.grid.NumberColumn.superclass.constructor.call(this, cfg);
43667         this.renderer = Ext.util.Format.numberRenderer(this.format);
43668     }
43669 });
43670
43671
43672 Ext.grid.DateColumn = Ext.extend(Ext.grid.Column, {
43673     
43674     format : 'm/d/Y',
43675     constructor: function(cfg){
43676         Ext.grid.DateColumn.superclass.constructor.call(this, cfg);
43677         this.renderer = Ext.util.Format.dateRenderer(this.format);
43678     }
43679 });
43680
43681
43682 Ext.grid.TemplateColumn = Ext.extend(Ext.grid.Column, {
43683     
43684     constructor: function(cfg){
43685         Ext.grid.TemplateColumn.superclass.constructor.call(this, cfg);
43686         var tpl = (!Ext.isPrimitive(this.tpl) && this.tpl.compile) ? this.tpl : new Ext.XTemplate(this.tpl);
43687         this.renderer = function(value, p, r){
43688             return tpl.apply(r.data);
43689         };
43690         this.tpl = tpl;
43691     }
43692 });
43693
43694
43695 Ext.grid.Column.types = {
43696     gridcolumn : Ext.grid.Column,
43697     booleancolumn: Ext.grid.BooleanColumn,
43698     numbercolumn: Ext.grid.NumberColumn,
43699     datecolumn: Ext.grid.DateColumn,
43700     templatecolumn: Ext.grid.TemplateColumn
43701 };
43702 Ext.grid.RowNumberer = Ext.extend(Object, {
43703     
43704     header: "",
43705     
43706     width: 23,
43707     
43708     sortable: false,
43709     
43710     constructor : function(config){
43711         Ext.apply(this, config);
43712         if(this.rowspan){
43713             this.renderer = this.renderer.createDelegate(this);
43714         }
43715     },
43716
43717     
43718     fixed:true,
43719     menuDisabled:true,
43720     dataIndex: '',
43721     id: 'numberer',
43722     rowspan: undefined,
43723
43724     
43725     renderer : function(v, p, record, rowIndex){
43726         if(this.rowspan){
43727             p.cellAttr = 'rowspan="'+this.rowspan+'"';
43728         }
43729         return rowIndex+1;
43730     }
43731 });
43732 Ext.grid.CheckboxSelectionModel = Ext.extend(Ext.grid.RowSelectionModel, {
43733
43734     
43735     
43736     header : '<div class="x-grid3-hd-checker">&#160;</div>',
43737     
43738     width : 20,
43739     
43740     sortable : false,
43741
43742     
43743     menuDisabled : true,
43744     fixed : true,
43745     dataIndex : '',
43746     id : 'checker',
43747
43748     constructor : function(){
43749         Ext.grid.CheckboxSelectionModel.superclass.constructor.apply(this, arguments);
43750
43751         if(this.checkOnly){
43752             this.handleMouseDown = Ext.emptyFn;
43753         }
43754     },
43755
43756     
43757     initEvents : function(){
43758         Ext.grid.CheckboxSelectionModel.superclass.initEvents.call(this);
43759         this.grid.on('render', function(){
43760             var view = this.grid.getView();
43761             view.mainBody.on('mousedown', this.onMouseDown, this);
43762             Ext.fly(view.innerHd).on('mousedown', this.onHdMouseDown, this);
43763
43764         }, this);
43765     },
43766
43767     
43768     onMouseDown : function(e, t){
43769         if(e.button === 0 && t.className == 'x-grid3-row-checker'){ 
43770             e.stopEvent();
43771             var row = e.getTarget('.x-grid3-row');
43772             if(row){
43773                 var index = row.rowIndex;
43774                 if(this.isSelected(index)){
43775                     this.deselectRow(index);
43776                 }else{
43777                     this.selectRow(index, true);
43778                 }
43779             }
43780         }
43781     },
43782
43783     
43784     onHdMouseDown : function(e, t){
43785         if(t.className == 'x-grid3-hd-checker'){
43786             e.stopEvent();
43787             var hd = Ext.fly(t.parentNode);
43788             var isChecked = hd.hasClass('x-grid3-hd-checker-on');
43789             if(isChecked){
43790                 hd.removeClass('x-grid3-hd-checker-on');
43791                 this.clearSelections();
43792             }else{
43793                 hd.addClass('x-grid3-hd-checker-on');
43794                 this.selectAll();
43795             }
43796         }
43797     },
43798
43799     
43800     renderer : function(v, p, record){
43801         return '<div class="x-grid3-row-checker">&#160;</div>';
43802     }
43803 });
43804 Ext.grid.CellSelectionModel = Ext.extend(Ext.grid.AbstractSelectionModel,  {
43805     
43806     constructor : function(config){
43807         Ext.apply(this, config);
43808
43809             this.selection = null;
43810         
43811             this.addEvents(
43812                 
43813                 "beforecellselect",
43814                 
43815                 "cellselect",
43816                 
43817                 "selectionchange"
43818             );
43819         
43820             Ext.grid.CellSelectionModel.superclass.constructor.call(this);
43821     },
43822
43823     
43824     initEvents : function(){
43825         this.grid.on('cellmousedown', this.handleMouseDown, this);
43826         this.grid.on(Ext.EventManager.useKeydown ? 'keydown' : 'keypress', this.handleKeyDown, this);
43827         this.grid.getView().on({
43828             scope: this,
43829             refresh: this.onViewChange,
43830             rowupdated: this.onRowUpdated,
43831             beforerowremoved: this.clearSelections,
43832             beforerowsinserted: this.clearSelections
43833         });
43834         if(this.grid.isEditor){
43835             this.grid.on('beforeedit', this.beforeEdit,  this);
43836         }
43837     },
43838
43839         
43840     beforeEdit : function(e){
43841         this.select(e.row, e.column, false, true, e.record);
43842     },
43843
43844         
43845     onRowUpdated : function(v, index, r){
43846         if(this.selection && this.selection.record == r){
43847             v.onCellSelect(index, this.selection.cell[1]);
43848         }
43849     },
43850
43851         
43852     onViewChange : function(){
43853         this.clearSelections(true);
43854     },
43855
43856         
43857     getSelectedCell : function(){
43858         return this.selection ? this.selection.cell : null;
43859     },
43860
43861     
43862     clearSelections : function(preventNotify){
43863         var s = this.selection;
43864         if(s){
43865             if(preventNotify !== true){
43866                 this.grid.view.onCellDeselect(s.cell[0], s.cell[1]);
43867             }
43868             this.selection = null;
43869             this.fireEvent("selectionchange", this, null);
43870         }
43871     },
43872
43873     
43874     hasSelection : function(){
43875         return this.selection ? true : false;
43876     },
43877
43878     
43879     handleMouseDown : function(g, row, cell, e){
43880         if(e.button !== 0 || this.isLocked()){
43881             return;
43882         }
43883         this.select(row, cell);
43884     },
43885
43886     
43887     select : function(rowIndex, colIndex, preventViewNotify, preventFocus,  r){
43888         if(this.fireEvent("beforecellselect", this, rowIndex, colIndex) !== false){
43889             this.clearSelections();
43890             r = r || this.grid.store.getAt(rowIndex);
43891             this.selection = {
43892                 record : r,
43893                 cell : [rowIndex, colIndex]
43894             };
43895             if(!preventViewNotify){
43896                 var v = this.grid.getView();
43897                 v.onCellSelect(rowIndex, colIndex);
43898                 if(preventFocus !== true){
43899                     v.focusCell(rowIndex, colIndex);
43900                 }
43901             }
43902             this.fireEvent("cellselect", this, rowIndex, colIndex);
43903             this.fireEvent("selectionchange", this, this.selection);
43904         }
43905     },
43906
43907         
43908     isSelectable : function(rowIndex, colIndex, cm){
43909         return !cm.isHidden(colIndex);
43910     },
43911     
43912     
43913     onEditorKey: function(field, e){
43914         if(e.getKey() == e.TAB){
43915             this.handleKeyDown(e);
43916         }
43917     },
43918
43919     
43920     handleKeyDown : function(e){
43921         if(!e.isNavKeyPress()){
43922             return;
43923         }
43924         
43925         var k = e.getKey(),
43926             g = this.grid,
43927             s = this.selection,
43928             sm = this,
43929             walk = function(row, col, step){
43930                 return g.walkCells(
43931                     row,
43932                     col,
43933                     step,
43934                     g.isEditor && g.editing ? sm.acceptsNav : sm.isSelectable, 
43935                     sm
43936                 );
43937             },
43938             cell, newCell, r, c, ae;
43939
43940         switch(k){
43941             case e.ESC:
43942             case e.PAGE_UP:
43943             case e.PAGE_DOWN:
43944                 
43945                 break;
43946             default:
43947                 
43948                 e.stopEvent();
43949                 break;
43950         }
43951
43952         if(!s){
43953             cell = walk(0, 0, 1); 
43954             if(cell){
43955                 this.select(cell[0], cell[1]);
43956             }
43957             return;
43958         }
43959
43960         cell = s.cell;  
43961         r = cell[0];    
43962         c = cell[1];    
43963         
43964         switch(k){
43965             case e.TAB:
43966                 if(e.shiftKey){
43967                     newCell = walk(r, c - 1, -1);
43968                 }else{
43969                     newCell = walk(r, c + 1, 1);
43970                 }
43971                 break;
43972             case e.DOWN:
43973                 newCell = walk(r + 1, c, 1);
43974                 break;
43975             case e.UP:
43976                 newCell = walk(r - 1, c, -1);
43977                 break;
43978             case e.RIGHT:
43979                 newCell = walk(r, c + 1, 1);
43980                 break;
43981             case e.LEFT:
43982                 newCell = walk(r, c - 1, -1);
43983                 break;
43984             case e.ENTER:
43985                 if (g.isEditor && !g.editing) {
43986                     g.startEditing(r, c);
43987                     return;
43988                 }
43989                 break;
43990         }
43991
43992         if(newCell){
43993             
43994             r = newCell[0];
43995             c = newCell[1];
43996
43997             this.select(r, c); 
43998
43999             if(g.isEditor && g.editing){ 
44000                 ae = g.activeEditor;
44001                 if(ae && ae.field.triggerBlur){
44002                     
44003                     ae.field.triggerBlur();
44004                 }
44005                 g.startEditing(r, c);
44006             }
44007         }
44008     },
44009
44010     acceptsNav : function(row, col, cm){
44011         return !cm.isHidden(col) && cm.isCellEditable(col, row);
44012     }
44013 });
44014 Ext.grid.EditorGridPanel = Ext.extend(Ext.grid.GridPanel, {
44015     
44016     clicksToEdit: 2,
44017     
44018     
44019     forceValidation: false,
44020
44021     
44022     isEditor : true,
44023     
44024     detectEdit: false,
44025
44026         
44027         autoEncode : false,
44028
44029         
44030     
44031     trackMouseOver: false, 
44032
44033     
44034     initComponent : function(){
44035         Ext.grid.EditorGridPanel.superclass.initComponent.call(this);
44036
44037         if(!this.selModel){
44038             
44039             this.selModel = new Ext.grid.CellSelectionModel();
44040         }
44041
44042         this.activeEditor = null;
44043
44044             this.addEvents(
44045             
44046             "beforeedit",
44047             
44048             "afteredit",
44049             
44050             "validateedit"
44051         );
44052     },
44053
44054     
44055     initEvents : function(){
44056         Ext.grid.EditorGridPanel.superclass.initEvents.call(this);
44057
44058         this.getGridEl().on('mousewheel', this.stopEditing.createDelegate(this, [true]), this);
44059         this.on('columnresize', this.stopEditing, this, [true]);
44060
44061         if(this.clicksToEdit == 1){
44062             this.on("cellclick", this.onCellDblClick, this);
44063         }else {
44064             var view = this.getView();
44065             if(this.clicksToEdit == 'auto' && view.mainBody){
44066                 view.mainBody.on('mousedown', this.onAutoEditClick, this);
44067             }
44068             this.on('celldblclick', this.onCellDblClick, this);
44069         }
44070     },
44071     
44072     onResize : function(){
44073         Ext.grid.EditorGridPanel.superclass.onResize.apply(this, arguments);
44074         var ae = this.activeEditor;
44075         if(this.editing && ae){
44076             ae.realign(true);
44077         }
44078     },
44079
44080     
44081     onCellDblClick : function(g, row, col){
44082         this.startEditing(row, col);
44083     },
44084
44085     
44086     onAutoEditClick : function(e, t){
44087         if(e.button !== 0){
44088             return;
44089         }
44090         var row = this.view.findRowIndex(t),
44091             col = this.view.findCellIndex(t);
44092         if(row !== false && col !== false){
44093             this.stopEditing();
44094             if(this.selModel.getSelectedCell){ 
44095                 var sc = this.selModel.getSelectedCell();
44096                 if(sc && sc[0] === row && sc[1] === col){
44097                     this.startEditing(row, col);
44098                 }
44099             }else{
44100                 if(this.selModel.isSelected(row)){
44101                     this.startEditing(row, col);
44102                 }
44103             }
44104         }
44105     },
44106
44107     
44108     onEditComplete : function(ed, value, startValue){
44109         this.editing = false;
44110         this.activeEditor = null;
44111         
44112                 var r = ed.record,
44113             field = this.colModel.getDataIndex(ed.col);
44114         value = this.postEditValue(value, startValue, r, field);
44115         if(this.forceValidation === true || String(value) !== String(startValue)){
44116             var e = {
44117                 grid: this,
44118                 record: r,
44119                 field: field,
44120                 originalValue: startValue,
44121                 value: value,
44122                 row: ed.row,
44123                 column: ed.col,
44124                 cancel:false
44125             };
44126             if(this.fireEvent("validateedit", e) !== false && !e.cancel && String(value) !== String(startValue)){
44127                 r.set(field, e.value);
44128                 delete e.cancel;
44129                 this.fireEvent("afteredit", e);
44130             }
44131         }
44132         this.view.focusCell(ed.row, ed.col);
44133     },
44134
44135     
44136     startEditing : function(row, col){
44137         this.stopEditing();
44138         if(this.colModel.isCellEditable(col, row)){
44139             this.view.ensureVisible(row, col, true);
44140             var r = this.store.getAt(row),
44141                 field = this.colModel.getDataIndex(col),
44142                 e = {
44143                     grid: this,
44144                     record: r,
44145                     field: field,
44146                     value: r.data[field],
44147                     row: row,
44148                     column: col,
44149                     cancel:false
44150                 };
44151             if(this.fireEvent("beforeedit", e) !== false && !e.cancel){
44152                 this.editing = true;
44153                 var ed = this.colModel.getCellEditor(col, row);
44154                 if(!ed){
44155                     return;
44156                 }
44157                 if(!ed.rendered){
44158                     ed.parentEl = this.view.getEditorParent(ed);
44159                     ed.on({
44160                         scope: this,
44161                         render: {
44162                             fn: function(c){
44163                                 c.field.focus(false, true);
44164                             },
44165                             single: true,
44166                             scope: this
44167                         },
44168                         specialkey: function(field, e){
44169                             this.getSelectionModel().onEditorKey(field, e);
44170                         },
44171                         complete: this.onEditComplete,
44172                         canceledit: this.stopEditing.createDelegate(this, [true])
44173                     });
44174                 }
44175                 Ext.apply(ed, {
44176                     row     : row,
44177                     col     : col,
44178                     record  : r
44179                 });
44180                 this.lastEdit = {
44181                     row: row,
44182                     col: col
44183                 };
44184                 this.activeEditor = ed;
44185                 var v = this.preEditValue(r, field);
44186                 ed.startEdit(this.view.getCell(row, col).firstChild, Ext.isDefined(v) ? v : '');
44187             }
44188         }
44189     },
44190
44191     
44192     preEditValue : function(r, field){
44193         var value = r.data[field];
44194         return this.autoEncode && Ext.isString(value) ? Ext.util.Format.htmlDecode(value) : value;
44195     },
44196
44197     
44198         postEditValue : function(value, originalValue, r, field){
44199                 return this.autoEncode && Ext.isString(value) ? Ext.util.Format.htmlEncode(value) : value;
44200         },
44201
44202     
44203     stopEditing : function(cancel){
44204         if(this.editing){
44205             var ae = this.activeEditor;
44206             if(ae){
44207                 ae[cancel === true ? 'cancelEdit' : 'completeEdit']();
44208                 this.view.focusCell(ae.row, ae.col);
44209             }
44210             this.activeEditor = null;
44211         }
44212         this.editing = false;
44213     }
44214 });
44215 Ext.reg('editorgrid', Ext.grid.EditorGridPanel);
44216
44217 Ext.grid.GridEditor = function(field, config){
44218     Ext.grid.GridEditor.superclass.constructor.call(this, field, config);
44219     field.monitorTab = false;
44220 };
44221
44222 Ext.extend(Ext.grid.GridEditor, Ext.Editor, {
44223     alignment: "tl-tl",
44224     autoSize: "width",
44225     hideEl : false,
44226     cls: "x-small-editor x-grid-editor",
44227     shim:false,
44228     shadow:false
44229 });
44230 Ext.grid.PropertyRecord = Ext.data.Record.create([
44231     {name:'name',type:'string'}, 'value'
44232 ]);
44233
44234
44235 Ext.grid.PropertyStore = Ext.extend(Ext.util.Observable, {
44236     
44237     constructor : function(grid, source){
44238         this.grid = grid;
44239         this.store = new Ext.data.Store({
44240             recordType : Ext.grid.PropertyRecord
44241         });
44242         this.store.on('update', this.onUpdate,  this);
44243         if(source){
44244             this.setSource(source);
44245         }
44246         Ext.grid.PropertyStore.superclass.constructor.call(this);    
44247     },
44248     
44249     
44250     setSource : function(o){
44251         this.source = o;
44252         this.store.removeAll();
44253         var data = [];
44254         for(var k in o){
44255             if(this.isEditableValue(o[k])){
44256                 data.push(new Ext.grid.PropertyRecord({name: k, value: o[k]}, k));
44257             }
44258         }
44259         this.store.loadRecords({records: data}, {}, true);
44260     },
44261
44262     
44263     onUpdate : function(ds, record, type){
44264         if(type == Ext.data.Record.EDIT){
44265             var v = record.data.value;
44266             var oldValue = record.modified.value;
44267             if(this.grid.fireEvent('beforepropertychange', this.source, record.id, v, oldValue) !== false){
44268                 this.source[record.id] = v;
44269                 record.commit();
44270                 this.grid.fireEvent('propertychange', this.source, record.id, v, oldValue);
44271             }else{
44272                 record.reject();
44273             }
44274         }
44275     },
44276
44277     
44278     getProperty : function(row){
44279        return this.store.getAt(row);
44280     },
44281
44282     
44283     isEditableValue: function(val){
44284         return Ext.isPrimitive(val) || Ext.isDate(val);
44285     },
44286
44287     
44288     setValue : function(prop, value){
44289         this.source[prop] = value;
44290         this.store.getById(prop).set('value', value);
44291     },
44292
44293     
44294     getSource : function(){
44295         return this.source;
44296     }
44297 });
44298
44299
44300 Ext.grid.PropertyColumnModel = Ext.extend(Ext.grid.ColumnModel, {
44301     
44302     nameText : 'Name',
44303     valueText : 'Value',
44304     dateFormat : 'm/j/Y',
44305     
44306     constructor : function(grid, store){
44307         var g = Ext.grid,
44308                 f = Ext.form;
44309                 
44310             this.grid = grid;
44311             g.PropertyColumnModel.superclass.constructor.call(this, [
44312                 {header: this.nameText, width:50, sortable: true, dataIndex:'name', id: 'name', menuDisabled:true},
44313                 {header: this.valueText, width:50, resizable:false, dataIndex: 'value', id: 'value', menuDisabled:true}
44314             ]);
44315             this.store = store;
44316         
44317             var bfield = new f.Field({
44318                 autoCreate: {tag: 'select', children: [
44319                     {tag: 'option', value: 'true', html: 'true'},
44320                     {tag: 'option', value: 'false', html: 'false'}
44321                 ]},
44322                 getValue : function(){
44323                     return this.el.dom.value == 'true';
44324                 }
44325             });
44326             this.editors = {
44327                 'date' : new g.GridEditor(new f.DateField({selectOnFocus:true})),
44328                 'string' : new g.GridEditor(new f.TextField({selectOnFocus:true})),
44329                 'number' : new g.GridEditor(new f.NumberField({selectOnFocus:true, style:'text-align:left;'})),
44330                 'boolean' : new g.GridEditor(bfield, {
44331                     autoSize: 'both'
44332                 })
44333             };
44334             this.renderCellDelegate = this.renderCell.createDelegate(this);
44335             this.renderPropDelegate = this.renderProp.createDelegate(this);
44336     },
44337
44338     
44339     renderDate : function(dateVal){
44340         return dateVal.dateFormat(this.dateFormat);
44341     },
44342
44343     
44344     renderBool : function(bVal){
44345         return bVal ? 'true' : 'false';
44346     },
44347
44348     
44349     isCellEditable : function(colIndex, rowIndex){
44350         return colIndex == 1;
44351     },
44352
44353     
44354     getRenderer : function(col){
44355         return col == 1 ?
44356             this.renderCellDelegate : this.renderPropDelegate;
44357     },
44358
44359     
44360     renderProp : function(v){
44361         return this.getPropertyName(v);
44362     },
44363
44364     
44365     renderCell : function(val){
44366         var rv = val;
44367         if(Ext.isDate(val)){
44368             rv = this.renderDate(val);
44369         }else if(typeof val == 'boolean'){
44370             rv = this.renderBool(val);
44371         }
44372         return Ext.util.Format.htmlEncode(rv);
44373     },
44374
44375     
44376     getPropertyName : function(name){
44377         var pn = this.grid.propertyNames;
44378         return pn && pn[name] ? pn[name] : name;
44379     },
44380
44381     
44382     getCellEditor : function(colIndex, rowIndex){
44383         var p = this.store.getProperty(rowIndex),
44384             n = p.data.name, 
44385             val = p.data.value;
44386         if(this.grid.customEditors[n]){
44387             return this.grid.customEditors[n];
44388         }
44389         if(Ext.isDate(val)){
44390             return this.editors.date;
44391         }else if(typeof val == 'number'){
44392             return this.editors.number;
44393         }else if(typeof val == 'boolean'){
44394             return this.editors['boolean'];
44395         }else{
44396             return this.editors.string;
44397         }
44398     },
44399
44400     
44401     destroy : function(){
44402         Ext.grid.PropertyColumnModel.superclass.destroy.call(this);
44403         for(var ed in this.editors){
44404             Ext.destroy(this.editors[ed]);
44405         }
44406     }
44407 });
44408
44409
44410 Ext.grid.PropertyGrid = Ext.extend(Ext.grid.EditorGridPanel, {
44411     
44412     
44413     
44414
44415     
44416     enableColumnMove:false,
44417     stripeRows:false,
44418     trackMouseOver: false,
44419     clicksToEdit:1,
44420     enableHdMenu : false,
44421     viewConfig : {
44422         forceFit:true
44423     },
44424
44425     
44426     initComponent : function(){
44427         this.customEditors = this.customEditors || {};
44428         this.lastEditRow = null;
44429         var store = new Ext.grid.PropertyStore(this);
44430         this.propStore = store;
44431         var cm = new Ext.grid.PropertyColumnModel(this, store);
44432         store.store.sort('name', 'ASC');
44433         this.addEvents(
44434             
44435             'beforepropertychange',
44436             
44437             'propertychange'
44438         );
44439         this.cm = cm;
44440         this.ds = store.store;
44441         Ext.grid.PropertyGrid.superclass.initComponent.call(this);
44442
44443                 this.mon(this.selModel, 'beforecellselect', function(sm, rowIndex, colIndex){
44444             if(colIndex === 0){
44445                 this.startEditing.defer(200, this, [rowIndex, 1]);
44446                 return false;
44447             }
44448         }, this);
44449     },
44450
44451     
44452     onRender : function(){
44453         Ext.grid.PropertyGrid.superclass.onRender.apply(this, arguments);
44454
44455         this.getGridEl().addClass('x-props-grid');
44456     },
44457
44458     
44459     afterRender: function(){
44460         Ext.grid.PropertyGrid.superclass.afterRender.apply(this, arguments);
44461         if(this.source){
44462             this.setSource(this.source);
44463         }
44464     },
44465
44466     
44467     setSource : function(source){
44468         this.propStore.setSource(source);
44469     },
44470
44471     
44472     getSource : function(){
44473         return this.propStore.getSource();
44474     }
44475
44476     
44477     
44478     
44479     
44480 });
44481 Ext.reg("propertygrid", Ext.grid.PropertyGrid);
44482
44483 Ext.grid.GroupingView = Ext.extend(Ext.grid.GridView, {
44484
44485     
44486     groupByText : 'Group By This Field',
44487     
44488     showGroupsText : 'Show in Groups',
44489     
44490     hideGroupedColumn : false,
44491     
44492     showGroupName : true,
44493     
44494     startCollapsed : false,
44495     
44496     enableGrouping : true,
44497     
44498     enableGroupingMenu : true,
44499     
44500     enableNoGroups : true,
44501     
44502     emptyGroupText : '(None)',
44503     
44504     ignoreAdd : false,
44505     
44506     groupTextTpl : '{text}',
44507
44508     
44509     groupMode: 'value',
44510
44511     
44512
44513     
44514     gidSeed : 1000,
44515
44516     
44517     initTemplates : function(){
44518         Ext.grid.GroupingView.superclass.initTemplates.call(this);
44519         this.state = {};
44520
44521         var sm = this.grid.getSelectionModel();
44522         sm.on(sm.selectRow ? 'beforerowselect' : 'beforecellselect',
44523                 this.onBeforeRowSelect, this);
44524
44525         if(!this.startGroup){
44526             this.startGroup = new Ext.XTemplate(
44527                 '<div id="{groupId}" class="x-grid-group {cls}">',
44528                     '<div id="{groupId}-hd" class="x-grid-group-hd" style="{style}"><div class="x-grid-group-title">', this.groupTextTpl ,'</div></div>',
44529                     '<div id="{groupId}-bd" class="x-grid-group-body">'
44530             );
44531         }
44532         this.startGroup.compile();
44533         if(!this.endGroup){
44534             this.endGroup = '</div></div>';
44535         }
44536
44537         this.endGroup = '</div></div>';
44538     },
44539
44540     
44541     findGroup : function(el){
44542         return Ext.fly(el).up('.x-grid-group', this.mainBody.dom);
44543     },
44544
44545     
44546     getGroups : function(){
44547         return this.hasRows() ? this.mainBody.dom.childNodes : [];
44548     },
44549
44550     
44551     onAdd : function(){
44552         if(this.enableGrouping && !this.ignoreAdd){
44553             var ss = this.getScrollState();
44554             this.refresh();
44555             this.restoreScroll(ss);
44556         }else if(!this.enableGrouping){
44557             Ext.grid.GroupingView.superclass.onAdd.apply(this, arguments);
44558         }
44559     },
44560
44561     
44562     onRemove : function(ds, record, index, isUpdate){
44563         Ext.grid.GroupingView.superclass.onRemove.apply(this, arguments);
44564         var g = document.getElementById(record._groupId);
44565         if(g && g.childNodes[1].childNodes.length < 1){
44566             Ext.removeNode(g);
44567         }
44568         this.applyEmptyText();
44569     },
44570
44571     
44572     refreshRow : function(record){
44573         if(this.ds.getCount()==1){
44574             this.refresh();
44575         }else{
44576             this.isUpdating = true;
44577             Ext.grid.GroupingView.superclass.refreshRow.apply(this, arguments);
44578             this.isUpdating = false;
44579         }
44580     },
44581
44582     
44583     beforeMenuShow : function(){
44584         var item, items = this.hmenu.items, disabled = this.cm.config[this.hdCtxIndex].groupable === false;
44585         if((item = items.get('groupBy'))){
44586             item.setDisabled(disabled);
44587         }
44588         if((item = items.get('showGroups'))){
44589             item.setDisabled(disabled);
44590         item.setChecked(this.enableGrouping, true);
44591         }
44592     },
44593
44594     
44595     renderUI : function(){
44596         Ext.grid.GroupingView.superclass.renderUI.call(this);
44597         this.mainBody.on('mousedown', this.interceptMouse, this);
44598
44599         if(this.enableGroupingMenu && this.hmenu){
44600             this.hmenu.add('-',{
44601                 itemId:'groupBy',
44602                 text: this.groupByText,
44603                 handler: this.onGroupByClick,
44604                 scope: this,
44605                 iconCls:'x-group-by-icon'
44606             });
44607             if(this.enableNoGroups){
44608                 this.hmenu.add({
44609                     itemId:'showGroups',
44610                     text: this.showGroupsText,
44611             checked: true,
44612                     checkHandler: this.onShowGroupsClick,
44613                     scope: this
44614                 });
44615             }
44616             this.hmenu.on('beforeshow', this.beforeMenuShow, this);
44617         }
44618     },
44619
44620     processEvent: function(name, e){
44621         var hd = e.getTarget('.x-grid-group-hd', this.mainBody);
44622         if(hd){
44623             
44624             var field = this.getGroupField(),
44625                 prefix = this.getPrefix(field),
44626                 groupValue = hd.id.substring(prefix.length);
44627
44628             
44629             groupValue = groupValue.substr(0, groupValue.length - 3);
44630             if(groupValue){
44631                 this.grid.fireEvent('group' + name, this.grid, field, groupValue, e);
44632             }
44633         }
44634
44635     },
44636
44637     
44638     onGroupByClick : function(){
44639     this.enableGrouping = true;
44640         this.grid.store.groupBy(this.cm.getDataIndex(this.hdCtxIndex));
44641         this.beforeMenuShow(); 
44642     this.refresh();
44643     },
44644
44645     
44646     onShowGroupsClick : function(mi, checked){
44647     this.enableGrouping = checked;
44648         if(checked){
44649             this.onGroupByClick();
44650         }else{
44651             this.grid.store.clearGrouping();
44652         }
44653     },
44654
44655     
44656     toggleRowIndex : function(rowIndex, expanded){
44657         if(!this.enableGrouping){
44658             return;
44659         }
44660         var row = this.getRow(rowIndex);
44661         if(row){
44662             this.toggleGroup(this.findGroup(row), expanded);
44663         }
44664     },
44665
44666     
44667     toggleGroup : function(group, expanded){
44668         var gel = Ext.get(group);
44669         expanded = Ext.isDefined(expanded) ? expanded : gel.hasClass('x-grid-group-collapsed');
44670         if(this.state[gel.id] !== expanded){
44671             this.grid.stopEditing(true);
44672             this.state[gel.id] = expanded;
44673             gel[expanded ? 'removeClass' : 'addClass']('x-grid-group-collapsed');
44674         }
44675     },
44676
44677     
44678     toggleAllGroups : function(expanded){
44679         var groups = this.getGroups();
44680         for(var i = 0, len = groups.length; i < len; i++){
44681             this.toggleGroup(groups[i], expanded);
44682         }
44683     },
44684
44685     
44686     expandAllGroups : function(){
44687         this.toggleAllGroups(true);
44688     },
44689
44690     
44691     collapseAllGroups : function(){
44692         this.toggleAllGroups(false);
44693     },
44694
44695     
44696     interceptMouse : function(e){
44697         var hd = e.getTarget('.x-grid-group-hd', this.mainBody);
44698         if(hd){
44699             e.stopEvent();
44700             this.toggleGroup(hd.parentNode);
44701         }
44702     },
44703
44704     
44705     getGroup : function(v, r, groupRenderer, rowIndex, colIndex, ds){
44706         var g = groupRenderer ? groupRenderer(v, {}, r, rowIndex, colIndex, ds) : String(v);
44707         if(g === '' || g === '&#160;'){
44708             g = this.cm.config[colIndex].emptyGroupText || this.emptyGroupText;
44709         }
44710         return g;
44711     },
44712
44713     
44714     getGroupField : function(){
44715         return this.grid.store.getGroupState();
44716     },
44717
44718     
44719     afterRender : function(){
44720         Ext.grid.GroupingView.superclass.afterRender.call(this);
44721         if(this.grid.deferRowRender){
44722             this.updateGroupWidths();
44723         }
44724     },
44725
44726     
44727     renderRows : function(){
44728         var groupField = this.getGroupField();
44729         var eg = !!groupField;
44730         
44731         if(this.hideGroupedColumn) {
44732             var colIndex = this.cm.findColumnIndex(groupField),
44733                 hasLastGroupField = Ext.isDefined(this.lastGroupField);
44734             if(!eg && hasLastGroupField){
44735                 this.mainBody.update('');
44736                 this.cm.setHidden(this.cm.findColumnIndex(this.lastGroupField), false);
44737                 delete this.lastGroupField;
44738             }else if (eg && !hasLastGroupField){
44739                 this.lastGroupField = groupField;
44740                 this.cm.setHidden(colIndex, true);
44741             }else if (eg && hasLastGroupField && groupField !== this.lastGroupField) {
44742                 this.mainBody.update('');
44743                 var oldIndex = this.cm.findColumnIndex(this.lastGroupField);
44744                 this.cm.setHidden(oldIndex, false);
44745                 this.lastGroupField = groupField;
44746                 this.cm.setHidden(colIndex, true);
44747             }
44748         }
44749         return Ext.grid.GroupingView.superclass.renderRows.apply(
44750                     this, arguments);
44751     },
44752
44753     
44754     doRender : function(cs, rs, ds, startRow, colCount, stripe){
44755         if(rs.length < 1){
44756             return '';
44757         }
44758         var groupField = this.getGroupField(),
44759             colIndex = this.cm.findColumnIndex(groupField),
44760             g;
44761
44762         this.enableGrouping = (this.enableGrouping === false) ? false : !!groupField;
44763
44764         if(!this.enableGrouping || this.isUpdating){
44765             return Ext.grid.GroupingView.superclass.doRender.apply(
44766                     this, arguments);
44767         }
44768         var gstyle = 'width:' + this.getTotalWidth() + ';',
44769             cfg = this.cm.config[colIndex],
44770             groupRenderer = cfg.groupRenderer || cfg.renderer,
44771             prefix = this.showGroupName ? (cfg.groupName || cfg.header)+': ' : '',
44772             groups = [],
44773             curGroup, i, len, gid;
44774
44775         for(i = 0, len = rs.length; i < len; i++){
44776             var rowIndex = startRow + i,
44777                 r = rs[i],
44778                 gvalue = r.data[groupField];
44779
44780                 g = this.getGroup(gvalue, r, groupRenderer, rowIndex, colIndex, ds);
44781             if(!curGroup || curGroup.group != g){
44782                 gid = this.constructId(gvalue, groupField, colIndex);
44783                 
44784                 
44785                 this.state[gid] = !(Ext.isDefined(this.state[gid]) ? !this.state[gid] : this.startCollapsed);
44786                 curGroup = {
44787                     group: g,
44788                     gvalue: gvalue,
44789                     text: prefix + g,
44790                     groupId: gid,
44791                     startRow: rowIndex,
44792                     rs: [r],
44793                     cls: this.state[gid] ? '' : 'x-grid-group-collapsed',
44794                     style: gstyle
44795                 };
44796                 groups.push(curGroup);
44797             }else{
44798                 curGroup.rs.push(r);
44799             }
44800             r._groupId = gid;
44801         }
44802
44803         var buf = [];
44804         for(i = 0, len = groups.length; i < len; i++){
44805             g = groups[i];
44806             this.doGroupStart(buf, g, cs, ds, colCount);
44807             buf[buf.length] = Ext.grid.GroupingView.superclass.doRender.call(
44808                     this, cs, g.rs, ds, g.startRow, colCount, stripe);
44809
44810             this.doGroupEnd(buf, g, cs, ds, colCount);
44811         }
44812         return buf.join('');
44813     },
44814
44815     
44816     getGroupId : function(value){
44817         var field = this.getGroupField();
44818         return this.constructId(value, field, this.cm.findColumnIndex(field));
44819     },
44820
44821     
44822     constructId : function(value, field, idx){
44823         var cfg = this.cm.config[idx],
44824             groupRenderer = cfg.groupRenderer || cfg.renderer,
44825             val = (this.groupMode == 'value') ? value : this.getGroup(value, {data:{}}, groupRenderer, 0, idx, this.ds);
44826
44827         return this.getPrefix(field) + Ext.util.Format.htmlEncode(val);
44828     },
44829
44830     
44831     getPrefix: function(field){
44832         return this.grid.getGridEl().id + '-gp-' + field + '-';
44833     },
44834
44835     
44836     doGroupStart : function(buf, g, cs, ds, colCount){
44837         buf[buf.length] = this.startGroup.apply(g);
44838     },
44839
44840     
44841     doGroupEnd : function(buf, g, cs, ds, colCount){
44842         buf[buf.length] = this.endGroup;
44843     },
44844
44845     
44846     getRows : function(){
44847         if(!this.enableGrouping){
44848             return Ext.grid.GroupingView.superclass.getRows.call(this);
44849         }
44850         var r = [];
44851         var g, gs = this.getGroups();
44852         for(var i = 0, len = gs.length; i < len; i++){
44853             g = gs[i].childNodes[1].childNodes;
44854             for(var j = 0, jlen = g.length; j < jlen; j++){
44855                 r[r.length] = g[j];
44856             }
44857         }
44858         return r;
44859     },
44860
44861     
44862     updateGroupWidths : function(){
44863         if(!this.enableGrouping || !this.hasRows()){
44864             return;
44865         }
44866         var tw = Math.max(this.cm.getTotalWidth(), this.el.dom.offsetWidth-this.getScrollOffset()) +'px';
44867         var gs = this.getGroups();
44868         for(var i = 0, len = gs.length; i < len; i++){
44869             gs[i].firstChild.style.width = tw;
44870         }
44871     },
44872
44873     
44874     onColumnWidthUpdated : function(col, w, tw){
44875         Ext.grid.GroupingView.superclass.onColumnWidthUpdated.call(this, col, w, tw);
44876         this.updateGroupWidths();
44877     },
44878
44879     
44880     onAllColumnWidthsUpdated : function(ws, tw){
44881         Ext.grid.GroupingView.superclass.onAllColumnWidthsUpdated.call(this, ws, tw);
44882         this.updateGroupWidths();
44883     },
44884
44885     
44886     onColumnHiddenUpdated : function(col, hidden, tw){
44887         Ext.grid.GroupingView.superclass.onColumnHiddenUpdated.call(this, col, hidden, tw);
44888         this.updateGroupWidths();
44889     },
44890
44891     
44892     onLayout : function(){
44893         this.updateGroupWidths();
44894     },
44895
44896     
44897     onBeforeRowSelect : function(sm, rowIndex){
44898         this.toggleRowIndex(rowIndex, true);
44899     }
44900 });
44901
44902 Ext.grid.GroupingView.GROUP_ID = 1000;