Upgrade to ExtJS 3.0.0 - Released 07/06/2009
[extjs.git] / docs / source / ext-all.html
1 <html>\r
2 <head>\r
3   <title>The source code</title>\r
4     <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />\r
5     <script type="text/javascript" src="../resources/prettify/prettify.js"></script>\r
6 </head>\r
7 <body  onload="prettyPrint();">\r
8     <pre class="prettyprint lang-js">/*
9  * Ext JS Library 2.0.2
10  * Copyright(c) 2006-2008, Ext JS, LLC.
11  * licensing@extjs.com
12  * 
13  * http://extjs.com/license
14  */
15
16
17 Ext.DomHelper = function(){
18     var tempTableEl = null;
19     var emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;
20     var tableRe = /^table|tbody|tr|td$/i;
21     
22     
23     var createHtml = function(o){
24         if(typeof o == 'string'){
25             return o;
26         }
27         var b = "";
28         if (Ext.isArray(o)) {
29             for (var i = 0, l = o.length; i < l; i++) {
30                 b += createHtml(o[i]);
31             }
32             return b;
33         }
34         if(!o.tag){
35             o.tag = "div";
36         }
37         b += "<" + o.tag;
38         for(var attr in o){
39             if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || typeof o[attr] == "function") continue;
40             if(attr == "style"){
41                 var s = o["style"];
42                 if(typeof s == "function"){
43                     s = s.call();
44                 }
45                 if(typeof s == "string"){
46                     b += ' style="' + s + '"';
47                 }else if(typeof s == "object"){
48                     b += ' style="';
49                     for(var key in s){
50                         if(typeof s[key] != "function"){
51                             b += key + ":" + s[key] + ";";
52                         }
53                     }
54                     b += '"';
55                 }
56             }else{
57                 if(attr == "cls"){
58                     b += ' class="' + o["cls"] + '"';
59                 }else if(attr == "htmlFor"){
60                     b += ' for="' + o["htmlFor"] + '"';
61                 }else{
62                     b += " " + attr + '="' + o[attr] + '"';
63                 }
64             }
65         }
66         if(emptyTags.test(o.tag)){
67             b += "/>";
68         }else{
69             b += ">";
70             var cn = o.children || o.cn;
71             if(cn){
72                 b += createHtml(cn);
73             } else if(o.html){
74                 b += o.html;
75             }
76             b += "</" + o.tag + ">";
77         }
78         return b;
79     };
80
81     
82     
83     var createDom = function(o, parentNode){
84         var el;
85         if (Ext.isArray(o)) {                       
86             el = document.createDocumentFragment(); 
87             for(var i = 0, l = o.length; i < l; i++) {
88                 createDom(o[i], el);
89             }
90         } else if (typeof o == "string)") {         
91             el = document.createTextNode(o);
92         } else {
93             el = document.createElement(o.tag||'div');
94             var useSet = !!el.setAttribute; 
95             for(var attr in o){
96                 if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || attr == "style" || typeof o[attr] == "function") continue;
97                 if(attr=="cls"){
98                     el.className = o["cls"];
99                 }else{
100                     if(useSet) el.setAttribute(attr, o[attr]);
101                     else el[attr] = o[attr];
102                 }
103             }
104             Ext.DomHelper.applyStyles(el, o.style);
105             var cn = o.children || o.cn;
106             if(cn){
107                 createDom(cn, el);
108             } else if(o.html){
109                 el.innerHTML = o.html;
110             }
111         }
112         if(parentNode){
113            parentNode.appendChild(el);
114         }
115         return el;
116     };
117
118     var ieTable = function(depth, s, h, e){
119         tempTableEl.innerHTML = [s, h, e].join('');
120         var i = -1, el = tempTableEl;
121         while(++i < depth){
122             el = el.firstChild;
123         }
124         return el;
125     };
126
127     
128     var ts = '<table>',
129         te = '</table>',
130         tbs = ts+'<tbody>',
131         tbe = '</tbody>'+te,
132         trs = tbs + '<tr>',
133         tre = '</tr>'+tbe;
134
135     
136     var insertIntoTable = function(tag, where, el, html){
137         if(!tempTableEl){
138             tempTableEl = document.createElement('div');
139         }
140         var node;
141         var before = null;
142         if(tag == 'td'){
143             if(where == 'afterbegin' || where == 'beforeend'){ 
144                 return;
145             }
146             if(where == 'beforebegin'){
147                 before = el;
148                 el = el.parentNode;
149             } else{
150                 before = el.nextSibling;
151                 el = el.parentNode;
152             }
153             node = ieTable(4, trs, html, tre);
154         }
155         else if(tag == 'tr'){
156             if(where == 'beforebegin'){
157                 before = el;
158                 el = el.parentNode;
159                 node = ieTable(3, tbs, html, tbe);
160             } else if(where == 'afterend'){
161                 before = el.nextSibling;
162                 el = el.parentNode;
163                 node = ieTable(3, tbs, html, tbe);
164             } else{ 
165                 if(where == 'afterbegin'){
166                     before = el.firstChild;
167                 }
168                 node = ieTable(4, trs, html, tre);
169             }
170         } else if(tag == 'tbody'){
171             if(where == 'beforebegin'){
172                 before = el;
173                 el = el.parentNode;
174                 node = ieTable(2, ts, html, te);
175             } else if(where == 'afterend'){
176                 before = el.nextSibling;
177                 el = el.parentNode;
178                 node = ieTable(2, ts, html, te);
179             } else{
180                 if(where == 'afterbegin'){
181                     before = el.firstChild;
182                 }
183                 node = ieTable(3, tbs, html, tbe);
184             }
185         } else{ 
186             if(where == 'beforebegin' || where == 'afterend'){ 
187                 return;
188             }
189             if(where == 'afterbegin'){
190                 before = el.firstChild;
191             }
192             node = ieTable(2, ts, html, te);
193         }
194         el.insertBefore(node, before);
195         return node;
196     };
197
198
199     return {
200     
201     useDom : false,
202
203     
204     markup : function(o){
205         return createHtml(o);
206     },
207
208     
209     applyStyles : function(el, styles){
210         if(styles){
211            el = Ext.fly(el);
212            if(typeof styles == "string"){
213                var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
214                var matches;
215                while ((matches = re.exec(styles)) != null){
216                    el.setStyle(matches[1], matches[2]);
217                }
218            }else if (typeof styles == "object"){
219                for (var style in styles){
220                   el.setStyle(style, styles[style]);
221                }
222            }else if (typeof styles == "function"){
223                 Ext.DomHelper.applyStyles(el, styles.call());
224            }
225         }
226     },
227
228     
229     insertHtml : function(where, el, html){
230         where = where.toLowerCase();
231         if(el.insertAdjacentHTML){
232             if(tableRe.test(el.tagName)){
233                 var rs;
234                 if(rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)){
235                     return rs;
236                 }
237             }
238             switch(where){
239                 case "beforebegin":
240                     el.insertAdjacentHTML('BeforeBegin', html);
241                     return el.previousSibling;
242                 case "afterbegin":
243                     el.insertAdjacentHTML('AfterBegin', html);
244                     return el.firstChild;
245                 case "beforeend":
246                     el.insertAdjacentHTML('BeforeEnd', html);
247                     return el.lastChild;
248                 case "afterend":
249                     el.insertAdjacentHTML('AfterEnd', html);
250                     return el.nextSibling;
251             }
252             throw 'Illegal insertion point -> "' + where + '"';
253         }
254         var range = el.ownerDocument.createRange();
255         var frag;
256         switch(where){
257              case "beforebegin":
258                 range.setStartBefore(el);
259                 frag = range.createContextualFragment(html);
260                 el.parentNode.insertBefore(frag, el);
261                 return el.previousSibling;
262              case "afterbegin":
263                 if(el.firstChild){
264                     range.setStartBefore(el.firstChild);
265                     frag = range.createContextualFragment(html);
266                     el.insertBefore(frag, el.firstChild);
267                     return el.firstChild;
268                 }else{
269                     el.innerHTML = html;
270                     return el.firstChild;
271                 }
272             case "beforeend":
273                 if(el.lastChild){
274                     range.setStartAfter(el.lastChild);
275                     frag = range.createContextualFragment(html);
276                     el.appendChild(frag);
277                     return el.lastChild;
278                 }else{
279                     el.innerHTML = html;
280                     return el.lastChild;
281                 }
282             case "afterend":
283                 range.setStartAfter(el);
284                 frag = range.createContextualFragment(html);
285                 el.parentNode.insertBefore(frag, el.nextSibling);
286                 return el.nextSibling;
287             }
288             throw 'Illegal insertion point -> "' + where + '"';
289     },
290
291     
292     insertBefore : function(el, o, returnElement){
293         return this.doInsert(el, o, returnElement, "beforeBegin");
294     },
295
296     
297     insertAfter : function(el, o, returnElement){
298         return this.doInsert(el, o, returnElement, "afterEnd", "nextSibling");
299     },
300
301     
302     insertFirst : function(el, o, returnElement){
303         return this.doInsert(el, o, returnElement, "afterBegin", "firstChild");
304     },
305
306     
307     doInsert : function(el, o, returnElement, pos, sibling){
308         el = Ext.getDom(el);
309         var newNode;
310         if(this.useDom){
311             newNode = createDom(o, null);
312             (sibling === "firstChild" ? el : el.parentNode).insertBefore(newNode, sibling ? el[sibling] : el);
313         }else{
314             var html = createHtml(o);
315             newNode = this.insertHtml(pos, el, html);
316         }
317         return returnElement ? Ext.get(newNode, true) : newNode;
318     },
319
320     
321     append : function(el, o, returnElement){
322         el = Ext.getDom(el);
323         var newNode;
324         if(this.useDom){
325             newNode = createDom(o, null);
326             el.appendChild(newNode);
327         }else{
328             var html = createHtml(o);
329             newNode = this.insertHtml("beforeEnd", el, html);
330         }
331         return returnElement ? Ext.get(newNode, true) : newNode;
332     },
333
334     
335     overwrite : function(el, o, returnElement){
336         el = Ext.getDom(el);
337         el.innerHTML = createHtml(o);
338         return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;
339     },
340
341     
342     createTemplate : function(o){
343         var html = createHtml(o);
344         return new Ext.Template(html);
345     }
346     };
347 }();
348
349
350 Ext.Template = function(html){
351     var a = arguments;
352     if(Ext.isArray(html)){
353         html = html.join("");
354     }else if(a.length > 1){
355         var buf = [];
356         for(var i = 0, len = a.length; i < len; i++){
357             if(typeof a[i] == 'object'){
358                 Ext.apply(this, a[i]);
359             }else{
360                 buf[buf.length] = a[i];
361             }
362         }
363         html = buf.join('');
364     }
365     
366     this.html = html;
367     if(this.compiled){
368         this.compile();   
369     }
370 };
371 Ext.Template.prototype = {
372     
373     applyTemplate : function(values){
374         if(this.compiled){
375             return this.compiled(values);
376         }
377         var useF = this.disableFormats !== true;
378         var fm = Ext.util.Format, tpl = this;
379         var fn = function(m, name, format, args){
380             if(format && useF){
381                 if(format.substr(0, 5) == "this."){
382                     return tpl.call(format.substr(5), values[name], values);
383                 }else{
384                     if(args){
385                         
386                         
387                         
388                         var re = /^\s*['"](.*)["']\s*$/;
389                         args = args.split(',');
390                         for(var i = 0, len = args.length; i < len; i++){
391                             args[i] = args[i].replace(re, "$1");
392                         }
393                         args = [values[name]].concat(args);
394                     }else{
395                         args = [values[name]];
396                     }
397                     return fm[format].apply(fm, args);
398                 }
399             }else{
400                 return values[name] !== undefined ? values[name] : "";
401             }
402         };
403         return this.html.replace(this.re, fn);
404     },
405     
406     
407     set : function(html, compile){
408         this.html = html;
409         this.compiled = null;
410         if(compile){
411             this.compile();
412         }
413         return this;
414     },
415     
416     
417     disableFormats : false,
418     
419     
420     re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
421     
422     
423     compile : function(){
424         var fm = Ext.util.Format;
425         var useF = this.disableFormats !== true;
426         var sep = Ext.isGecko ? "+" : ",";
427         var fn = function(m, name, format, args){
428             if(format && useF){
429                 args = args ? ',' + args : "";
430                 if(format.substr(0, 5) != "this."){
431                     format = "fm." + format + '(';
432                 }else{
433                     format = 'this.call("'+ format.substr(5) + '", ';
434                     args = ", values";
435                 }
436             }else{
437                 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
438             }
439             return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
440         };
441         var body;
442         
443         if(Ext.isGecko){
444             body = "this.compiled = function(values){ return '" +
445                    this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
446                     "';};";
447         }else{
448             body = ["this.compiled = function(values){ return ['"];
449             body.push(this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn));
450             body.push("'].join('');};");
451             body = body.join('');
452         }
453         eval(body);
454         return this;
455     },
456     
457     
458     call : function(fnName, value, allValues){
459         return this[fnName](value, allValues);
460     },
461     
462     
463     insertFirst: function(el, values, returnElement){
464         return this.doInsert('afterBegin', el, values, returnElement);
465     },
466
467     
468     insertBefore: function(el, values, returnElement){
469         return this.doInsert('beforeBegin', el, values, returnElement);
470     },
471
472     
473     insertAfter : function(el, values, returnElement){
474         return this.doInsert('afterEnd', el, values, returnElement);
475     },
476     
477     
478     append : function(el, values, returnElement){
479         return this.doInsert('beforeEnd', el, values, returnElement);
480     },
481
482     doInsert : function(where, el, values, returnEl){
483         el = Ext.getDom(el);
484         var newNode = Ext.DomHelper.insertHtml(where, el, this.applyTemplate(values));
485         return returnEl ? Ext.get(newNode, true) : newNode;
486     },
487
488     
489     overwrite : function(el, values, returnElement){
490         el = Ext.getDom(el);
491         el.innerHTML = this.applyTemplate(values);
492         return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;
493     }
494 };
495
496 Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate;
497
498
499 Ext.DomHelper.Template = Ext.Template;
500
501
502 Ext.Template.from = function(el, config){
503     el = Ext.getDom(el);
504     return new Ext.Template(el.value || el.innerHTML, config || '');
505 };
506
507
508 Ext.DomQuery = function(){
509     var cache = {}, simpleCache = {}, valueCache = {};
510     var nonSpace = /\S/;
511     var trimRe = /^\s+|\s+$/g;
512     var tplRe = /\{(\d+)\}/g;
513     var modeRe = /^(\s?[\/>+~]\s?|\s|$)/;
514     var tagTokenRe = /^(#)?([\w-\*]+)/;
515     var nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/;
516
517     function child(p, index){
518         var i = 0;
519         var n = p.firstChild;
520         while(n){
521             if(n.nodeType == 1){
522                if(++i == index){
523                    return n;
524                }
525             }
526             n = n.nextSibling;
527         }
528         return null;
529     };
530
531     function next(n){
532         while((n = n.nextSibling) && n.nodeType != 1);
533         return n;
534     };
535
536     function prev(n){
537         while((n = n.previousSibling) && n.nodeType != 1);
538         return n;
539     };
540
541     function children(d){
542         var n = d.firstChild, ni = -1;
543             while(n){
544                 var nx = n.nextSibling;
545                 if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
546                     d.removeChild(n);
547                 }else{
548                     n.nodeIndex = ++ni;
549                 }
550                 n = nx;
551             }
552             return this;
553         };
554
555     function byClassName(c, a, v){
556         if(!v){
557             return c;
558         }
559         var r = [], ri = -1, cn;
560         for(var i = 0, ci; ci = c[i]; i++){
561             if((' '+ci.className+' ').indexOf(v) != -1){
562                 r[++ri] = ci;
563             }
564         }
565         return r;
566     };
567
568     function attrValue(n, attr){
569         if(!n.tagName && typeof n.length != "undefined"){
570             n = n[0];
571         }
572         if(!n){
573             return null;
574         }
575         if(attr == "for"){
576             return n.htmlFor;
577         }
578         if(attr == "class" || attr == "className"){
579             return n.className;
580         }
581         return n.getAttribute(attr) || n[attr];
582
583     };
584
585     function getNodes(ns, mode, tagName){
586         var result = [], ri = -1, cs;
587         if(!ns){
588             return result;
589         }
590         tagName = tagName || "*";
591         if(typeof ns.getElementsByTagName != "undefined"){
592             ns = [ns];
593         }
594         if(!mode){
595             for(var i = 0, ni; ni = ns[i]; i++){
596                 cs = ni.getElementsByTagName(tagName);
597                 for(var j = 0, ci; ci = cs[j]; j++){
598                     result[++ri] = ci;
599                 }
600             }
601         }else if(mode == "/" || mode == ">"){
602             var utag = tagName.toUpperCase();
603             for(var i = 0, ni, cn; ni = ns[i]; i++){
604                 cn = ni.children || ni.childNodes;
605                 for(var j = 0, cj; cj = cn[j]; j++){
606                     if(cj.nodeName == utag || cj.nodeName == tagName  || tagName == '*'){
607                         result[++ri] = cj;
608                     }
609                 }
610             }
611         }else if(mode == "+"){
612             var utag = tagName.toUpperCase();
613             for(var i = 0, n; n = ns[i]; i++){
614                 while((n = n.nextSibling) && n.nodeType != 1);
615                 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
616                     result[++ri] = n;
617                 }
618             }
619         }else if(mode == "~"){
620             for(var i = 0, n; n = ns[i]; i++){
621                 while((n = n.nextSibling) && (n.nodeType != 1 || (tagName == '*' || n.tagName.toLowerCase()!=tagName)));
622                 if(n){
623                     result[++ri] = n;
624                 }
625             }
626         }
627         return result;
628     };
629
630     function concat(a, b){
631         if(b.slice){
632             return a.concat(b);
633         }
634         for(var i = 0, l = b.length; i < l; i++){
635             a[a.length] = b[i];
636         }
637         return a;
638     }
639
640     function byTag(cs, tagName){
641         if(cs.tagName || cs == document){
642             cs = [cs];
643         }
644         if(!tagName){
645             return cs;
646         }
647         var r = [], ri = -1;
648         tagName = tagName.toLowerCase();
649         for(var i = 0, ci; ci = cs[i]; i++){
650             if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
651                 r[++ri] = ci;
652             }
653         }
654         return r;
655     };
656
657     function byId(cs, attr, id){
658         if(cs.tagName || cs == document){
659             cs = [cs];
660         }
661         if(!id){
662             return cs;
663         }
664         var r = [], ri = -1;
665         for(var i = 0,ci; ci = cs[i]; i++){
666             if(ci && ci.id == id){
667                 r[++ri] = ci;
668                 return r;
669             }
670         }
671         return r;
672     };
673
674     function byAttribute(cs, attr, value, op, custom){
675         var r = [], ri = -1, st = custom=="{";
676         var f = Ext.DomQuery.operators[op];
677         for(var i = 0, ci; ci = cs[i]; i++){
678             var a;
679             if(st){
680                 a = Ext.DomQuery.getStyle(ci, attr);
681             }
682             else if(attr == "class" || attr == "className"){
683                 a = ci.className;
684             }else if(attr == "for"){
685                 a = ci.htmlFor;
686             }else if(attr == "href"){
687                 a = ci.getAttribute("href", 2);
688             }else{
689                 a = ci.getAttribute(attr);
690             }
691             if((f && f(a, value)) || (!f && a)){
692                 r[++ri] = ci;
693             }
694         }
695         return r;
696     };
697
698     function byPseudo(cs, name, value){
699         return Ext.DomQuery.pseudos[name](cs, value);
700     };
701
702     
703     
704     
705     var isIE = window.ActiveXObject ? true : false;
706
707     
708     
709     eval("var batch = 30803;");
710
711     var key = 30803;
712
713     function nodupIEXml(cs){
714         var d = ++key;
715         cs[0].setAttribute("_nodup", d);
716         var r = [cs[0]];
717         for(var i = 1, len = cs.length; i < len; i++){
718             var c = cs[i];
719             if(!c.getAttribute("_nodup") != d){
720                 c.setAttribute("_nodup", d);
721                 r[r.length] = c;
722             }
723         }
724         for(var i = 0, len = cs.length; i < len; i++){
725             cs[i].removeAttribute("_nodup");
726         }
727         return r;
728     }
729
730     function nodup(cs){
731         if(!cs){
732             return [];
733         }
734         var len = cs.length, c, i, r = cs, cj, ri = -1;
735         if(!len || typeof cs.nodeType != "undefined" || len == 1){
736             return cs;
737         }
738         if(isIE && typeof cs[0].selectSingleNode != "undefined"){
739             return nodupIEXml(cs);
740         }
741         var d = ++key;
742         cs[0]._nodup = d;
743         for(i = 1; c = cs[i]; i++){
744             if(c._nodup != d){
745                 c._nodup = d;
746             }else{
747                 r = [];
748                 for(var j = 0; j < i; j++){
749                     r[++ri] = cs[j];
750                 }
751                 for(j = i+1; cj = cs[j]; j++){
752                     if(cj._nodup != d){
753                         cj._nodup = d;
754                         r[++ri] = cj;
755                     }
756                 }
757                 return r;
758             }
759         }
760         return r;
761     }
762
763     function quickDiffIEXml(c1, c2){
764         var d = ++key;
765         for(var i = 0, len = c1.length; i < len; i++){
766             c1[i].setAttribute("_qdiff", d);
767         }
768         var r = [];
769         for(var i = 0, len = c2.length; i < len; i++){
770             if(c2[i].getAttribute("_qdiff") != d){
771                 r[r.length] = c2[i];
772             }
773         }
774         for(var i = 0, len = c1.length; i < len; i++){
775            c1[i].removeAttribute("_qdiff");
776         }
777         return r;
778     }
779
780     function quickDiff(c1, c2){
781         var len1 = c1.length;
782         if(!len1){
783             return c2;
784         }
785         if(isIE && c1[0].selectSingleNode){
786             return quickDiffIEXml(c1, c2);
787         }
788         var d = ++key;
789         for(var i = 0; i < len1; i++){
790             c1[i]._qdiff = d;
791         }
792         var r = [];
793         for(var i = 0, len = c2.length; i < len; i++){
794             if(c2[i]._qdiff != d){
795                 r[r.length] = c2[i];
796             }
797         }
798         return r;
799     }
800
801     function quickId(ns, mode, root, id){
802         if(ns == root){
803            var d = root.ownerDocument || root;
804            return d.getElementById(id);
805         }
806         ns = getNodes(ns, mode, "*");
807         return byId(ns, null, id);
808     }
809
810     return {
811         getStyle : function(el, name){
812             return Ext.fly(el).getStyle(name);
813         },
814         
815         compile : function(path, type){
816             type = type || "select";
817
818             var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"];
819             var q = path, mode, lq;
820             var tk = Ext.DomQuery.matchers;
821             var tklen = tk.length;
822             var mm;
823
824             
825             var lmode = q.match(modeRe);
826             if(lmode && lmode[1]){
827                 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
828                 q = q.replace(lmode[1], "");
829             }
830             
831             while(path.substr(0, 1)=="/"){
832                 path = path.substr(1);
833             }
834
835             while(q && lq != q){
836                 lq = q;
837                 var tm = q.match(tagTokenRe);
838                 if(type == "select"){
839                     if(tm){
840                         if(tm[1] == "#"){
841                             fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
842                         }else{
843                             fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
844                         }
845                         q = q.replace(tm[0], "");
846                     }else if(q.substr(0, 1) != '@'){
847                         fn[fn.length] = 'n = getNodes(n, mode, "*");';
848                     }
849                 }else{
850                     if(tm){
851                         if(tm[1] == "#"){
852                             fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
853                         }else{
854                             fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
855                         }
856                         q = q.replace(tm[0], "");
857                     }
858                 }
859                 while(!(mm = q.match(modeRe))){
860                     var matched = false;
861                     for(var j = 0; j < tklen; j++){
862                         var t = tk[j];
863                         var m = q.match(t.re);
864                         if(m){
865                             fn[fn.length] = t.select.replace(tplRe, function(x, i){
866                                                     return m[i];
867                                                 });
868                             q = q.replace(m[0], "");
869                             matched = true;
870                             break;
871                         }
872                     }
873                     
874                     if(!matched){
875                         throw 'Error parsing selector, parsing failed at "' + q + '"';
876                     }
877                 }
878                 if(mm[1]){
879                     fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';
880                     q = q.replace(mm[1], "");
881                 }
882             }
883             fn[fn.length] = "return nodup(n);\n}";
884             eval(fn.join(""));
885             return f;
886         },
887
888         
889         select : function(path, root, type){
890             if(!root || root == document){
891                 root = document;
892             }
893             if(typeof root == "string"){
894                 root = document.getElementById(root);
895             }
896             var paths = path.split(",");
897             var results = [];
898             for(var i = 0, len = paths.length; i < len; i++){
899                 var p = paths[i].replace(trimRe, "");
900                 if(!cache[p]){
901                     cache[p] = Ext.DomQuery.compile(p);
902                     if(!cache[p]){
903                         throw p + " is not a valid selector";
904                     }
905                 }
906                 var result = cache[p](root);
907                 if(result && result != document){
908                     results = results.concat(result);
909                 }
910             }
911             if(paths.length > 1){
912                 return nodup(results);
913             }
914             return results;
915         },
916
917         
918         selectNode : function(path, root){
919             return Ext.DomQuery.select(path, root)[0];
920         },
921
922         
923         selectValue : function(path, root, defaultValue){
924             path = path.replace(trimRe, "");
925             if(!valueCache[path]){
926                 valueCache[path] = Ext.DomQuery.compile(path, "select");
927             }
928             var n = valueCache[path](root);
929             n = n[0] ? n[0] : n;
930             var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
931             return ((v === null||v === undefined||v==='') ? defaultValue : v);
932         },
933
934         
935         selectNumber : function(path, root, defaultValue){
936             var v = Ext.DomQuery.selectValue(path, root, defaultValue || 0);
937             return parseFloat(v);
938         },
939
940         
941         is : function(el, ss){
942             if(typeof el == "string"){
943                 el = document.getElementById(el);
944             }
945             var isArray = Ext.isArray(el);
946             var result = Ext.DomQuery.filter(isArray ? el : [el], ss);
947             return isArray ? (result.length == el.length) : (result.length > 0);
948         },
949
950         
951         filter : function(els, ss, nonMatches){
952             ss = ss.replace(trimRe, "");
953             if(!simpleCache[ss]){
954                 simpleCache[ss] = Ext.DomQuery.compile(ss, "simple");
955             }
956             var result = simpleCache[ss](els);
957             return nonMatches ? quickDiff(result, els) : result;
958         },
959
960         
961         matchers : [{
962                 re: /^\.([\w-]+)/,
963                 select: 'n = byClassName(n, null, " {1} ");'
964             }, {
965                 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
966                 select: 'n = byPseudo(n, "{1}", "{2}");'
967             },{
968                 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
969                 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
970             }, {
971                 re: /^#([\w-]+)/,
972                 select: 'n = byId(n, null, "{1}");'
973             },{
974                 re: /^@([\w-]+)/,
975                 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
976             }
977         ],
978
979         
980         operators : {
981             "=" : function(a, v){
982                 return a == v;
983             },
984             "!=" : function(a, v){
985                 return a != v;
986             },
987             "^=" : function(a, v){
988                 return a && a.substr(0, v.length) == v;
989             },
990             "$=" : function(a, v){
991                 return a && a.substr(a.length-v.length) == v;
992             },
993             "*=" : function(a, v){
994                 return a && a.indexOf(v) !== -1;
995             },
996             "%=" : function(a, v){
997                 return (a % v) == 0;
998             },
999             "|=" : function(a, v){
1000                 return a && (a == v || a.substr(0, v.length+1) == v+'-');
1001             },
1002             "~=" : function(a, v){
1003                 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
1004             }
1005         },
1006
1007         
1008         pseudos : {
1009             "first-child" : function(c){
1010                 var r = [], ri = -1, n;
1011                 for(var i = 0, ci; ci = n = c[i]; i++){
1012                     while((n = n.previousSibling) && n.nodeType != 1);
1013                     if(!n){
1014                         r[++ri] = ci;
1015                     }
1016                 }
1017                 return r;
1018             },
1019
1020             "last-child" : function(c){
1021                 var r = [], ri = -1, n;
1022                 for(var i = 0, ci; ci = n = c[i]; i++){
1023                     while((n = n.nextSibling) && n.nodeType != 1);
1024                     if(!n){
1025                         r[++ri] = ci;
1026                     }
1027                 }
1028                 return r;
1029             },
1030
1031             "nth-child" : function(c, a) {
1032                 var r = [], ri = -1;
1033                 var m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a);
1034                 var f = (m[1] || 1) - 0, l = m[2] - 0;
1035                 for(var i = 0, n; n = c[i]; i++){
1036                     var pn = n.parentNode;
1037                     if (batch != pn._batch) {
1038                         var j = 0;
1039                         for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
1040                             if(cn.nodeType == 1){
1041                                cn.nodeIndex = ++j;
1042                             }
1043                         }
1044                         pn._batch = batch;
1045                     }
1046                     if (f == 1) {
1047                         if (l == 0 || n.nodeIndex == l){
1048                             r[++ri] = n;
1049                         }
1050                     } else if ((n.nodeIndex + l) % f == 0){
1051                         r[++ri] = n;
1052                     }
1053                 }
1054
1055                 return r;
1056             },
1057
1058             "only-child" : function(c){
1059                 var r = [], ri = -1;;
1060                 for(var i = 0, ci; ci = c[i]; i++){
1061                     if(!prev(ci) && !next(ci)){
1062                         r[++ri] = ci;
1063                     }
1064                 }
1065                 return r;
1066             },
1067
1068             "empty" : function(c){
1069                 var r = [], ri = -1;
1070                 for(var i = 0, ci; ci = c[i]; i++){
1071                     var cns = ci.childNodes, j = 0, cn, empty = true;
1072                     while(cn = cns[j]){
1073                         ++j;
1074                         if(cn.nodeType == 1 || cn.nodeType == 3){
1075                             empty = false;
1076                             break;
1077                         }
1078                     }
1079                     if(empty){
1080                         r[++ri] = ci;
1081                     }
1082                 }
1083                 return r;
1084             },
1085
1086             "contains" : function(c, v){
1087                 var r = [], ri = -1;
1088                 for(var i = 0, ci; ci = c[i]; i++){
1089                     if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
1090                         r[++ri] = ci;
1091                     }
1092                 }
1093                 return r;
1094             },
1095
1096             "nodeValue" : function(c, v){
1097                 var r = [], ri = -1;
1098                 for(var i = 0, ci; ci = c[i]; i++){
1099                     if(ci.firstChild && ci.firstChild.nodeValue == v){
1100                         r[++ri] = ci;
1101                     }
1102                 }
1103                 return r;
1104             },
1105
1106             "checked" : function(c){
1107                 var r = [], ri = -1;
1108                 for(var i = 0, ci; ci = c[i]; i++){
1109                     if(ci.checked == true){
1110                         r[++ri] = ci;
1111                     }
1112                 }
1113                 return r;
1114             },
1115
1116             "not" : function(c, ss){
1117                 return Ext.DomQuery.filter(c, ss, true);
1118             },
1119
1120             "any" : function(c, selectors){
1121                 var ss = selectors.split('|');
1122                 var r = [], ri = -1, s;
1123                 for(var i = 0, ci; ci = c[i]; i++){
1124                     for(var j = 0; s = ss[j]; j++){
1125                         if(Ext.DomQuery.is(ci, s)){
1126                             r[++ri] = ci;
1127                             break;
1128                         }
1129                     }
1130                 }
1131                 return r;
1132             },
1133
1134             "odd" : function(c){
1135                 return this["nth-child"](c, "odd");
1136             },
1137
1138             "even" : function(c){
1139                 return this["nth-child"](c, "even");
1140             },
1141
1142             "nth" : function(c, a){
1143                 return c[a-1] || [];
1144             },
1145
1146             "first" : function(c){
1147                 return c[0] || [];
1148             },
1149
1150             "last" : function(c){
1151                 return c[c.length-1] || [];
1152             },
1153
1154             "has" : function(c, ss){
1155                 var s = Ext.DomQuery.select;
1156                 var r = [], ri = -1;
1157                 for(var i = 0, ci; ci = c[i]; i++){
1158                     if(s(ss, ci).length > 0){
1159                         r[++ri] = ci;
1160                     }
1161                 }
1162                 return r;
1163             },
1164
1165             "next" : function(c, ss){
1166                 var is = Ext.DomQuery.is;
1167                 var r = [], ri = -1;
1168                 for(var i = 0, ci; ci = c[i]; i++){
1169                     var n = next(ci);
1170                     if(n && is(n, ss)){
1171                         r[++ri] = ci;
1172                     }
1173                 }
1174                 return r;
1175             },
1176
1177             "prev" : function(c, ss){
1178                 var is = Ext.DomQuery.is;
1179                 var r = [], ri = -1;
1180                 for(var i = 0, ci; ci = c[i]; i++){
1181                     var n = prev(ci);
1182                     if(n && is(n, ss)){
1183                         r[++ri] = ci;
1184                     }
1185                 }
1186                 return r;
1187             }
1188         }
1189     };
1190 }();
1191
1192
1193 Ext.query = Ext.DomQuery.select;
1194
1195
1196 Ext.util.Observable = function(){
1197     
1198     if(this.listeners){
1199         this.on(this.listeners);
1200         delete this.listeners;
1201     }
1202 };
1203 Ext.util.Observable.prototype = {
1204     
1205     fireEvent : function(){
1206         if(this.eventsSuspended !== true){
1207             var ce = this.events[arguments[0].toLowerCase()];
1208             if(typeof ce == "object"){
1209                 return ce.fire.apply(ce, Array.prototype.slice.call(arguments, 1));
1210             }
1211         }
1212         return true;
1213     },
1214
1215         filterOptRe : /^(?:scope|delay|buffer|single)$/,
1216
1217     
1218     addListener : function(eventName, fn, scope, o){
1219         if(typeof eventName == "object"){
1220             o = eventName;
1221             for(var e in o){
1222                 if(this.filterOptRe.test(e)){
1223                     continue;
1224                 }
1225                 if(typeof o[e] == "function"){
1226                                         this.addListener(e, o[e], o.scope,  o);
1227                 }else{
1228                                         this.addListener(e, o[e].fn, o[e].scope, o[e]);
1229                 }
1230             }
1231             return;
1232         }
1233         o = (!o || typeof o == "boolean") ? {} : o;
1234         eventName = eventName.toLowerCase();
1235         var ce = this.events[eventName] || true;
1236         if(typeof ce == "boolean"){
1237             ce = new Ext.util.Event(this, eventName);
1238             this.events[eventName] = ce;
1239         }
1240         ce.addListener(fn, scope, o);
1241     },
1242
1243     
1244     removeListener : function(eventName, fn, scope){
1245         var ce = this.events[eventName.toLowerCase()];
1246         if(typeof ce == "object"){
1247             ce.removeListener(fn, scope);
1248         }
1249     },
1250
1251     
1252     purgeListeners : function(){
1253         for(var evt in this.events){
1254             if(typeof this.events[evt] == "object"){
1255                  this.events[evt].clearListeners();
1256             }
1257         }
1258     },
1259
1260     relayEvents : function(o, events){
1261         var createHandler = function(ename){
1262             return function(){
1263                 return this.fireEvent.apply(this, Ext.combine(ename, Array.prototype.slice.call(arguments, 0)));
1264             };
1265         };
1266         for(var i = 0, len = events.length; i < len; i++){
1267             var ename = events[i];
1268             if(!this.events[ename]){ this.events[ename] = true; };
1269             o.on(ename, createHandler(ename), this);
1270         }
1271     },
1272
1273     
1274     addEvents : function(o){
1275         if(!this.events){
1276             this.events = {};
1277         }
1278         if(typeof o == 'string'){
1279             for(var i = 0, a = arguments, v; v = a[i]; i++){
1280                 if(!this.events[a[i]]){
1281                     o[a[i]] = true;
1282                 }
1283             }
1284         }else{
1285             Ext.applyIf(this.events, o);
1286         }
1287     },
1288
1289     
1290     hasListener : function(eventName){
1291         var e = this.events[eventName];
1292         return typeof e == "object" && e.listeners.length > 0;
1293     },
1294
1295     
1296     suspendEvents : function(){
1297         this.eventsSuspended = true;
1298     },
1299
1300     
1301     resumeEvents : function(){
1302         this.eventsSuspended = false;
1303     },
1304
1305                 getMethodEvent : function(method){
1306         if(!this.methodEvents){
1307             this.methodEvents = {};
1308         }
1309         var e = this.methodEvents[method];
1310         if(!e){
1311             e = {};
1312             this.methodEvents[method] = e;
1313
1314             e.originalFn = this[method];
1315             e.methodName = method;
1316             e.before = [];
1317             e.after = [];
1318
1319
1320             var returnValue, v, cancel;
1321             var obj = this;
1322
1323             var makeCall = function(fn, scope, args){
1324                 if((v = fn.apply(scope || obj, args)) !== undefined){
1325                     if(typeof v === 'object'){
1326                         if(v.returnValue !== undefined){
1327                             returnValue = v.returnValue;
1328                         }else{
1329                             returnValue = v;
1330                         }
1331                         if(v.cancel === true){
1332                             cancel = true;
1333                         }
1334                     }else if(v === false){
1335                         cancel = true;
1336                     }else {
1337                         returnValue = v;
1338                     }
1339                 }
1340             }
1341
1342             this[method] = function(){
1343                 returnValue = v = undefined; cancel = false;
1344                 var args = Array.prototype.slice.call(arguments, 0);
1345                 for(var i = 0, len = e.before.length; i < len; i++){
1346                     makeCall(e.before[i].fn, e.before[i].scope, args);
1347                     if(cancel){
1348                         return returnValue;
1349                     }
1350                 }
1351
1352                 if((v = e.originalFn.apply(obj, args)) !== undefined){
1353                     returnValue = v;
1354                 }
1355
1356                 for(var i = 0, len = e.after.length; i < len; i++){
1357                     makeCall(e.after[i].fn, e.after[i].scope, args);
1358                     if(cancel){
1359                         return returnValue;
1360                     }
1361                 }
1362                 return returnValue;
1363             };
1364         }
1365         return e;
1366     },
1367
1368         beforeMethod : function(method, fn, scope){
1369         var e = this.getMethodEvent(method);
1370         e.before.push({fn: fn, scope: scope});
1371     },
1372
1373         afterMethod : function(method, fn, scope){
1374         var e = this.getMethodEvent(method);
1375         e.after.push({fn: fn, scope: scope});
1376     },
1377
1378     removeMethodListener : function(method, fn, scope){
1379         var e = this.getMethodEvent(method);
1380         for(var i = 0, len = e.before.length; i < len; i++){
1381             if(e.before[i].fn == fn && e.before[i].scope == scope){
1382                 e.before.splice(i, 1);
1383                 return;
1384             }
1385         }
1386         for(var i = 0, len = e.after.length; i < len; i++){
1387             if(e.after[i].fn == fn && e.after[i].scope == scope){
1388                 e.after.splice(i, 1);
1389                 return;
1390             }
1391         }
1392     }
1393 };
1394
1395 Ext.util.Observable.prototype.on = Ext.util.Observable.prototype.addListener;
1396
1397 Ext.util.Observable.prototype.un = Ext.util.Observable.prototype.removeListener;
1398
1399
1400 Ext.util.Observable.capture = function(o, fn, scope){
1401     o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
1402 };
1403
1404
1405 Ext.util.Observable.releaseCapture = function(o){
1406     o.fireEvent = Ext.util.Observable.prototype.fireEvent;
1407 };
1408
1409 (function(){
1410
1411     var createBuffered = function(h, o, scope){
1412         var task = new Ext.util.DelayedTask();
1413         return function(){
1414             task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
1415         };
1416     };
1417
1418     var createSingle = function(h, e, fn, scope){
1419         return function(){
1420             e.removeListener(fn, scope);
1421             return h.apply(scope, arguments);
1422         };
1423     };
1424
1425     var createDelayed = function(h, o, scope){
1426         return function(){
1427             var args = Array.prototype.slice.call(arguments, 0);
1428             setTimeout(function(){
1429                 h.apply(scope, args);
1430             }, o.delay || 10);
1431         };
1432     };
1433
1434     Ext.util.Event = function(obj, name){
1435         this.name = name;
1436         this.obj = obj;
1437         this.listeners = [];
1438     };
1439
1440     Ext.util.Event.prototype = {
1441         addListener : function(fn, scope, options){
1442             scope = scope || this.obj;
1443             if(!this.isListening(fn, scope)){
1444                 var l = this.createListener(fn, scope, options);
1445                 if(!this.firing){
1446                     this.listeners.push(l);
1447                 }else{                     this.listeners = this.listeners.slice(0);
1448                     this.listeners.push(l);
1449                 }
1450             }
1451         },
1452
1453         createListener : function(fn, scope, o){
1454             o = o || {};
1455             scope = scope || this.obj;
1456             var l = {fn: fn, scope: scope, options: o};
1457             var h = fn;
1458             if(o.delay){
1459                 h = createDelayed(h, o, scope);
1460             }
1461             if(o.single){
1462                 h = createSingle(h, this, fn, scope);
1463             }
1464             if(o.buffer){
1465                 h = createBuffered(h, o, scope);
1466             }
1467             l.fireFn = h;
1468             return l;
1469         },
1470
1471         findListener : function(fn, scope){
1472             scope = scope || this.obj;
1473             var ls = this.listeners;
1474             for(var i = 0, len = ls.length; i < len; i++){
1475                 var l = ls[i];
1476                 if(l.fn == fn && l.scope == scope){
1477                     return i;
1478                 }
1479             }
1480             return -1;
1481         },
1482
1483         isListening : function(fn, scope){
1484             return this.findListener(fn, scope) != -1;
1485         },
1486
1487         removeListener : function(fn, scope){
1488             var index;
1489             if((index = this.findListener(fn, scope)) != -1){
1490                 if(!this.firing){
1491                     this.listeners.splice(index, 1);
1492                 }else{
1493                     this.listeners = this.listeners.slice(0);
1494                     this.listeners.splice(index, 1);
1495                 }
1496                 return true;
1497             }
1498             return false;
1499         },
1500
1501         clearListeners : function(){
1502             this.listeners = [];
1503         },
1504
1505         fire : function(){
1506             var ls = this.listeners, scope, len = ls.length;
1507             if(len > 0){
1508                 this.firing = true;
1509                 var args = Array.prototype.slice.call(arguments, 0);
1510                 for(var i = 0; i < len; i++){
1511                     var l = ls[i];
1512                     if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){
1513                         this.firing = false;
1514                         return false;
1515                     }
1516                 }
1517                 this.firing = false;
1518             }
1519             return true;
1520         }
1521     };
1522 })();
1523
1524 Ext.EventManager = function(){
1525     var docReadyEvent, docReadyProcId, docReadyState = false;
1526     var resizeEvent, resizeTask, textEvent, textSize;
1527     var E = Ext.lib.Event;
1528     var D = Ext.lib.Dom;
1529
1530
1531     var fireDocReady = function(){
1532         if(!docReadyState){
1533             docReadyState = true;
1534             Ext.isReady = true;
1535             if(docReadyProcId){
1536                 clearInterval(docReadyProcId);
1537             }
1538             if(Ext.isGecko || Ext.isOpera) {
1539                 document.removeEventListener("DOMContentLoaded", fireDocReady, false);
1540             }
1541             if(Ext.isIE){
1542                 var defer = document.getElementById("ie-deferred-loader");
1543                 if(defer){
1544                     defer.onreadystatechange = null;
1545                     defer.parentNode.removeChild(defer);
1546                 }
1547             }
1548             if(docReadyEvent){
1549                 docReadyEvent.fire();
1550                 docReadyEvent.clearListeners();
1551             }
1552         }
1553     };
1554
1555     var initDocReady = function(){
1556         docReadyEvent = new Ext.util.Event();
1557         if(Ext.isGecko || Ext.isOpera) {
1558             document.addEventListener("DOMContentLoaded", fireDocReady, false);
1559         }else if(Ext.isIE){
1560             document.write("<s"+'cript id="ie-deferred-loader" defer="defer" src="/'+'/:"></s'+"cript>");
1561             var defer = document.getElementById("ie-deferred-loader");
1562             defer.onreadystatechange = function(){
1563                 if(this.readyState == "complete"){
1564                     fireDocReady();
1565                 }
1566             };
1567         }else if(Ext.isSafari){
1568             docReadyProcId = setInterval(function(){
1569                 var rs = document.readyState;
1570                 if(rs == "complete") {
1571                     fireDocReady();
1572                  }
1573             }, 10);
1574         }
1575         
1576         E.on(window, "load", fireDocReady);
1577     };
1578
1579     var createBuffered = function(h, o){
1580         var task = new Ext.util.DelayedTask(h);
1581         return function(e){
1582             
1583             e = new Ext.EventObjectImpl(e);
1584             task.delay(o.buffer, h, null, [e]);
1585         };
1586     };
1587
1588     var createSingle = function(h, el, ename, fn){
1589         return function(e){
1590             Ext.EventManager.removeListener(el, ename, fn);
1591             h(e);
1592         };
1593     };
1594
1595     var createDelayed = function(h, o){
1596         return function(e){
1597             
1598             e = new Ext.EventObjectImpl(e);
1599             setTimeout(function(){
1600                 h(e);
1601             }, o.delay || 10);
1602         };
1603     };
1604
1605     var listen = function(element, ename, opt, fn, scope){
1606         var o = (!opt || typeof opt == "boolean") ? {} : opt;
1607         fn = fn || o.fn; scope = scope || o.scope;
1608         var el = Ext.getDom(element);
1609         if(!el){
1610             throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
1611         }
1612         var h = function(e){
1613             e = Ext.EventObject.setEvent(e);
1614             var t;
1615             if(o.delegate){
1616                 t = e.getTarget(o.delegate, el);
1617                 if(!t){
1618                     return;
1619                 }
1620             }else{
1621                 t = e.target;
1622             }
1623             if(o.stopEvent === true){
1624                 e.stopEvent();
1625             }
1626             if(o.preventDefault === true){
1627                e.preventDefault();
1628             }
1629             if(o.stopPropagation === true){
1630                 e.stopPropagation();
1631             }
1632
1633             if(o.normalized === false){
1634                 e = e.browserEvent;
1635             }
1636
1637             fn.call(scope || el, e, t, o);
1638         };
1639         if(o.delay){
1640             h = createDelayed(h, o);
1641         }
1642         if(o.single){
1643             h = createSingle(h, el, ename, fn);
1644         }
1645         if(o.buffer){
1646             h = createBuffered(h, o);
1647         }
1648         fn._handlers = fn._handlers || [];
1649         fn._handlers.push([Ext.id(el), ename, h]);
1650
1651         E.on(el, ename, h);
1652         if(ename == "mousewheel" && el.addEventListener){ 
1653             el.addEventListener("DOMMouseScroll", h, false);
1654             E.on(window, 'unload', function(){
1655                 el.removeEventListener("DOMMouseScroll", h, false);
1656             });
1657         }
1658         if(ename == "mousedown" && el == document){ 
1659             Ext.EventManager.stoppedMouseDownEvent.addListener(h);
1660         }
1661         return h;
1662     };
1663
1664     var stopListening = function(el, ename, fn){
1665         var id = Ext.id(el), hds = fn._handlers, hd = fn;
1666         if(hds){
1667             for(var i = 0, len = hds.length; i < len; i++){
1668                 var h = hds[i];
1669                 if(h[0] == id && h[1] == ename){
1670                     hd = h[2];
1671                     hds.splice(i, 1);
1672                     break;
1673                 }
1674             }
1675         }
1676         E.un(el, ename, hd);
1677         el = Ext.getDom(el);
1678         if(ename == "mousewheel" && el.addEventListener){
1679             el.removeEventListener("DOMMouseScroll", hd, false);
1680         }
1681         if(ename == "mousedown" && el == document){ 
1682             Ext.EventManager.stoppedMouseDownEvent.removeListener(hd);
1683         }
1684     };
1685
1686     var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
1687     var pub = {
1688
1689     
1690         addListener : function(element, eventName, fn, scope, options){
1691             if(typeof eventName == "object"){
1692                 var o = eventName;
1693                 for(var e in o){
1694                     if(propRe.test(e)){
1695                         continue;
1696                     }
1697                     if(typeof o[e] == "function"){
1698                         
1699                         listen(element, e, o, o[e], o.scope);
1700                     }else{
1701                         
1702                         listen(element, e, o[e]);
1703                     }
1704                 }
1705                 return;
1706             }
1707             return listen(element, eventName, options, fn, scope);
1708         },
1709
1710         
1711         removeListener : function(element, eventName, fn){
1712             return stopListening(element, eventName, fn);
1713         },
1714
1715         
1716         onDocumentReady : function(fn, scope, options){
1717             if(docReadyState){ 
1718                 docReadyEvent.addListener(fn, scope, options);
1719                 docReadyEvent.fire();
1720                 docReadyEvent.clearListeners();
1721                 return;
1722             }
1723             if(!docReadyEvent){
1724                 initDocReady();
1725             }
1726             docReadyEvent.addListener(fn, scope, options);
1727         },
1728
1729         
1730         onWindowResize : function(fn, scope, options){
1731             if(!resizeEvent){
1732                 resizeEvent = new Ext.util.Event();
1733                 resizeTask = new Ext.util.DelayedTask(function(){
1734                     resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
1735                 });
1736                 E.on(window, "resize", this.fireWindowResize, this);
1737             }
1738             resizeEvent.addListener(fn, scope, options);
1739         },
1740
1741         
1742         fireWindowResize : function(){
1743             if(resizeEvent){
1744                 if((Ext.isIE||Ext.isAir) && resizeTask){
1745                     resizeTask.delay(50);
1746                 }else{
1747                     resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
1748                 }
1749             }
1750         },
1751
1752         
1753         onTextResize : function(fn, scope, options){
1754             if(!textEvent){
1755                 textEvent = new Ext.util.Event();
1756                 var textEl = new Ext.Element(document.createElement('div'));
1757                 textEl.dom.className = 'x-text-resize';
1758                 textEl.dom.innerHTML = 'X';
1759                 textEl.appendTo(document.body);
1760                 textSize = textEl.dom.offsetHeight;
1761                 setInterval(function(){
1762                     if(textEl.dom.offsetHeight != textSize){
1763                         textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
1764                     }
1765                 }, this.textResizeInterval);
1766             }
1767             textEvent.addListener(fn, scope, options);
1768         },
1769
1770         
1771         removeResizeListener : function(fn, scope){
1772             if(resizeEvent){
1773                 resizeEvent.removeListener(fn, scope);
1774             }
1775         },
1776
1777         
1778         fireResize : function(){
1779             if(resizeEvent){
1780                 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
1781             }
1782         },
1783         
1784         ieDeferSrc : false,
1785         
1786         textResizeInterval : 50
1787     };
1788      
1789     pub.on = pub.addListener;
1790     
1791     pub.un = pub.removeListener;
1792
1793     pub.stoppedMouseDownEvent = new Ext.util.Event();
1794     return pub;
1795 }();
1796
1797 Ext.onReady = Ext.EventManager.onDocumentReady;
1798
1799 Ext.onReady(function(){
1800     var bd = Ext.getBody();
1801     if(!bd){ return; }
1802
1803     var cls = [
1804             Ext.isIE ? "ext-ie " + (Ext.isIE6 ? 'ext-ie6' : 'ext-ie7')
1805             : Ext.isGecko ? "ext-gecko"
1806             : Ext.isOpera ? "ext-opera"
1807             : Ext.isSafari ? "ext-safari" : ""];
1808
1809     if(Ext.isMac){
1810         cls.push("ext-mac");
1811     }
1812     if(Ext.isLinux){
1813         cls.push("ext-linux");
1814     }
1815     if(Ext.isBorderBox){
1816         cls.push('ext-border-box');
1817     }
1818     if(Ext.isStrict){ 
1819         var p = bd.dom.parentNode;
1820         if(p){
1821             p.className += ' ext-strict';
1822         }
1823     }
1824     bd.addClass(cls.join(' '));
1825 });
1826
1827
1828 Ext.EventObject = function(){
1829
1830     var E = Ext.lib.Event;
1831
1832     
1833     var safariKeys = {
1834         63234 : 37, 
1835         63235 : 39, 
1836         63232 : 38, 
1837         63233 : 40, 
1838         63276 : 33, 
1839         63277 : 34, 
1840         63272 : 46, 
1841         63273 : 36, 
1842         63275 : 35  
1843     };
1844
1845     
1846     var btnMap = Ext.isIE ? {1:0,4:1,2:2} :
1847                 (Ext.isSafari ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
1848
1849     Ext.EventObjectImpl = function(e){
1850         if(e){
1851             this.setEvent(e.browserEvent || e);
1852         }
1853     };
1854     Ext.EventObjectImpl.prototype = {
1855         
1856         browserEvent : null,
1857         
1858         button : -1,
1859         
1860         shiftKey : false,
1861         
1862         ctrlKey : false,
1863         
1864         altKey : false,
1865
1866         
1867         BACKSPACE : 8,
1868         
1869         TAB : 9,
1870         
1871         RETURN : 13,
1872         
1873         ENTER : 13,
1874         
1875         SHIFT : 16,
1876         
1877         CONTROL : 17,
1878         
1879         ESC : 27,
1880         
1881         SPACE : 32,
1882         
1883         PAGEUP : 33,
1884         
1885         PAGEDOWN : 34,
1886         
1887         END : 35,
1888         
1889         HOME : 36,
1890         
1891         LEFT : 37,
1892         
1893         UP : 38,
1894         
1895         RIGHT : 39,
1896         
1897         DOWN : 40,
1898         
1899         DELETE : 46,
1900         
1901         F5 : 116,
1902
1903            
1904         setEvent : function(e){
1905             if(e == this || (e && e.browserEvent)){ 
1906                 return e;
1907             }
1908             this.browserEvent = e;
1909             if(e){
1910                 
1911                 this.button = e.button ? btnMap[e.button] : (e.which ? e.which-1 : -1);
1912                 if(e.type == 'click' && this.button == -1){
1913                     this.button = 0;
1914                 }
1915                 this.type = e.type;
1916                 this.shiftKey = e.shiftKey;
1917                 
1918                 this.ctrlKey = e.ctrlKey || e.metaKey;
1919                 this.altKey = e.altKey;
1920                 
1921                 this.keyCode = e.keyCode;
1922                 this.charCode = e.charCode;
1923                 
1924                 this.target = E.getTarget(e);
1925                 
1926                 this.xy = E.getXY(e);
1927             }else{
1928                 this.button = -1;
1929                 this.shiftKey = false;
1930                 this.ctrlKey = false;
1931                 this.altKey = false;
1932                 this.keyCode = 0;
1933                 this.charCode =0;
1934                 this.target = null;
1935                 this.xy = [0, 0];
1936             }
1937             return this;
1938         },
1939
1940         
1941         stopEvent : function(){
1942             if(this.browserEvent){
1943                 if(this.browserEvent.type == 'mousedown'){
1944                     Ext.EventManager.stoppedMouseDownEvent.fire(this);
1945                 }
1946                 E.stopEvent(this.browserEvent);
1947             }
1948         },
1949
1950         
1951         preventDefault : function(){
1952             if(this.browserEvent){
1953                 E.preventDefault(this.browserEvent);
1954             }
1955         },
1956
1957         
1958         isNavKeyPress : function(){
1959             var k = this.keyCode;
1960             k = Ext.isSafari ? (safariKeys[k] || k) : k;
1961             return (k >= 33 && k <= 40) || k == this.RETURN || k == this.TAB || k == this.ESC;
1962         },
1963
1964         isSpecialKey : function(){
1965             var k = this.keyCode;
1966             return (this.type == 'keypress' && this.ctrlKey) || k == 9 || k == 13  || k == 40 || k == 27 ||
1967             (k == 16) || (k == 17) ||
1968             (k >= 18 && k <= 20) ||
1969             (k >= 33 && k <= 35) ||
1970             (k >= 36 && k <= 39) ||
1971             (k >= 44 && k <= 45);
1972         },
1973         
1974         stopPropagation : function(){
1975             if(this.browserEvent){
1976                 if(this.browserEvent.type == 'mousedown'){
1977                     Ext.EventManager.stoppedMouseDownEvent.fire(this);
1978                 }
1979                 E.stopPropagation(this.browserEvent);
1980             }
1981         },
1982
1983         
1984         getCharCode : function(){
1985             return this.charCode || this.keyCode;
1986         },
1987
1988         
1989         getKey : function(){
1990             var k = this.keyCode || this.charCode;
1991             return Ext.isSafari ? (safariKeys[k] || k) : k;
1992         },
1993
1994         
1995         getPageX : function(){
1996             return this.xy[0];
1997         },
1998
1999         
2000         getPageY : function(){
2001             return this.xy[1];
2002         },
2003
2004         
2005         getTime : function(){
2006             if(this.browserEvent){
2007                 return E.getTime(this.browserEvent);
2008             }
2009             return null;
2010         },
2011
2012         
2013         getXY : function(){
2014             return this.xy;
2015         },
2016
2017         
2018         getTarget : function(selector, maxDepth, returnEl){
2019                 var t = Ext.get(this.target);
2020             return selector ? t.findParent(selector, maxDepth, returnEl) : (returnEl ? t : this.target);
2021         },
2022         
2023         
2024         getRelatedTarget : function(){
2025             if(this.browserEvent){
2026                 return E.getRelatedTarget(this.browserEvent);
2027             }
2028             return null;
2029         },
2030
2031         
2032         getWheelDelta : function(){
2033             var e = this.browserEvent;
2034             var delta = 0;
2035             if(e.wheelDelta){ 
2036                 delta = e.wheelDelta/120;
2037             }else if(e.detail){ 
2038                 delta = -e.detail/3;
2039             }
2040             return delta;
2041         },
2042
2043         
2044         hasModifier : function(){
2045             return ((this.ctrlKey || this.altKey) || this.shiftKey) ? true : false;
2046         },
2047
2048         
2049         within : function(el, related){
2050             var t = this[related ? "getRelatedTarget" : "getTarget"]();
2051             return t && Ext.fly(el).contains(t);
2052         },
2053
2054         getPoint : function(){
2055             return new Ext.lib.Point(this.xy[0], this.xy[1]);
2056         }
2057     };
2058
2059     return new Ext.EventObjectImpl();
2060 }();
2061
2062 (function(){
2063 var D = Ext.lib.Dom;
2064 var E = Ext.lib.Event;
2065 var A = Ext.lib.Anim;
2066
2067 var propCache = {};
2068 var camelRe = /(-[a-z])/gi;
2069 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
2070 var view = document.defaultView;
2071
2072 Ext.Element = function(element, forceNew){
2073     var dom = typeof element == "string" ?
2074             document.getElementById(element) : element;
2075     if(!dom){         return null;
2076     }
2077     var id = dom.id;
2078     if(forceNew !== true && id && Ext.Element.cache[id]){         return Ext.Element.cache[id];
2079     }
2080
2081     
2082     this.dom = dom;
2083
2084     
2085     this.id = id || Ext.id(dom);
2086 };
2087
2088 var El = Ext.Element;
2089
2090 El.prototype = {
2091     
2092     originalDisplay : "",
2093
2094     visibilityMode : 1,
2095     
2096     defaultUnit : "px",
2097     
2098     setVisibilityMode : function(visMode){
2099         this.visibilityMode = visMode;
2100         return this;
2101     },
2102     
2103     enableDisplayMode : function(display){
2104         this.setVisibilityMode(El.DISPLAY);
2105         if(typeof display != "undefined") this.originalDisplay = display;
2106         return this;
2107     },
2108
2109     
2110     findParent : function(simpleSelector, maxDepth, returnEl){
2111         var p = this.dom, b = document.body, depth = 0, dq = Ext.DomQuery, stopEl;
2112         maxDepth = maxDepth || 50;
2113         if(typeof maxDepth != "number"){
2114             stopEl = Ext.getDom(maxDepth);
2115             maxDepth = 10;
2116         }
2117         while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
2118             if(dq.is(p, simpleSelector)){
2119                 return returnEl ? Ext.get(p) : p;
2120             }
2121             depth++;
2122             p = p.parentNode;
2123         }
2124         return null;
2125     },
2126
2127
2128     
2129     findParentNode : function(simpleSelector, maxDepth, returnEl){
2130         var p = Ext.fly(this.dom.parentNode, '_internal');
2131         return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
2132     },
2133
2134     
2135     up : function(simpleSelector, maxDepth){
2136         return this.findParentNode(simpleSelector, maxDepth, true);
2137     },
2138
2139
2140
2141     
2142     is : function(simpleSelector){
2143         return Ext.DomQuery.is(this.dom, simpleSelector);
2144     },
2145
2146     
2147     animate : function(args, duration, onComplete, easing, animType){
2148         this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
2149         return this;
2150     },
2151
2152     
2153     anim : function(args, opt, animType, defaultDur, defaultEase, cb){
2154         animType = animType || 'run';
2155         opt = opt || {};
2156         var anim = Ext.lib.Anim[animType](
2157             this.dom, args,
2158             (opt.duration || defaultDur) || .35,
2159             (opt.easing || defaultEase) || 'easeOut',
2160             function(){
2161                 Ext.callback(cb, this);
2162                 Ext.callback(opt.callback, opt.scope || this, [this, opt]);
2163             },
2164             this
2165         );
2166         opt.anim = anim;
2167         return anim;
2168     },
2169
2170         preanim : function(a, i){
2171         return !a[i] ? false : (typeof a[i] == "object" ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
2172     },
2173
2174     
2175     clean : function(forceReclean){
2176         if(this.isCleaned && forceReclean !== true){
2177             return this;
2178         }
2179         var ns = /\S/;
2180         var d = this.dom, n = d.firstChild, ni = -1;
2181             while(n){
2182                 var nx = n.nextSibling;
2183                 if(n.nodeType == 3 && !ns.test(n.nodeValue)){
2184                     d.removeChild(n);
2185                 }else{
2186                     n.nodeIndex = ++ni;
2187                 }
2188                 n = nx;
2189             }
2190             this.isCleaned = true;
2191             return this;
2192         },
2193
2194     
2195     scrollIntoView : function(container, hscroll){
2196         var c = Ext.getDom(container) || Ext.getBody().dom;
2197         var el = this.dom;
2198
2199         var o = this.getOffsetsTo(c),
2200             l = o[0] + c.scrollLeft,
2201             t = o[1] + c.scrollTop,
2202             b = t+el.offsetHeight,
2203             r = l+el.offsetWidth;
2204
2205         var ch = c.clientHeight;
2206         var ct = parseInt(c.scrollTop, 10);
2207         var cl = parseInt(c.scrollLeft, 10);
2208         var cb = ct + ch;
2209         var cr = cl + c.clientWidth;
2210
2211         if(el.offsetHeight > ch || t < ct){
2212                 c.scrollTop = t;
2213         }else if(b > cb){
2214             c.scrollTop = b-ch;
2215         }
2216         c.scrollTop = c.scrollTop; 
2217         if(hscroll !== false){
2218                         if(el.offsetWidth > c.clientWidth || l < cl){
2219                 c.scrollLeft = l;
2220             }else if(r > cr){
2221                 c.scrollLeft = r-c.clientWidth;
2222             }
2223             c.scrollLeft = c.scrollLeft;
2224         }
2225         return this;
2226     },
2227
2228         scrollChildIntoView : function(child, hscroll){
2229         Ext.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
2230     },
2231
2232     
2233     autoHeight : function(animate, duration, onComplete, easing){
2234         var oldHeight = this.getHeight();
2235         this.clip();
2236         this.setHeight(1);         setTimeout(function(){
2237             var height = parseInt(this.dom.scrollHeight, 10);             if(!animate){
2238                 this.setHeight(height);
2239                 this.unclip();
2240                 if(typeof onComplete == "function"){
2241                     onComplete();
2242                 }
2243             }else{
2244                 this.setHeight(oldHeight);                 this.setHeight(height, animate, duration, function(){
2245                     this.unclip();
2246                     if(typeof onComplete == "function") onComplete();
2247                 }.createDelegate(this), easing);
2248             }
2249         }.createDelegate(this), 0);
2250         return this;
2251     },
2252
2253     
2254     contains : function(el){
2255         if(!el){return false;}
2256         return D.isAncestor(this.dom, el.dom ? el.dom : el);
2257     },
2258
2259     
2260     isVisible : function(deep) {
2261         var vis = !(this.getStyle("visibility") == "hidden" || this.getStyle("display") == "none");
2262         if(deep !== true || !vis){
2263             return vis;
2264         }
2265         var p = this.dom.parentNode;
2266         while(p && p.tagName.toLowerCase() != "body"){
2267             if(!Ext.fly(p, '_isVisible').isVisible()){
2268                 return false;
2269             }
2270             p = p.parentNode;
2271         }
2272         return true;
2273     },
2274
2275     
2276     select : function(selector, unique){
2277         return El.select(selector, unique, this.dom);
2278     },
2279
2280     
2281     query : function(selector, unique){
2282         return Ext.DomQuery.select(selector, this.dom);
2283     },
2284
2285     
2286     child : function(selector, returnDom){
2287         var n = Ext.DomQuery.selectNode(selector, this.dom);
2288         return returnDom ? n : Ext.get(n);
2289     },
2290
2291     
2292     down : function(selector, returnDom){
2293         var n = Ext.DomQuery.selectNode(" > " + selector, this.dom);
2294         return returnDom ? n : Ext.get(n);
2295     },
2296
2297     
2298     initDD : function(group, config, overrides){
2299         var dd = new Ext.dd.DD(Ext.id(this.dom), group, config);
2300         return Ext.apply(dd, overrides);
2301     },
2302
2303     
2304     initDDProxy : function(group, config, overrides){
2305         var dd = new Ext.dd.DDProxy(Ext.id(this.dom), group, config);
2306         return Ext.apply(dd, overrides);
2307     },
2308
2309     
2310     initDDTarget : function(group, config, overrides){
2311         var dd = new Ext.dd.DDTarget(Ext.id(this.dom), group, config);
2312         return Ext.apply(dd, overrides);
2313     },
2314
2315     
2316      setVisible : function(visible, animate){
2317         if(!animate || !A){
2318             if(this.visibilityMode == El.DISPLAY){
2319                 this.setDisplayed(visible);
2320             }else{
2321                 this.fixDisplay();
2322                 this.dom.style.visibility = visible ? "visible" : "hidden";
2323             }
2324         }else{
2325                         var dom = this.dom;
2326             var visMode = this.visibilityMode;
2327             if(visible){
2328                 this.setOpacity(.01);
2329                 this.setVisible(true);
2330             }
2331             this.anim({opacity: { to: (visible?1:0) }},
2332                   this.preanim(arguments, 1),
2333                   null, .35, 'easeIn', function(){
2334                      if(!visible){
2335                          if(visMode == El.DISPLAY){
2336                              dom.style.display = "none";
2337                          }else{
2338                              dom.style.visibility = "hidden";
2339                          }
2340                          Ext.get(dom).setOpacity(1);
2341                      }
2342                  });
2343         }
2344         return this;
2345     },
2346
2347     
2348     isDisplayed : function() {
2349         return this.getStyle("display") != "none";
2350     },
2351
2352     
2353     toggle : function(animate){
2354         this.setVisible(!this.isVisible(), this.preanim(arguments, 0));
2355         return this;
2356     },
2357
2358     
2359     setDisplayed : function(value) {
2360         if(typeof value == "boolean"){
2361            value = value ? this.originalDisplay : "none";
2362         }
2363         this.setStyle("display", value);
2364         return this;
2365     },
2366
2367     
2368     focus : function() {
2369         try{
2370             this.dom.focus();
2371         }catch(e){}
2372         return this;
2373     },
2374
2375     
2376     blur : function() {
2377         try{
2378             this.dom.blur();
2379         }catch(e){}
2380         return this;
2381     },
2382
2383     
2384     addClass : function(className){
2385         if(Ext.isArray(className)){
2386             for(var i = 0, len = className.length; i < len; i++) {
2387                 this.addClass(className[i]);
2388             }
2389         }else{
2390             if(className && !this.hasClass(className)){
2391                 this.dom.className = this.dom.className + " " + className;
2392             }
2393         }
2394         return this;
2395     },
2396
2397     
2398     radioClass : function(className){
2399         var siblings = this.dom.parentNode.childNodes;
2400         for(var i = 0; i < siblings.length; i++) {
2401                 var s = siblings[i];
2402                 if(s.nodeType == 1){
2403                     Ext.get(s).removeClass(className);
2404                 }
2405         }
2406         this.addClass(className);
2407         return this;
2408     },
2409
2410     
2411     removeClass : function(className){
2412         if(!className || !this.dom.className){
2413             return this;
2414         }
2415         if(Ext.isArray(className)){
2416             for(var i = 0, len = className.length; i < len; i++) {
2417                 this.removeClass(className[i]);
2418             }
2419         }else{
2420             if(this.hasClass(className)){
2421                 var re = this.classReCache[className];
2422                 if (!re) {
2423                    re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");
2424                    this.classReCache[className] = re;
2425                 }
2426                 this.dom.className =
2427                     this.dom.className.replace(re, " ");
2428             }
2429         }
2430         return this;
2431     },
2432
2433         classReCache: {},
2434
2435     
2436     toggleClass : function(className){
2437         if(this.hasClass(className)){
2438             this.removeClass(className);
2439         }else{
2440             this.addClass(className);
2441         }
2442         return this;
2443     },
2444
2445     
2446     hasClass : function(className){
2447         return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
2448     },
2449
2450     
2451     replaceClass : function(oldClassName, newClassName){
2452         this.removeClass(oldClassName);
2453         this.addClass(newClassName);
2454         return this;
2455     },
2456
2457     
2458     getStyles : function(){
2459         var a = arguments, len = a.length, r = {};
2460         for(var i = 0; i < len; i++){
2461             r[a[i]] = this.getStyle(a[i]);
2462         }
2463         return r;
2464     },
2465
2466     
2467     getStyle : function(){
2468         return view && view.getComputedStyle ?
2469             function(prop){
2470                 var el = this.dom, v, cs, camel;
2471                 if(prop == 'float'){
2472                     prop = "cssFloat";
2473                 }
2474                 if(v = el.style[prop]){
2475                     return v;
2476                 }
2477                 if(cs = view.getComputedStyle(el, "")){
2478                     if(!(camel = propCache[prop])){
2479                         camel = propCache[prop] = prop.replace(camelRe, camelFn);
2480                     }
2481                     return cs[camel];
2482                 }
2483                 return null;
2484             } :
2485             function(prop){
2486                 var el = this.dom, v, cs, camel;
2487                 if(prop == 'opacity'){
2488                     if(typeof el.style.filter == 'string'){
2489                         var m = el.style.filter.match(/alpha\(opacity=(.*)\)/i);
2490                         if(m){
2491                             var fv = parseFloat(m[1]);
2492                             if(!isNaN(fv)){
2493                                 return fv ? fv / 100 : 0;
2494                             }
2495                         }
2496                     }
2497                     return 1;
2498                 }else if(prop == 'float'){
2499                     prop = "styleFloat";
2500                 }
2501                 if(!(camel = propCache[prop])){
2502                     camel = propCache[prop] = prop.replace(camelRe, camelFn);
2503                 }
2504                 if(v = el.style[camel]){
2505                     return v;
2506                 }
2507                 if(cs = el.currentStyle){
2508                     return cs[camel];
2509                 }
2510                 return null;
2511             };
2512     }(),
2513
2514     
2515     setStyle : function(prop, value){
2516         if(typeof prop == "string"){
2517             var camel;
2518             if(!(camel = propCache[prop])){
2519                 camel = propCache[prop] = prop.replace(camelRe, camelFn);
2520             }
2521             if(camel == 'opacity') {
2522                 this.setOpacity(value);
2523             }else{
2524                 this.dom.style[camel] = value;
2525             }
2526         }else{
2527             for(var style in prop){
2528                 if(typeof prop[style] != "function"){
2529                    this.setStyle(style, prop[style]);
2530                 }
2531             }
2532         }
2533         return this;
2534     },
2535
2536     
2537     applyStyles : function(style){
2538         Ext.DomHelper.applyStyles(this.dom, style);
2539         return this;
2540     },
2541
2542     
2543     getX : function(){
2544         return D.getX(this.dom);
2545     },
2546
2547     
2548     getY : function(){
2549         return D.getY(this.dom);
2550     },
2551
2552     
2553     getXY : function(){
2554         return D.getXY(this.dom);
2555     },
2556
2557     
2558     getOffsetsTo : function(el){
2559         var o = this.getXY();
2560         var e = Ext.fly(el, '_internal').getXY();
2561         return [o[0]-e[0],o[1]-e[1]];
2562     },
2563
2564     
2565     setX : function(x, animate){
2566         if(!animate || !A){
2567             D.setX(this.dom, x);
2568         }else{
2569             this.setXY([x, this.getY()], this.preanim(arguments, 1));
2570         }
2571         return this;
2572     },
2573
2574     
2575     setY : function(y, animate){
2576         if(!animate || !A){
2577             D.setY(this.dom, y);
2578         }else{
2579             this.setXY([this.getX(), y], this.preanim(arguments, 1));
2580         }
2581         return this;
2582     },
2583
2584     
2585     setLeft : function(left){
2586         this.setStyle("left", this.addUnits(left));
2587         return this;
2588     },
2589
2590     
2591     setTop : function(top){
2592         this.setStyle("top", this.addUnits(top));
2593         return this;
2594     },
2595
2596     
2597     setRight : function(right){
2598         this.setStyle("right", this.addUnits(right));
2599         return this;
2600     },
2601
2602     
2603     setBottom : function(bottom){
2604         this.setStyle("bottom", this.addUnits(bottom));
2605         return this;
2606     },
2607
2608     
2609     setXY : function(pos, animate){
2610         if(!animate || !A){
2611             D.setXY(this.dom, pos);
2612         }else{
2613             this.anim({points: {to: pos}}, this.preanim(arguments, 1), 'motion');
2614         }
2615         return this;
2616     },
2617
2618     
2619     setLocation : function(x, y, animate){
2620         this.setXY([x, y], this.preanim(arguments, 2));
2621         return this;
2622     },
2623
2624     
2625     moveTo : function(x, y, animate){
2626         this.setXY([x, y], this.preanim(arguments, 2));
2627         return this;
2628     },
2629
2630     
2631     getRegion : function(){
2632         return D.getRegion(this.dom);
2633     },
2634
2635     
2636     getHeight : function(contentHeight){
2637         var h = this.dom.offsetHeight || 0;
2638         h = contentHeight !== true ? h : h-this.getBorderWidth("tb")-this.getPadding("tb");
2639         return h < 0 ? 0 : h;
2640     },
2641
2642     
2643     getWidth : function(contentWidth){
2644         var w = this.dom.offsetWidth || 0;
2645         w = contentWidth !== true ? w : w-this.getBorderWidth("lr")-this.getPadding("lr");
2646         return w < 0 ? 0 : w;
2647     },
2648
2649     
2650     getComputedHeight : function(){
2651         var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);
2652         if(!h){
2653             h = parseInt(this.getStyle('height'), 10) || 0;
2654             if(!this.isBorderBox()){
2655                 h += this.getFrameWidth('tb');
2656             }
2657         }
2658         return h;
2659     },
2660
2661     
2662     getComputedWidth : function(){
2663         var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
2664         if(!w){
2665             w = parseInt(this.getStyle('width'), 10) || 0;
2666             if(!this.isBorderBox()){
2667                 w += this.getFrameWidth('lr');
2668             }
2669         }
2670         return w;
2671     },
2672
2673     
2674     getSize : function(contentSize){
2675         return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
2676     },
2677
2678     getStyleSize : function(){
2679         var w, h, d = this.dom, s = d.style;
2680         if(s.width && s.width != 'auto'){
2681             w = parseInt(s.width, 10);
2682             if(Ext.isBorderBox){
2683                w -= this.getFrameWidth('lr');
2684             }
2685         }
2686         if(s.height && s.height != 'auto'){
2687             h = parseInt(s.height, 10);
2688             if(Ext.isBorderBox){
2689                h -= this.getFrameWidth('tb');
2690             }
2691         }
2692         return {width: w || this.getWidth(true), height: h || this.getHeight(true)};
2693
2694     },
2695
2696     
2697     getViewSize : function(){
2698         var d = this.dom, doc = document, aw = 0, ah = 0;
2699         if(d == doc || d == doc.body){
2700             return {width : D.getViewWidth(), height: D.getViewHeight()};
2701         }else{
2702             return {
2703                 width : d.clientWidth,
2704                 height: d.clientHeight
2705             };
2706         }
2707     },
2708
2709     
2710     getValue : function(asNumber){
2711         return asNumber ? parseInt(this.dom.value, 10) : this.dom.value;
2712     },
2713
2714         adjustWidth : function(width){
2715         if(typeof width == "number"){
2716             if(this.autoBoxAdjust && !this.isBorderBox()){
2717                width -= (this.getBorderWidth("lr") + this.getPadding("lr"));
2718             }
2719             if(width < 0){
2720                 width = 0;
2721             }
2722         }
2723         return width;
2724     },
2725
2726         adjustHeight : function(height){
2727         if(typeof height == "number"){
2728            if(this.autoBoxAdjust && !this.isBorderBox()){
2729                height -= (this.getBorderWidth("tb") + this.getPadding("tb"));
2730            }
2731            if(height < 0){
2732                height = 0;
2733            }
2734         }
2735         return height;
2736     },
2737
2738     
2739     setWidth : function(width, animate){
2740         width = this.adjustWidth(width);
2741         if(!animate || !A){
2742             this.dom.style.width = this.addUnits(width);
2743         }else{
2744             this.anim({width: {to: width}}, this.preanim(arguments, 1));
2745         }
2746         return this;
2747     },
2748
2749     
2750      setHeight : function(height, animate){
2751         height = this.adjustHeight(height);
2752         if(!animate || !A){
2753             this.dom.style.height = this.addUnits(height);
2754         }else{
2755             this.anim({height: {to: height}}, this.preanim(arguments, 1));
2756         }
2757         return this;
2758     },
2759
2760     
2761      setSize : function(width, height, animate){
2762         if(typeof width == "object"){             height = width.height; width = width.width;
2763         }
2764         width = this.adjustWidth(width); height = this.adjustHeight(height);
2765         if(!animate || !A){
2766             this.dom.style.width = this.addUnits(width);
2767             this.dom.style.height = this.addUnits(height);
2768         }else{
2769             this.anim({width: {to: width}, height: {to: height}}, this.preanim(arguments, 2));
2770         }
2771         return this;
2772     },
2773
2774     
2775     setBounds : function(x, y, width, height, animate){
2776         if(!animate || !A){
2777             this.setSize(width, height);
2778             this.setLocation(x, y);
2779         }else{
2780             width = this.adjustWidth(width); height = this.adjustHeight(height);
2781             this.anim({points: {to: [x, y]}, width: {to: width}, height: {to: height}},
2782                           this.preanim(arguments, 4), 'motion');
2783         }
2784         return this;
2785     },
2786
2787     
2788     setRegion : function(region, animate){
2789         this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.preanim(arguments, 1));
2790         return this;
2791     },
2792
2793     
2794     addListener : function(eventName, fn, scope, options){
2795         Ext.EventManager.on(this.dom,  eventName, fn, scope || this, options);
2796     },
2797
2798     
2799     removeListener : function(eventName, fn){
2800         Ext.EventManager.removeListener(this.dom,  eventName, fn);
2801         return this;
2802     },
2803
2804     
2805     removeAllListeners : function(){
2806         E.purgeElement(this.dom);
2807         return this;
2808     },
2809
2810     
2811     relayEvent : function(eventName, observable){
2812         this.on(eventName, function(e){
2813             observable.fireEvent(eventName, e);
2814         });
2815     },
2816
2817     
2818      setOpacity : function(opacity, animate){
2819         if(!animate || !A){
2820             var s = this.dom.style;
2821             if(Ext.isIE){
2822                 s.zoom = 1;
2823                 s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +
2824                            (opacity == 1 ? "" : " alpha(opacity=" + opacity * 100 + ")");
2825             }else{
2826                 s.opacity = opacity;
2827             }
2828         }else{
2829             this.anim({opacity: {to: opacity}}, this.preanim(arguments, 1), null, .35, 'easeIn');
2830         }
2831         return this;
2832     },
2833
2834     
2835     getLeft : function(local){
2836         if(!local){
2837             return this.getX();
2838         }else{
2839             return parseInt(this.getStyle("left"), 10) || 0;
2840         }
2841     },
2842
2843     
2844     getRight : function(local){
2845         if(!local){
2846             return this.getX() + this.getWidth();
2847         }else{
2848             return (this.getLeft(true) + this.getWidth()) || 0;
2849         }
2850     },
2851
2852     
2853     getTop : function(local) {
2854         if(!local){
2855             return this.getY();
2856         }else{
2857             return parseInt(this.getStyle("top"), 10) || 0;
2858         }
2859     },
2860
2861     
2862     getBottom : function(local){
2863         if(!local){
2864             return this.getY() + this.getHeight();
2865         }else{
2866             return (this.getTop(true) + this.getHeight()) || 0;
2867         }
2868     },
2869
2870     
2871     position : function(pos, zIndex, x, y){
2872         if(!pos){
2873            if(this.getStyle('position') == 'static'){
2874                this.setStyle('position', 'relative');
2875            }
2876         }else{
2877             this.setStyle("position", pos);
2878         }
2879         if(zIndex){
2880             this.setStyle("z-index", zIndex);
2881         }
2882         if(x !== undefined && y !== undefined){
2883             this.setXY([x, y]);
2884         }else if(x !== undefined){
2885             this.setX(x);
2886         }else if(y !== undefined){
2887             this.setY(y);
2888         }
2889     },
2890
2891     
2892     clearPositioning : function(value){
2893         value = value ||'';
2894         this.setStyle({
2895             "left": value,
2896             "right": value,
2897             "top": value,
2898             "bottom": value,
2899             "z-index": "",
2900             "position" : "static"
2901         });
2902         return this;
2903     },
2904
2905     
2906     getPositioning : function(){
2907         var l = this.getStyle("left");
2908         var t = this.getStyle("top");
2909         return {
2910             "position" : this.getStyle("position"),
2911             "left" : l,
2912             "right" : l ? "" : this.getStyle("right"),
2913             "top" : t,
2914             "bottom" : t ? "" : this.getStyle("bottom"),
2915             "z-index" : this.getStyle("z-index")
2916         };
2917     },
2918
2919     
2920     getBorderWidth : function(side){
2921         return this.addStyles(side, El.borders);
2922     },
2923
2924     
2925     getPadding : function(side){
2926         return this.addStyles(side, El.paddings);
2927     },
2928
2929     
2930     setPositioning : function(pc){
2931         this.applyStyles(pc);
2932         if(pc.right == "auto"){
2933             this.dom.style.right = "";
2934         }
2935         if(pc.bottom == "auto"){
2936             this.dom.style.bottom = "";
2937         }
2938         return this;
2939     },
2940
2941         fixDisplay : function(){
2942         if(this.getStyle("display") == "none"){
2943             this.setStyle("visibility", "hidden");
2944             this.setStyle("display", this.originalDisplay);             if(this.getStyle("display") == "none"){                 this.setStyle("display", "block");
2945             }
2946         }
2947     },
2948
2949         setOverflow : function(v){
2950         if(v=='auto' && Ext.isMac && Ext.isGecko){              this.dom.style.overflow = 'hidden';
2951                 (function(){this.dom.style.overflow = 'auto';}).defer(1, this);
2952         }else{
2953                 this.dom.style.overflow = v;
2954         }
2955         },
2956         
2957     
2958      setLeftTop : function(left, top){
2959         this.dom.style.left = this.addUnits(left);
2960         this.dom.style.top = this.addUnits(top);
2961         return this;
2962     },
2963
2964     
2965      move : function(direction, distance, animate){
2966         var xy = this.getXY();
2967         direction = direction.toLowerCase();
2968         switch(direction){
2969             case "l":
2970             case "left":
2971                 this.moveTo(xy[0]-distance, xy[1], this.preanim(arguments, 2));
2972                 break;
2973            case "r":
2974            case "right":
2975                 this.moveTo(xy[0]+distance, xy[1], this.preanim(arguments, 2));
2976                 break;
2977            case "t":
2978            case "top":
2979            case "up":
2980                 this.moveTo(xy[0], xy[1]-distance, this.preanim(arguments, 2));
2981                 break;
2982            case "b":
2983            case "bottom":
2984            case "down":
2985                 this.moveTo(xy[0], xy[1]+distance, this.preanim(arguments, 2));
2986                 break;
2987         }
2988         return this;
2989     },
2990
2991     
2992     clip : function(){
2993         if(!this.isClipped){
2994            this.isClipped = true;
2995            this.originalClip = {
2996                "o": this.getStyle("overflow"),
2997                "x": this.getStyle("overflow-x"),
2998                "y": this.getStyle("overflow-y")
2999            };
3000            this.setStyle("overflow", "hidden");
3001            this.setStyle("overflow-x", "hidden");
3002            this.setStyle("overflow-y", "hidden");
3003         }
3004         return this;
3005     },
3006
3007     
3008     unclip : function(){
3009         if(this.isClipped){
3010             this.isClipped = false;
3011             var o = this.originalClip;
3012             if(o.o){this.setStyle("overflow", o.o);}
3013             if(o.x){this.setStyle("overflow-x", o.x);}
3014             if(o.y){this.setStyle("overflow-y", o.y);}
3015         }
3016         return this;
3017     },
3018
3019
3020     
3021     getAnchorXY : function(anchor, local, s){
3022                 
3023         var w, h, vp = false;
3024         if(!s){
3025             var d = this.dom;
3026             if(d == document.body || d == document){
3027                 vp = true;
3028                 w = D.getViewWidth(); h = D.getViewHeight();
3029             }else{
3030                 w = this.getWidth(); h = this.getHeight();
3031             }
3032         }else{
3033             w = s.width;  h = s.height;
3034         }
3035         var x = 0, y = 0, r = Math.round;
3036         switch((anchor || "tl").toLowerCase()){
3037             case "c":
3038                 x = r(w*.5);
3039                 y = r(h*.5);
3040             break;
3041             case "t":
3042                 x = r(w*.5);
3043                 y = 0;
3044             break;
3045             case "l":
3046                 x = 0;
3047                 y = r(h*.5);
3048             break;
3049             case "r":
3050                 x = w;
3051                 y = r(h*.5);
3052             break;
3053             case "b":
3054                 x = r(w*.5);
3055                 y = h;
3056             break;
3057             case "tl":
3058                 x = 0;
3059                 y = 0;
3060             break;
3061             case "bl":
3062                 x = 0;
3063                 y = h;
3064             break;
3065             case "br":
3066                 x = w;
3067                 y = h;
3068             break;
3069             case "tr":
3070                 x = w;
3071                 y = 0;
3072             break;
3073         }
3074         if(local === true){
3075             return [x, y];
3076         }
3077         if(vp){
3078             var sc = this.getScroll();
3079             return [x + sc.left, y + sc.top];
3080         }
3081                 var o = this.getXY();
3082         return [x+o[0], y+o[1]];
3083     },
3084
3085     
3086     getAlignToXY : function(el, p, o){
3087         el = Ext.get(el);
3088         if(!el || !el.dom){
3089             throw "Element.alignToXY with an element that doesn't exist";
3090         }
3091         var d = this.dom;
3092         var c = false;         var p1 = "", p2 = "";
3093         o = o || [0,0];
3094
3095         if(!p){
3096             p = "tl-bl";
3097         }else if(p == "?"){
3098             p = "tl-bl?";
3099         }else if(p.indexOf("-") == -1){
3100             p = "tl-" + p;
3101         }
3102         p = p.toLowerCase();
3103         var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
3104         if(!m){
3105            throw "Element.alignTo with an invalid alignment " + p;
3106         }
3107         p1 = m[1]; p2 = m[2]; c = !!m[3];
3108
3109                         var a1 = this.getAnchorXY(p1, true);
3110         var a2 = el.getAnchorXY(p2, false);
3111
3112         var x = a2[0] - a1[0] + o[0];
3113         var y = a2[1] - a1[1] + o[1];
3114
3115         if(c){
3116                         var w = this.getWidth(), h = this.getHeight(), r = el.getRegion();
3117                         var dw = D.getViewWidth()-5, dh = D.getViewHeight()-5;
3118
3119                                                 var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);
3120            var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);
3121            var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
3122            var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
3123
3124            var doc = document;
3125            var scrollX = (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0)+5;
3126            var scrollY = (doc.documentElement.scrollTop || doc.body.scrollTop || 0)+5;
3127
3128            if((x+w) > dw + scrollX){
3129                 x = swapX ? r.left-w : dw+scrollX-w;
3130             }
3131            if(x < scrollX){
3132                x = swapX ? r.right : scrollX;
3133            }
3134            if((y+h) > dh + scrollY){
3135                 y = swapY ? r.top-h : dh+scrollY-h;
3136             }
3137            if (y < scrollY){
3138                y = swapY ? r.bottom : scrollY;
3139            }
3140         }
3141         return [x,y];
3142     },
3143
3144         getConstrainToXY : function(){
3145         var os = {top:0, left:0, bottom:0, right: 0};
3146
3147         return function(el, local, offsets, proposedXY){
3148             el = Ext.get(el);
3149             offsets = offsets ? Ext.applyIf(offsets, os) : os;
3150
3151             var vw, vh, vx = 0, vy = 0;
3152             if(el.dom == document.body || el.dom == document){
3153                 vw = Ext.lib.Dom.getViewWidth();
3154                 vh = Ext.lib.Dom.getViewHeight();
3155             }else{
3156                 vw = el.dom.clientWidth;
3157                 vh = el.dom.clientHeight;
3158                 if(!local){
3159                     var vxy = el.getXY();
3160                     vx = vxy[0];
3161                     vy = vxy[1];
3162                 }
3163             }
3164
3165             var s = el.getScroll();
3166
3167             vx += offsets.left + s.left;
3168             vy += offsets.top + s.top;
3169
3170             vw -= offsets.right;
3171             vh -= offsets.bottom;
3172
3173             var vr = vx+vw;
3174             var vb = vy+vh;
3175
3176             var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
3177             var x = xy[0], y = xy[1];
3178             var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
3179
3180                         var moved = false;
3181
3182                         if((x + w) > vr){
3183                 x = vr - w;
3184                 moved = true;
3185             }
3186             if((y + h) > vb){
3187                 y = vb - h;
3188                 moved = true;
3189             }
3190                         if(x < vx){
3191                 x = vx;
3192                 moved = true;
3193             }
3194             if(y < vy){
3195                 y = vy;
3196                 moved = true;
3197             }
3198             return moved ? [x, y] : false;
3199         };
3200     }(),
3201
3202         adjustForConstraints : function(xy, parent, offsets){
3203         return this.getConstrainToXY(parent || document, false, offsets, xy) ||  xy;
3204     },
3205
3206     
3207     alignTo : function(element, position, offsets, animate){
3208         var xy = this.getAlignToXY(element, position, offsets);
3209         this.setXY(xy, this.preanim(arguments, 3));
3210         return this;
3211     },
3212
3213     
3214     anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
3215         var action = function(){
3216             this.alignTo(el, alignment, offsets, animate);
3217             Ext.callback(callback, this);
3218         };
3219         Ext.EventManager.onWindowResize(action, this);
3220         var tm = typeof monitorScroll;
3221         if(tm != 'undefined'){
3222             Ext.EventManager.on(window, 'scroll', action, this,
3223                 {buffer: tm == 'number' ? monitorScroll : 50});
3224         }
3225         action.call(this);         return this;
3226     },
3227     
3228     clearOpacity : function(){
3229         if (window.ActiveXObject) {
3230             if(typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)){
3231                 this.dom.style.filter = "";
3232             }
3233         } else {
3234             this.dom.style.opacity = "";
3235             this.dom.style["-moz-opacity"] = "";
3236             this.dom.style["-khtml-opacity"] = "";
3237         }
3238         return this;
3239     },
3240
3241     
3242     hide : function(animate){
3243         this.setVisible(false, this.preanim(arguments, 0));
3244         return this;
3245     },
3246
3247     
3248     show : function(animate){
3249         this.setVisible(true, this.preanim(arguments, 0));
3250         return this;
3251     },
3252
3253     
3254     addUnits : function(size){
3255         return Ext.Element.addUnits(size, this.defaultUnit);
3256     },
3257
3258     
3259     update : function(html, loadScripts, callback){
3260         if(typeof html == "undefined"){
3261             html = "";
3262         }
3263         if(loadScripts !== true){
3264             this.dom.innerHTML = html;
3265             if(typeof callback == "function"){
3266                 callback();
3267             }
3268             return this;
3269         }
3270         var id = Ext.id();
3271         var dom = this.dom;
3272
3273         html += '<span id="' + id + '"></span>';
3274
3275         E.onAvailable(id, function(){
3276             var hd = document.getElementsByTagName("head")[0];
3277             var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
3278             var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
3279             var typeRe = /\stype=([\'\"])(.*?)\1/i;
3280
3281             var match;
3282             while(match = re.exec(html)){
3283                 var attrs = match[1];
3284                 var srcMatch = attrs ? attrs.match(srcRe) : false;
3285                 if(srcMatch && srcMatch[2]){
3286                    var s = document.createElement("script");
3287                    s.src = srcMatch[2];
3288                    var typeMatch = attrs.match(typeRe);
3289                    if(typeMatch && typeMatch[2]){
3290                        s.type = typeMatch[2];
3291                    }
3292                    hd.appendChild(s);
3293                 }else if(match[2] && match[2].length > 0){
3294                     if(window.execScript) {
3295                        window.execScript(match[2]);
3296                     } else {
3297                        window.eval(match[2]);
3298                     }
3299                 }
3300             }
3301             var el = document.getElementById(id);
3302             if(el){Ext.removeNode(el);}
3303             if(typeof callback == "function"){
3304                 callback();
3305             }
3306         });
3307         dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
3308         return this;
3309     },
3310
3311     
3312     load : function(){
3313         var um = this.getUpdater();
3314         um.update.apply(um, arguments);
3315         return this;
3316     },
3317
3318     
3319     getUpdater : function(){
3320         if(!this.updateManager){
3321             this.updateManager = new Ext.Updater(this);
3322         }
3323         return this.updateManager;
3324     },
3325
3326     
3327     unselectable : function(){
3328         this.dom.unselectable = "on";
3329         this.swallowEvent("selectstart", true);
3330         this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
3331         this.addClass("x-unselectable");
3332         return this;
3333     },
3334
3335     
3336     getCenterXY : function(){
3337         return this.getAlignToXY(document, 'c-c');
3338     },
3339
3340     
3341     center : function(centerIn){
3342         this.alignTo(centerIn || document, 'c-c');
3343         return this;
3344     },
3345
3346     
3347     isBorderBox : function(){
3348         return noBoxAdjust[this.dom.tagName.toLowerCase()] || Ext.isBorderBox;
3349     },
3350
3351     
3352     getBox : function(contentBox, local){
3353         var xy;
3354         if(!local){
3355             xy = this.getXY();
3356         }else{
3357             var left = parseInt(this.getStyle("left"), 10) || 0;
3358             var top = parseInt(this.getStyle("top"), 10) || 0;
3359             xy = [left, top];
3360         }
3361         var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
3362         if(!contentBox){
3363             bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
3364         }else{
3365             var l = this.getBorderWidth("l")+this.getPadding("l");
3366             var r = this.getBorderWidth("r")+this.getPadding("r");
3367             var t = this.getBorderWidth("t")+this.getPadding("t");
3368             var b = this.getBorderWidth("b")+this.getPadding("b");
3369             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)};
3370         }
3371         bx.right = bx.x + bx.width;
3372         bx.bottom = bx.y + bx.height;
3373         return bx;
3374     },
3375
3376     
3377     getFrameWidth : function(sides, onlyContentBox){
3378         return onlyContentBox && Ext.isBorderBox ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
3379     },
3380
3381     
3382     setBox : function(box, adjust, animate){
3383         var w = box.width, h = box.height;
3384         if((adjust && !this.autoBoxAdjust) && !this.isBorderBox()){
3385            w -= (this.getBorderWidth("lr") + this.getPadding("lr"));
3386            h -= (this.getBorderWidth("tb") + this.getPadding("tb"));
3387         }
3388         this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));
3389         return this;
3390     },
3391
3392     
3393      repaint : function(){
3394         var dom = this.dom;
3395         this.addClass("x-repaint");
3396         setTimeout(function(){
3397             Ext.get(dom).removeClass("x-repaint");
3398         }, 1);
3399         return this;
3400     },
3401
3402     
3403     getMargins : function(side){
3404         if(!side){
3405             return {
3406                 top: parseInt(this.getStyle("margin-top"), 10) || 0,
3407                 left: parseInt(this.getStyle("margin-left"), 10) || 0,
3408                 bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,
3409                 right: parseInt(this.getStyle("margin-right"), 10) || 0
3410             };
3411         }else{
3412             return this.addStyles(side, El.margins);
3413          }
3414     },
3415
3416         addStyles : function(sides, styles){
3417         var val = 0, v, w;
3418         for(var i = 0, len = sides.length; i < len; i++){
3419             v = this.getStyle(styles[sides.charAt(i)]);
3420             if(v){
3421                  w = parseInt(v, 10);
3422                  if(w){ val += (w >= 0 ? w : -1 * w); }
3423             }
3424         }
3425         return val;
3426     },
3427
3428     
3429     createProxy : function(config, renderTo, matchBox){
3430         config = typeof config == "object" ?
3431             config : {tag : "div", cls: config};
3432
3433         var proxy;
3434         if(renderTo){
3435             proxy = Ext.DomHelper.append(renderTo, config, true);
3436         }else {
3437             proxy = Ext.DomHelper.insertBefore(this.dom, config, true);
3438         }
3439         if(matchBox){
3440            proxy.setBox(this.getBox());
3441         }
3442         return proxy;
3443     },
3444
3445     
3446     mask : function(msg, msgCls){
3447         if(this.getStyle("position") == "static"){
3448             this.setStyle("position", "relative");
3449         }
3450         if(this._maskMsg){
3451             this._maskMsg.remove();
3452         }
3453         if(this._mask){
3454             this._mask.remove();
3455         }
3456
3457         this._mask = Ext.DomHelper.append(this.dom, {cls:"ext-el-mask"}, true);
3458
3459         this.addClass("x-masked");
3460         this._mask.setDisplayed(true);
3461         if(typeof msg == 'string'){
3462             this._maskMsg = Ext.DomHelper.append(this.dom, {cls:"ext-el-mask-msg", cn:{tag:'div'}}, true);
3463             var mm = this._maskMsg;
3464             mm.dom.className = msgCls ? "ext-el-mask-msg " + msgCls : "ext-el-mask-msg";
3465             mm.dom.firstChild.innerHTML = msg;
3466             mm.setDisplayed(true);
3467             mm.center(this);
3468         }
3469         if(Ext.isIE && !(Ext.isIE7 && Ext.isStrict) && this.getStyle('height') == 'auto'){             this._mask.setSize(this.dom.clientWidth, this.getHeight());
3470         }
3471         return this._mask;
3472     },
3473
3474     
3475     unmask : function(){
3476         if(this._mask){
3477             if(this._maskMsg){
3478                 this._maskMsg.remove();
3479                 delete this._maskMsg;
3480             }
3481             this._mask.remove();
3482             delete this._mask;
3483         }
3484         this.removeClass("x-masked");
3485     },
3486
3487     
3488     isMasked : function(){
3489         return this._mask && this._mask.isVisible();
3490     },
3491
3492     
3493     createShim : function(){
3494         var el = document.createElement('iframe');
3495         el.frameBorder = 'no';
3496         el.className = 'ext-shim';
3497         if(Ext.isIE && Ext.isSecure){
3498             el.src = Ext.SSL_SECURE_URL;
3499         }
3500         var shim = Ext.get(this.dom.parentNode.insertBefore(el, this.dom));
3501         shim.autoBoxAdjust = false;
3502         return shim;
3503     },
3504
3505     
3506     remove : function(){
3507         Ext.removeNode(this.dom);
3508         delete El.cache[this.dom.id];
3509     },
3510
3511     
3512     hover : function(overFn, outFn, scope){
3513         var preOverFn = function(e){
3514             if(!e.within(this, true)){
3515                 overFn.apply(scope || this, arguments);
3516             }
3517         };
3518         var preOutFn = function(e){
3519             if(!e.within(this, true)){
3520                 outFn.apply(scope || this, arguments);
3521             }
3522         };
3523         this.on("mouseover", preOverFn, this.dom);
3524         this.on("mouseout", preOutFn, this.dom);
3525         return this;
3526     },
3527
3528     
3529     addClassOnOver : function(className, preventFlicker){
3530         this.hover(
3531             function(){
3532                 Ext.fly(this, '_internal').addClass(className);
3533             },
3534             function(){
3535                 Ext.fly(this, '_internal').removeClass(className);
3536             }
3537         );
3538         return this;
3539     },
3540
3541     
3542     addClassOnFocus : function(className){
3543         this.on("focus", function(){
3544             Ext.fly(this, '_internal').addClass(className);
3545         }, this.dom);
3546         this.on("blur", function(){
3547             Ext.fly(this, '_internal').removeClass(className);
3548         }, this.dom);
3549         return this;
3550     },
3551     
3552     addClassOnClick : function(className){
3553         var dom = this.dom;
3554         this.on("mousedown", function(){
3555             Ext.fly(dom, '_internal').addClass(className);
3556             var d = Ext.getDoc();
3557             var fn = function(){
3558                 Ext.fly(dom, '_internal').removeClass(className);
3559                 d.removeListener("mouseup", fn);
3560             };
3561             d.on("mouseup", fn);
3562         });
3563         return this;
3564     },
3565
3566     
3567     swallowEvent : function(eventName, preventDefault){
3568         var fn = function(e){
3569             e.stopPropagation();
3570             if(preventDefault){
3571                 e.preventDefault();
3572             }
3573         };
3574         if(Ext.isArray(eventName)){
3575             for(var i = 0, len = eventName.length; i < len; i++){
3576                  this.on(eventName[i], fn);
3577             }
3578             return this;
3579         }
3580         this.on(eventName, fn);
3581         return this;
3582     },
3583
3584     
3585     parent : function(selector, returnDom){
3586         return this.matchNode('parentNode', 'parentNode', selector, returnDom);
3587     },
3588
3589      
3590     next : function(selector, returnDom){
3591         return this.matchNode('nextSibling', 'nextSibling', selector, returnDom);
3592     },
3593
3594     
3595     prev : function(selector, returnDom){
3596         return this.matchNode('previousSibling', 'previousSibling', selector, returnDom);
3597     },
3598
3599
3600     
3601     first : function(selector, returnDom){
3602         return this.matchNode('nextSibling', 'firstChild', selector, returnDom);
3603     },
3604
3605     
3606     last : function(selector, returnDom){
3607         return this.matchNode('previousSibling', 'lastChild', selector, returnDom);
3608     },
3609
3610     matchNode : function(dir, start, selector, returnDom){
3611         var n = this.dom[start];
3612         while(n){
3613             if(n.nodeType == 1 && (!selector || Ext.DomQuery.is(n, selector))){
3614                 return !returnDom ? Ext.get(n) : n;
3615             }
3616             n = n[dir];
3617         }
3618         return null;
3619     },
3620
3621     
3622     appendChild: function(el){
3623         el = Ext.get(el);
3624         el.appendTo(this);
3625         return this;
3626     },
3627
3628     
3629     createChild: function(config, insertBefore, returnDom){
3630         config = config || {tag:'div'};
3631         if(insertBefore){
3632             return Ext.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
3633         }
3634         return Ext.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config,  returnDom !== true);
3635     },
3636
3637     
3638     appendTo: function(el){
3639         el = Ext.getDom(el);
3640         el.appendChild(this.dom);
3641         return this;
3642     },
3643
3644     
3645     insertBefore: function(el){
3646         el = Ext.getDom(el);
3647         el.parentNode.insertBefore(this.dom, el);
3648         return this;
3649     },
3650
3651     
3652     insertAfter: function(el){
3653         el = Ext.getDom(el);
3654         el.parentNode.insertBefore(this.dom, el.nextSibling);
3655         return this;
3656     },
3657
3658     
3659     insertFirst: function(el, returnDom){
3660         el = el || {};
3661         if(typeof el == 'object' && !el.nodeType && !el.dom){             return this.createChild(el, this.dom.firstChild, returnDom);
3662         }else{
3663             el = Ext.getDom(el);
3664             this.dom.insertBefore(el, this.dom.firstChild);
3665             return !returnDom ? Ext.get(el) : el;
3666         }
3667     },
3668
3669     
3670     insertSibling: function(el, where, returnDom){
3671         var rt;
3672         if(Ext.isArray(el)){
3673             for(var i = 0, len = el.length; i < len; i++){
3674                 rt = this.insertSibling(el[i], where, returnDom);
3675             }
3676             return rt;
3677         }
3678         where = where ? where.toLowerCase() : 'before';
3679         el = el || {};
3680         var refNode = where == 'before' ? this.dom : this.dom.nextSibling;
3681
3682         if(typeof el == 'object' && !el.nodeType && !el.dom){             if(where == 'after' && !this.dom.nextSibling){
3683                 rt = Ext.DomHelper.append(this.dom.parentNode, el, !returnDom);
3684             }else{
3685                 rt = Ext.DomHelper[where == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !returnDom);
3686             }
3687
3688         }else{
3689             rt = this.dom.parentNode.insertBefore(Ext.getDom(el), refNode);
3690             if(!returnDom){
3691                 rt = Ext.get(rt);
3692             }
3693         }
3694         return rt;
3695     },
3696
3697     
3698     wrap: function(config, returnDom){
3699         if(!config){
3700             config = {tag: "div"};
3701         }
3702         var newEl = Ext.DomHelper.insertBefore(this.dom, config, !returnDom);
3703         newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
3704         return newEl;
3705     },
3706
3707     
3708     replace: function(el){
3709         el = Ext.get(el);
3710         this.insertBefore(el);
3711         el.remove();
3712         return this;
3713     },
3714
3715     
3716     replaceWith: function(el){
3717         if(typeof el == 'object' && !el.nodeType && !el.dom){             el = this.insertSibling(el, 'before');
3718         }else{
3719             el = Ext.getDom(el);
3720             this.dom.parentNode.insertBefore(el, this.dom);
3721         }
3722         El.uncache(this.id);
3723         this.dom.parentNode.removeChild(this.dom);
3724         this.dom = el;
3725         this.id = Ext.id(el);
3726         El.cache[this.id] = this;
3727         return this;
3728     },
3729
3730     
3731     insertHtml : function(where, html, returnEl){
3732         var el = Ext.DomHelper.insertHtml(where, this.dom, html);
3733         return returnEl ? Ext.get(el) : el;
3734     },
3735
3736     
3737     set : function(o, useSet){
3738         var el = this.dom;
3739         useSet = typeof useSet == 'undefined' ? (el.setAttribute ? true : false) : useSet;
3740         for(var attr in o){
3741             if(attr == "style" || typeof o[attr] == "function") continue;
3742             if(attr=="cls"){
3743                 el.className = o["cls"];
3744             }else if(o.hasOwnProperty(attr)){
3745                 if(useSet) el.setAttribute(attr, o[attr]);
3746                 else el[attr] = o[attr];
3747             }
3748         }
3749         if(o.style){
3750             Ext.DomHelper.applyStyles(el, o.style);
3751         }
3752         return this;
3753     },
3754
3755     
3756     addKeyListener : function(key, fn, scope){
3757         var config;
3758         if(typeof key != "object" || Ext.isArray(key)){
3759             config = {
3760                 key: key,
3761                 fn: fn,
3762                 scope: scope
3763             };
3764         }else{
3765             config = {
3766                 key : key.key,
3767                 shift : key.shift,
3768                 ctrl : key.ctrl,
3769                 alt : key.alt,
3770                 fn: fn,
3771                 scope: scope
3772             };
3773         }
3774         return new Ext.KeyMap(this, config);
3775     },
3776
3777     
3778     addKeyMap : function(config){
3779         return new Ext.KeyMap(this, config);
3780     },
3781
3782     
3783      isScrollable : function(){
3784         var dom = this.dom;
3785         return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
3786     },
3787
3788     
3789     scrollTo : function(side, value, animate){
3790         var prop = side.toLowerCase() == "left" ? "scrollLeft" : "scrollTop";
3791         if(!animate || !A){
3792             this.dom[prop] = value;
3793         }else{
3794             var to = prop == "scrollLeft" ? [value, this.dom.scrollTop] : [this.dom.scrollLeft, value];
3795             this.anim({scroll: {"to": to}}, this.preanim(arguments, 2), 'scroll');
3796         }
3797         return this;
3798     },
3799
3800     
3801      scroll : function(direction, distance, animate){
3802          if(!this.isScrollable()){
3803              return;
3804          }
3805          var el = this.dom;
3806          var l = el.scrollLeft, t = el.scrollTop;
3807          var w = el.scrollWidth, h = el.scrollHeight;
3808          var cw = el.clientWidth, ch = el.clientHeight;
3809          direction = direction.toLowerCase();
3810          var scrolled = false;
3811          var a = this.preanim(arguments, 2);
3812          switch(direction){
3813              case "l":
3814              case "left":
3815                  if(w - l > cw){
3816                      var v = Math.min(l + distance, w-cw);
3817                      this.scrollTo("left", v, a);
3818                      scrolled = true;
3819                  }
3820                  break;
3821             case "r":
3822             case "right":
3823                  if(l > 0){
3824                      var v = Math.max(l - distance, 0);
3825                      this.scrollTo("left", v, a);
3826                      scrolled = true;
3827                  }
3828                  break;
3829             case "t":
3830             case "top":
3831             case "up":
3832                  if(t > 0){
3833                      var v = Math.max(t - distance, 0);
3834                      this.scrollTo("top", v, a);
3835                      scrolled = true;
3836                  }
3837                  break;
3838             case "b":
3839             case "bottom":
3840             case "down":
3841                  if(h - t > ch){
3842                      var v = Math.min(t + distance, h-ch);
3843                      this.scrollTo("top", v, a);
3844                      scrolled = true;
3845                  }
3846                  break;
3847          }
3848          return scrolled;
3849     },
3850
3851     
3852     translatePoints : function(x, y){
3853         if(typeof x == 'object' || Ext.isArray(x)){
3854             y = x[1]; x = x[0];
3855         }
3856         var p = this.getStyle('position');
3857         var o = this.getXY();
3858
3859         var l = parseInt(this.getStyle('left'), 10);
3860         var t = parseInt(this.getStyle('top'), 10);
3861
3862         if(isNaN(l)){
3863             l = (p == "relative") ? 0 : this.dom.offsetLeft;
3864         }
3865         if(isNaN(t)){
3866             t = (p == "relative") ? 0 : this.dom.offsetTop;
3867         }
3868
3869         return {left: (x - o[0] + l), top: (y - o[1] + t)};
3870     },
3871
3872     
3873     getScroll : function(){
3874         var d = this.dom, doc = document;
3875         if(d == doc || d == doc.body){
3876             var l, t;
3877             if(Ext.isIE && Ext.isStrict){
3878                 l = doc.documentElement.scrollLeft || (doc.body.scrollLeft || 0);
3879                 t = doc.documentElement.scrollTop || (doc.body.scrollTop || 0);
3880             }else{
3881                 l = window.pageXOffset || (doc.body.scrollLeft || 0);
3882                 t = window.pageYOffset || (doc.body.scrollTop || 0);
3883             }
3884             return {left: l, top: t};
3885         }else{
3886             return {left: d.scrollLeft, top: d.scrollTop};
3887         }
3888     },
3889
3890     
3891     getColor : function(attr, defaultValue, prefix){
3892         var v = this.getStyle(attr);
3893         if(!v || v == "transparent" || v == "inherit") {
3894             return defaultValue;
3895         }
3896         var color = typeof prefix == "undefined" ? "#" : prefix;
3897         if(v.substr(0, 4) == "rgb("){
3898             var rvs = v.slice(4, v.length -1).split(",");
3899             for(var i = 0; i < 3; i++){
3900                 var h = parseInt(rvs[i]);
3901                 var s = h.toString(16);
3902                 if(h < 16){
3903                     s = "0" + s;
3904                 }
3905                 color += s;
3906             }
3907         } else {
3908             if(v.substr(0, 1) == "#"){
3909                 if(v.length == 4) {
3910                     for(var i = 1; i < 4; i++){
3911                         var c = v.charAt(i);
3912                         color +=  c + c;
3913                     }
3914                 }else if(v.length == 7){
3915                     color += v.substr(1);
3916                 }
3917             }
3918         }
3919         return(color.length > 5 ? color.toLowerCase() : defaultValue);
3920     },
3921
3922     
3923     boxWrap : function(cls){
3924         cls = cls || 'x-box';
3925         var el = Ext.get(this.insertHtml('beforeBegin', String.format('<div class="{0}">'+El.boxMarkup+'</div>', cls)));
3926         el.child('.'+cls+'-mc').dom.appendChild(this.dom);
3927         return el;
3928     },
3929
3930     
3931     getAttributeNS : Ext.isIE ? function(ns, name){
3932         var d = this.dom;
3933         var type = typeof d[ns+":"+name];
3934         if(type != 'undefined' && type != 'unknown'){
3935             return d[ns+":"+name];
3936         }
3937         return d[name];
3938     } : function(ns, name){
3939         var d = this.dom;
3940         return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];
3941     },
3942
3943     getTextWidth : function(text, min, max){
3944         return (Ext.util.TextMetrics.measure(this.dom, Ext.value(text, this.dom.innerHTML, true)).width).constrain(min || 0, max || 1000000);
3945     }
3946 };
3947
3948 var ep = El.prototype;
3949
3950
3951 ep.on = ep.addListener;
3952     ep.mon = ep.addListener;
3953
3954 ep.getUpdateManager = ep.getUpdater;
3955
3956
3957 ep.un = ep.removeListener;
3958
3959
3960 ep.autoBoxAdjust = true;
3961
3962 El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
3963
3964 El.addUnits = function(v, defaultUnit){
3965     if(v === "" || v == "auto"){
3966         return v;
3967     }
3968     if(v === undefined){
3969         return '';
3970     }
3971     if(typeof v == "number" || !El.unitPattern.test(v)){
3972         return v + (defaultUnit || 'px');
3973     }
3974     return v;
3975 };
3976
3977 El.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>';
3978
3979 El.VISIBILITY = 1;
3980
3981 El.DISPLAY = 2;
3982
3983 El.borders = {l: "border-left-width", r: "border-right-width", t: "border-top-width", b: "border-bottom-width"};
3984 El.paddings = {l: "padding-left", r: "padding-right", t: "padding-top", b: "padding-bottom"};
3985 El.margins = {l: "margin-left", r: "margin-right", t: "margin-top", b: "margin-bottom"};
3986
3987
3988
3989
3990 El.cache = {};
3991
3992 var docEl;
3993
3994
3995 El.get = function(el){
3996     var ex, elm, id;
3997     if(!el){ return null; }
3998     if(typeof el == "string"){         if(!(elm = document.getElementById(el))){
3999             return null;
4000         }
4001         if(ex = El.cache[el]){
4002             ex.dom = elm;
4003         }else{
4004             ex = El.cache[el] = new El(elm);
4005         }
4006         return ex;
4007     }else if(el.tagName){         if(!(id = el.id)){
4008             id = Ext.id(el);
4009         }
4010         if(ex = El.cache[id]){
4011             ex.dom = el;
4012         }else{
4013             ex = El.cache[id] = new El(el);
4014         }
4015         return ex;
4016     }else if(el instanceof El){
4017         if(el != docEl){
4018             el.dom = document.getElementById(el.id) || el.dom;                                                                       El.cache[el.id] = el;         }
4019         return el;
4020     }else if(el.isComposite){
4021         return el;
4022     }else if(Ext.isArray(el)){
4023         return El.select(el);
4024     }else if(el == document){
4025                 if(!docEl){
4026             var f = function(){};
4027             f.prototype = El.prototype;
4028             docEl = new f();
4029             docEl.dom = document;
4030         }
4031         return docEl;
4032     }
4033     return null;
4034 };
4035
4036 El.uncache = function(el){
4037     for(var i = 0, a = arguments, len = a.length; i < len; i++) {
4038         if(a[i]){
4039             delete El.cache[a[i].id || a[i]];
4040         }
4041     }
4042 };
4043
4044 El.garbageCollect = function(){
4045     if(!Ext.enableGarbageCollector){
4046         clearInterval(El.collectorThread);
4047         return;
4048     }
4049     for(var eid in El.cache){
4050         var el = El.cache[eid], d = el.dom;
4051                                                                                                                                                 if(!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))){
4052             delete El.cache[eid];
4053             if(d && Ext.enableListenerCollection){
4054                 E.purgeElement(d);
4055             }
4056         }
4057     }
4058 }
4059 El.collectorThreadId = setInterval(El.garbageCollect, 30000);
4060
4061 var flyFn = function(){};
4062 flyFn.prototype = El.prototype;
4063 var _cls = new flyFn();
4064
4065 El.Flyweight = function(dom){
4066     this.dom = dom;
4067 };
4068
4069 El.Flyweight.prototype = _cls;
4070 El.Flyweight.prototype.isFlyweight = true;
4071
4072 El._flyweights = {};
4073
4074 El.fly = function(el, named){
4075     named = named || '_global';
4076     el = Ext.getDom(el);
4077     if(!el){
4078         return null;
4079     }
4080     if(!El._flyweights[named]){
4081         El._flyweights[named] = new El.Flyweight();
4082     }
4083     El._flyweights[named].dom = el;
4084     return El._flyweights[named];
4085 };
4086
4087
4088 Ext.get = El.get;
4089
4090 Ext.fly = El.fly;
4091
4092 var noBoxAdjust = Ext.isStrict ? {
4093     select:1
4094 } : {
4095     input:1, select:1, textarea:1
4096 };
4097 if(Ext.isIE || Ext.isGecko){
4098     noBoxAdjust['button'] = 1;
4099 }
4100
4101
4102 Ext.EventManager.on(window, 'unload', function(){
4103     delete El.cache;
4104     delete El._flyweights;
4105 });
4106 })();
4107
4108 Ext.enableFx = true;
4109
4110
4111 Ext.Fx = {
4112         
4113     slideIn : function(anchor, o){
4114         var el = this.getFxEl();
4115         o = o || {};
4116
4117         el.queueFx(o, function(){
4118
4119             anchor = anchor || "t";
4120
4121                         this.fixDisplay();
4122
4123                         var r = this.getFxRestore();
4124             var b = this.getBox();
4125                         this.setSize(b);
4126
4127                         var wrap = this.fxWrap(r.pos, o, "hidden");
4128
4129             var st = this.dom.style;
4130             st.visibility = "visible";
4131             st.position = "absolute";
4132
4133                         var after = function(){
4134                 el.fxUnwrap(wrap, r.pos, o);
4135                 st.width = r.width;
4136                 st.height = r.height;
4137                 el.afterFx(o);
4138             };
4139                         var a, pt = {to: [b.x, b.y]}, bw = {to: b.width}, bh = {to: b.height};
4140
4141             switch(anchor.toLowerCase()){
4142                 case "t":
4143                     wrap.setSize(b.width, 0);
4144                     st.left = st.bottom = "0";
4145                     a = {height: bh};
4146                 break;
4147                 case "l":
4148                     wrap.setSize(0, b.height);
4149                     st.right = st.top = "0";
4150                     a = {width: bw};
4151                 break;
4152                 case "r":
4153                     wrap.setSize(0, b.height);
4154                     wrap.setX(b.right);
4155                     st.left = st.top = "0";
4156                     a = {width: bw, points: pt};
4157                 break;
4158                 case "b":
4159                     wrap.setSize(b.width, 0);
4160                     wrap.setY(b.bottom);
4161                     st.left = st.top = "0";
4162                     a = {height: bh, points: pt};
4163                 break;
4164                 case "tl":
4165                     wrap.setSize(0, 0);
4166                     st.right = st.bottom = "0";
4167                     a = {width: bw, height: bh};
4168                 break;
4169                 case "bl":
4170                     wrap.setSize(0, 0);
4171                     wrap.setY(b.y+b.height);
4172                     st.right = st.top = "0";
4173                     a = {width: bw, height: bh, points: pt};
4174                 break;
4175                 case "br":
4176                     wrap.setSize(0, 0);
4177                     wrap.setXY([b.right, b.bottom]);
4178                     st.left = st.top = "0";
4179                     a = {width: bw, height: bh, points: pt};
4180                 break;
4181                 case "tr":
4182                     wrap.setSize(0, 0);
4183                     wrap.setX(b.x+b.width);
4184                     st.left = st.bottom = "0";
4185                     a = {width: bw, height: bh, points: pt};
4186                 break;
4187             }
4188             this.dom.style.visibility = "visible";
4189             wrap.show();
4190
4191             arguments.callee.anim = wrap.fxanim(a,
4192                 o,
4193                 'motion',
4194                 .5,
4195                 'easeOut', after);
4196         });
4197         return this;
4198     },
4199     
4200         
4201     slideOut : function(anchor, o){
4202         var el = this.getFxEl();
4203         o = o || {};
4204
4205         el.queueFx(o, function(){
4206
4207             anchor = anchor || "t";
4208
4209                         var r = this.getFxRestore();
4210             
4211             var b = this.getBox();
4212                         this.setSize(b);
4213
4214                         var wrap = this.fxWrap(r.pos, o, "visible");
4215
4216             var st = this.dom.style;
4217             st.visibility = "visible";
4218             st.position = "absolute";
4219
4220             wrap.setSize(b);
4221
4222             var after = function(){
4223                 if(o.useDisplay){
4224                     el.setDisplayed(false);
4225                 }else{
4226                     el.hide();
4227                 }
4228
4229                 el.fxUnwrap(wrap, r.pos, o);
4230
4231                 st.width = r.width;
4232                 st.height = r.height;
4233
4234                 el.afterFx(o);
4235             };
4236
4237             var a, zero = {to: 0};
4238             switch(anchor.toLowerCase()){
4239                 case "t":
4240                     st.left = st.bottom = "0";
4241                     a = {height: zero};
4242                 break;
4243                 case "l":
4244                     st.right = st.top = "0";
4245                     a = {width: zero};
4246                 break;
4247                 case "r":
4248                     st.left = st.top = "0";
4249                     a = {width: zero, points: {to:[b.right, b.y]}};
4250                 break;
4251                 case "b":
4252                     st.left = st.top = "0";
4253                     a = {height: zero, points: {to:[b.x, b.bottom]}};
4254                 break;
4255                 case "tl":
4256                     st.right = st.bottom = "0";
4257                     a = {width: zero, height: zero};
4258                 break;
4259                 case "bl":
4260                     st.right = st.top = "0";
4261                     a = {width: zero, height: zero, points: {to:[b.x, b.bottom]}};
4262                 break;
4263                 case "br":
4264                     st.left = st.top = "0";
4265                     a = {width: zero, height: zero, points: {to:[b.x+b.width, b.bottom]}};
4266                 break;
4267                 case "tr":
4268                     st.left = st.bottom = "0";
4269                     a = {width: zero, height: zero, points: {to:[b.right, b.y]}};
4270                 break;
4271             }
4272
4273             arguments.callee.anim = wrap.fxanim(a,
4274                 o,
4275                 'motion',
4276                 .5,
4277                 "easeOut", after);
4278         });
4279         return this;
4280     },
4281
4282         
4283     puff : function(o){
4284         var el = this.getFxEl();
4285         o = o || {};
4286
4287         el.queueFx(o, function(){
4288             this.clearOpacity();
4289             this.show();
4290
4291                         var r = this.getFxRestore();
4292             var st = this.dom.style;
4293
4294             var after = function(){
4295                 if(o.useDisplay){
4296                     el.setDisplayed(false);
4297                 }else{
4298                     el.hide();
4299                 }
4300
4301                 el.clearOpacity();
4302
4303                 el.setPositioning(r.pos);
4304                 st.width = r.width;
4305                 st.height = r.height;
4306                 st.fontSize = '';
4307                 el.afterFx(o);
4308             };
4309
4310             var width = this.getWidth();
4311             var height = this.getHeight();
4312
4313             arguments.callee.anim = this.fxanim({
4314                     width : {to: this.adjustWidth(width * 2)},
4315                     height : {to: this.adjustHeight(height * 2)},
4316                     points : {by: [-(width * .5), -(height * .5)]},
4317                     opacity : {to: 0},
4318                     fontSize: {to:200, unit: "%"}
4319                 },
4320                 o,
4321                 'motion',
4322                 .5,
4323                 "easeOut", after);
4324         });
4325         return this;
4326     },
4327
4328         
4329     switchOff : function(o){
4330         var el = this.getFxEl();
4331         o = o || {};
4332
4333         el.queueFx(o, function(){
4334             this.clearOpacity();
4335             this.clip();
4336
4337                         var r = this.getFxRestore();
4338             var st = this.dom.style;
4339
4340             var after = function(){
4341                 if(o.useDisplay){
4342                     el.setDisplayed(false);
4343                 }else{
4344                     el.hide();
4345                 }
4346
4347                 el.clearOpacity();
4348                 el.setPositioning(r.pos);
4349                 st.width = r.width;
4350                 st.height = r.height;
4351
4352                 el.afterFx(o);
4353             };
4354
4355             this.fxanim({opacity:{to:0.3}}, null, null, .1, null, function(){
4356                 this.clearOpacity();
4357                 (function(){
4358                     this.fxanim({
4359                         height:{to:1},
4360                         points:{by:[0, this.getHeight() * .5]}
4361                     }, o, 'motion', 0.3, 'easeIn', after);
4362                 }).defer(100, this);
4363             });
4364         });
4365         return this;
4366     },
4367
4368         
4369     highlight : function(color, o){
4370         var el = this.getFxEl();
4371         o = o || {};
4372
4373         el.queueFx(o, function(){
4374             color = color || "ffff9c";
4375             var attr = o.attr || "backgroundColor";
4376
4377             this.clearOpacity();
4378             this.show();
4379
4380             var origColor = this.getColor(attr);
4381             var restoreColor = this.dom.style[attr];
4382             var endColor = (o.endColor || origColor) || "ffffff";
4383
4384             var after = function(){
4385                 el.dom.style[attr] = restoreColor;
4386                 el.afterFx(o);
4387             };
4388
4389             var a = {};
4390             a[attr] = {from: color, to: endColor};
4391             arguments.callee.anim = this.fxanim(a,
4392                 o,
4393                 'color',
4394                 1,
4395                 'easeIn', after);
4396         });
4397         return this;
4398     },
4399
4400    
4401     frame : function(color, count, o){
4402         var el = this.getFxEl();
4403         o = o || {};
4404
4405         el.queueFx(o, function(){
4406             color = color || "#C3DAF9";
4407             if(color.length == 6){
4408                 color = "#" + color;
4409             }
4410             count = count || 1;
4411             var duration = o.duration || 1;
4412             this.show();
4413
4414             var b = this.getBox();
4415             var animFn = function(){
4416                 var proxy = Ext.getBody().createChild({
4417                      style:{
4418                         visbility:"hidden",
4419                         position:"absolute",
4420                         "z-index":"35000",                         border:"0px solid " + color
4421                      }
4422                   });
4423                 var scale = Ext.isBorderBox ? 2 : 1;
4424                 proxy.animate({
4425                     top:{from:b.y, to:b.y - 20},
4426                     left:{from:b.x, to:b.x - 20},
4427                     borderWidth:{from:0, to:10},
4428                     opacity:{from:1, to:0},
4429                     height:{from:b.height, to:(b.height + (20*scale))},
4430                     width:{from:b.width, to:(b.width + (20*scale))}
4431                 }, duration, function(){
4432                     proxy.remove();
4433                     if(--count > 0){
4434                          animFn();
4435                     }else{
4436                         el.afterFx(o);
4437                     }
4438                 });
4439             };
4440             animFn.call(this);
4441         });
4442         return this;
4443     },
4444
4445    
4446     pause : function(seconds){
4447         var el = this.getFxEl();
4448         var o = {};
4449
4450         el.queueFx(o, function(){
4451             setTimeout(function(){
4452                 el.afterFx(o);
4453             }, seconds * 1000);
4454         });
4455         return this;
4456     },
4457
4458    
4459     fadeIn : function(o){
4460         var el = this.getFxEl();
4461         o = o || {};
4462         el.queueFx(o, function(){
4463             this.setOpacity(0);
4464             this.fixDisplay();
4465             this.dom.style.visibility = 'visible';
4466             var to = o.endOpacity || 1;
4467             arguments.callee.anim = this.fxanim({opacity:{to:to}},
4468                 o, null, .5, "easeOut", function(){
4469                 if(to == 1){
4470                     this.clearOpacity();
4471                 }
4472                 el.afterFx(o);
4473             });
4474         });
4475         return this;
4476     },
4477
4478    
4479     fadeOut : function(o){
4480         var el = this.getFxEl();
4481         o = o || {};
4482         el.queueFx(o, function(){
4483             arguments.callee.anim = this.fxanim({opacity:{to:o.endOpacity || 0}},
4484                 o, null, .5, "easeOut", function(){
4485                 if(this.visibilityMode == Ext.Element.DISPLAY || o.useDisplay){
4486                      this.dom.style.display = "none";
4487                 }else{
4488                      this.dom.style.visibility = "hidden";
4489                 }
4490                 this.clearOpacity();
4491                 el.afterFx(o);
4492             });
4493         });
4494         return this;
4495     },
4496
4497    
4498     scale : function(w, h, o){
4499         this.shift(Ext.apply({}, o, {
4500             width: w,
4501             height: h
4502         }));
4503         return this;
4504     },
4505
4506    
4507     shift : function(o){
4508         var el = this.getFxEl();
4509         o = o || {};
4510         el.queueFx(o, function(){
4511             var a = {}, w = o.width, h = o.height, x = o.x, y = o.y,  op = o.opacity;
4512             if(w !== undefined){
4513                 a.width = {to: this.adjustWidth(w)};
4514             }
4515             if(h !== undefined){
4516                 a.height = {to: this.adjustHeight(h)};
4517             }
4518             if(x !== undefined || y !== undefined){
4519                 a.points = {to: [
4520                     x !== undefined ? x : this.getX(),
4521                     y !== undefined ? y : this.getY()
4522                 ]};
4523             }
4524             if(op !== undefined){
4525                 a.opacity = {to: op};
4526             }
4527             if(o.xy !== undefined){
4528                 a.points = {to: o.xy};
4529             }
4530             arguments.callee.anim = this.fxanim(a,
4531                 o, 'motion', .35, "easeOut", function(){
4532                 el.afterFx(o);
4533             });
4534         });
4535         return this;
4536     },
4537
4538         
4539     ghost : function(anchor, o){
4540         var el = this.getFxEl();
4541         o = o || {};
4542
4543         el.queueFx(o, function(){
4544             anchor = anchor || "b";
4545
4546                         var r = this.getFxRestore();
4547             var w = this.getWidth(),
4548                 h = this.getHeight();
4549
4550             var st = this.dom.style;
4551
4552             var after = function(){
4553                 if(o.useDisplay){
4554                     el.setDisplayed(false);
4555                 }else{
4556                     el.hide();
4557                 }
4558
4559                 el.clearOpacity();
4560                 el.setPositioning(r.pos);
4561                 st.width = r.width;
4562                 st.height = r.height;
4563
4564                 el.afterFx(o);
4565             };
4566
4567             var a = {opacity: {to: 0}, points: {}}, pt = a.points;
4568             switch(anchor.toLowerCase()){
4569                 case "t":
4570                     pt.by = [0, -h];
4571                 break;
4572                 case "l":
4573                     pt.by = [-w, 0];
4574                 break;
4575                 case "r":
4576                     pt.by = [w, 0];
4577                 break;
4578                 case "b":
4579                     pt.by = [0, h];
4580                 break;
4581                 case "tl":
4582                     pt.by = [-w, -h];
4583                 break;
4584                 case "bl":
4585                     pt.by = [-w, h];
4586                 break;
4587                 case "br":
4588                     pt.by = [w, h];
4589                 break;
4590                 case "tr":
4591                     pt.by = [w, -h];
4592                 break;
4593             }
4594
4595             arguments.callee.anim = this.fxanim(a,
4596                 o,
4597                 'motion',
4598                 .5,
4599                 "easeOut", after);
4600         });
4601         return this;
4602     },
4603
4604         
4605     syncFx : function(){
4606         this.fxDefaults = Ext.apply(this.fxDefaults || {}, {
4607             block : false,
4608             concurrent : true,
4609             stopFx : false
4610         });
4611         return this;
4612     },
4613
4614         
4615     sequenceFx : function(){
4616         this.fxDefaults = Ext.apply(this.fxDefaults || {}, {
4617             block : false,
4618             concurrent : false,
4619             stopFx : false
4620         });
4621         return this;
4622     },
4623
4624         
4625     nextFx : function(){
4626         var ef = this.fxQueue[0];
4627         if(ef){
4628             ef.call(this);
4629         }
4630     },
4631
4632         
4633     hasActiveFx : function(){
4634         return this.fxQueue && this.fxQueue[0];
4635     },
4636
4637         
4638     stopFx : function(){
4639         if(this.hasActiveFx()){
4640             var cur = this.fxQueue[0];
4641             if(cur && cur.anim && cur.anim.isAnimated()){
4642                 this.fxQueue = [cur];                 cur.anim.stop(true);
4643             }
4644         }
4645         return this;
4646     },
4647
4648         
4649     beforeFx : function(o){
4650         if(this.hasActiveFx() && !o.concurrent){
4651            if(o.stopFx){
4652                this.stopFx();
4653                return true;
4654            }
4655            return false;
4656         }
4657         return true;
4658     },
4659
4660         
4661     hasFxBlock : function(){
4662         var q = this.fxQueue;
4663         return q && q[0] && q[0].block;
4664     },
4665
4666         
4667     queueFx : function(o, fn){
4668         if(!this.fxQueue){
4669             this.fxQueue = [];
4670         }
4671         if(!this.hasFxBlock()){
4672             Ext.applyIf(o, this.fxDefaults);
4673             if(!o.concurrent){
4674                 var run = this.beforeFx(o);
4675                 fn.block = o.block;
4676                 this.fxQueue.push(fn);
4677                 if(run){
4678                     this.nextFx();
4679                 }
4680             }else{
4681                 fn.call(this);
4682             }
4683         }
4684         return this;
4685     },
4686
4687         
4688     fxWrap : function(pos, o, vis){
4689         var wrap;
4690         if(!o.wrap || !(wrap = Ext.get(o.wrap))){
4691             var wrapXY;
4692             if(o.fixPosition){
4693                 wrapXY = this.getXY();
4694             }
4695             var div = document.createElement("div");
4696             div.style.visibility = vis;
4697             wrap = Ext.get(this.dom.parentNode.insertBefore(div, this.dom));
4698             wrap.setPositioning(pos);
4699             if(wrap.getStyle("position") == "static"){
4700                 wrap.position("relative");
4701             }
4702             this.clearPositioning('auto');
4703             wrap.clip();
4704             wrap.dom.appendChild(this.dom);
4705             if(wrapXY){
4706                 wrap.setXY(wrapXY);
4707             }
4708         }
4709         return wrap;
4710     },
4711
4712         
4713     fxUnwrap : function(wrap, pos, o){
4714         this.clearPositioning();
4715         this.setPositioning(pos);
4716         if(!o.wrap){
4717             wrap.dom.parentNode.insertBefore(this.dom, wrap.dom);
4718             wrap.remove();
4719         }
4720     },
4721
4722         
4723     getFxRestore : function(){
4724         var st = this.dom.style;
4725         return {pos: this.getPositioning(), width: st.width, height : st.height};
4726     },
4727
4728         
4729     afterFx : function(o){
4730         if(o.afterStyle){
4731             this.applyStyles(o.afterStyle);
4732         }
4733         if(o.afterCls){
4734             this.addClass(o.afterCls);
4735         }
4736         if(o.remove === true){
4737             this.remove();
4738         }
4739         Ext.callback(o.callback, o.scope, [this]);
4740         if(!o.concurrent){
4741             this.fxQueue.shift();
4742             this.nextFx();
4743         }
4744     },
4745
4746         
4747     getFxEl : function(){         return Ext.get(this.dom);
4748     },
4749
4750         
4751     fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
4752         animType = animType || 'run';
4753         opt = opt || {};
4754         var anim = Ext.lib.Anim[animType](
4755             this.dom, args,
4756             (opt.duration || defaultDur) || .35,
4757             (opt.easing || defaultEase) || 'easeOut',
4758             function(){
4759                 Ext.callback(cb, this);
4760             },
4761             this
4762         );
4763         opt.anim = anim;
4764         return anim;
4765     }
4766 };
4767
4768 Ext.Fx.resize = Ext.Fx.scale;
4769
4770 Ext.apply(Ext.Element.prototype, Ext.Fx);
4771
4772
4773 Ext.CompositeElement = function(els){
4774     this.elements = [];
4775     this.addElements(els);
4776 };
4777 Ext.CompositeElement.prototype = {
4778     isComposite: true,
4779     addElements : function(els){
4780         if(!els) return this;
4781         if(typeof els == "string"){
4782             els = Ext.Element.selectorFunction(els);
4783         }
4784         var yels = this.elements;
4785         var index = yels.length-1;
4786         for(var i = 0, len = els.length; i < len; i++) {
4787                 yels[++index] = Ext.get(els[i]);
4788         }
4789         return this;
4790     },
4791
4792     
4793     fill : function(els){
4794         this.elements = [];
4795         this.add(els);
4796         return this;
4797     },
4798
4799     
4800     filter : function(selector){
4801         var els = [];
4802         this.each(function(el){
4803             if(el.is(selector)){
4804                 els[els.length] = el.dom;
4805             }
4806         });
4807         this.fill(els);
4808         return this;
4809     },
4810
4811     invoke : function(fn, args){
4812         var els = this.elements;
4813         for(var i = 0, len = els.length; i < len; i++) {
4814                 Ext.Element.prototype[fn].apply(els[i], args);
4815         }
4816         return this;
4817     },
4818     
4819     add : function(els){
4820         if(typeof els == "string"){
4821             this.addElements(Ext.Element.selectorFunction(els));
4822         }else if(els.length !== undefined){
4823             this.addElements(els);
4824         }else{
4825             this.addElements([els]);
4826         }
4827         return this;
4828     },
4829     
4830     each : function(fn, scope){
4831         var els = this.elements;
4832         for(var i = 0, len = els.length; i < len; i++){
4833             if(fn.call(scope || els[i], els[i], this, i) === false) {
4834                 break;
4835             }
4836         }
4837         return this;
4838     },
4839
4840     
4841     item : function(index){
4842         return this.elements[index] || null;
4843     },
4844
4845     
4846     first : function(){
4847         return this.item(0);
4848     },
4849
4850     
4851     last : function(){
4852         return this.item(this.elements.length-1);
4853     },
4854
4855     
4856     getCount : function(){
4857         return this.elements.length;
4858     },
4859
4860     
4861     contains : function(el){
4862         return this.indexOf(el) !== -1;
4863     },
4864
4865     
4866     indexOf : function(el){
4867         return this.elements.indexOf(Ext.get(el));
4868     },
4869
4870
4871     
4872     removeElement : function(el, removeDom){
4873         if(Ext.isArray(el)){
4874             for(var i = 0, len = el.length; i < len; i++){
4875                 this.removeElement(el[i]);
4876             }
4877             return this;
4878         }
4879         var index = typeof el == 'number' ? el : this.indexOf(el);
4880         if(index !== -1 && this.elements[index]){
4881             if(removeDom){
4882                 var d = this.elements[index];
4883                 if(d.dom){
4884                     d.remove();
4885                 }else{
4886                     Ext.removeNode(d);
4887                 }
4888             }
4889             this.elements.splice(index, 1);
4890         }
4891         return this;
4892     },
4893
4894     
4895     replaceElement : function(el, replacement, domReplace){
4896         var index = typeof el == 'number' ? el : this.indexOf(el);
4897         if(index !== -1){
4898             if(domReplace){
4899                 this.elements[index].replaceWith(replacement);
4900             }else{
4901                 this.elements.splice(index, 1, Ext.get(replacement))
4902             }
4903         }
4904         return this;
4905     },
4906
4907     
4908     clear : function(){
4909         this.elements = [];
4910     }
4911 };
4912 (function(){
4913 Ext.CompositeElement.createCall = function(proto, fnName){
4914     if(!proto[fnName]){
4915         proto[fnName] = function(){
4916             return this.invoke(fnName, arguments);
4917         };
4918     }
4919 };
4920 for(var fnName in Ext.Element.prototype){
4921     if(typeof Ext.Element.prototype[fnName] == "function"){
4922         Ext.CompositeElement.createCall(Ext.CompositeElement.prototype, fnName);
4923     }
4924 };
4925 })();
4926
4927
4928 Ext.CompositeElementLite = function(els){
4929     Ext.CompositeElementLite.superclass.constructor.call(this, els);
4930     this.el = new Ext.Element.Flyweight();
4931 };
4932 Ext.extend(Ext.CompositeElementLite, Ext.CompositeElement, {
4933     addElements : function(els){
4934         if(els){
4935             if(Ext.isArray(els)){
4936                 this.elements = this.elements.concat(els);
4937             }else{
4938                 var yels = this.elements;
4939                 var index = yels.length-1;
4940                 for(var i = 0, len = els.length; i < len; i++) {
4941                     yels[++index] = els[i];
4942                 }
4943             }
4944         }
4945         return this;
4946     },
4947     invoke : function(fn, args){
4948         var els = this.elements;
4949         var el = this.el;
4950         for(var i = 0, len = els.length; i < len; i++) {
4951             el.dom = els[i];
4952                 Ext.Element.prototype[fn].apply(el, args);
4953         }
4954         return this;
4955     },
4956     
4957     item : function(index){
4958         if(!this.elements[index]){
4959             return null;
4960         }
4961         this.el.dom = this.elements[index];
4962         return this.el;
4963     },
4964
4965     
4966     addListener : function(eventName, handler, scope, opt){
4967         var els = this.elements;
4968         for(var i = 0, len = els.length; i < len; i++) {
4969             Ext.EventManager.on(els[i], eventName, handler, scope || els[i], opt);
4970         }
4971         return this;
4972     },
4973
4974     
4975     each : function(fn, scope){
4976         var els = this.elements;
4977         var el = this.el;
4978         for(var i = 0, len = els.length; i < len; i++){
4979             el.dom = els[i];
4980                 if(fn.call(scope || el, el, this, i) === false){
4981                 break;
4982             }
4983         }
4984         return this;
4985     },
4986
4987     indexOf : function(el){
4988         return this.elements.indexOf(Ext.getDom(el));
4989     },
4990
4991     replaceElement : function(el, replacement, domReplace){
4992         var index = typeof el == 'number' ? el : this.indexOf(el);
4993         if(index !== -1){
4994             replacement = Ext.getDom(replacement);
4995             if(domReplace){
4996                 var d = this.elements[index];
4997                 d.parentNode.insertBefore(replacement, d);
4998                 Ext.removeNode(d);
4999             }
5000             this.elements.splice(index, 1, replacement);
5001         }
5002         return this;
5003     }
5004 });
5005 Ext.CompositeElementLite.prototype.on = Ext.CompositeElementLite.prototype.addListener;
5006 if(Ext.DomQuery){
5007     Ext.Element.selectorFunction = Ext.DomQuery.select;
5008 }
5009
5010 Ext.Element.select = function(selector, unique, root){
5011     var els;
5012     if(typeof selector == "string"){
5013         els = Ext.Element.selectorFunction(selector, root);
5014     }else if(selector.length !== undefined){
5015         els = selector;
5016     }else{
5017         throw "Invalid selector";
5018     }
5019     if(unique === true){
5020         return new Ext.CompositeElement(els);
5021     }else{
5022         return new Ext.CompositeElementLite(els);
5023     }
5024 };
5025
5026 Ext.select = Ext.Element.select;
5027
5028 Ext.data.Connection = function(config){
5029     Ext.apply(this, config);
5030     this.addEvents(
5031         
5032         "beforerequest",
5033         
5034         "requestcomplete",
5035         
5036         "requestexception"
5037     );
5038     Ext.data.Connection.superclass.constructor.call(this);
5039 };
5040
5041 Ext.extend(Ext.data.Connection, Ext.util.Observable, {
5042     
5043     
5044     
5045     
5046     
5047     timeout : 30000,
5048     
5049     autoAbort:false,
5050
5051     
5052     disableCaching: true,
5053
5054     
5055     request : function(o){
5056         if(this.fireEvent("beforerequest", this, o) !== false){
5057             var p = o.params;
5058
5059             if(typeof p == "function"){
5060                 p = p.call(o.scope||window, o);
5061             }
5062             if(typeof p == "object"){
5063                 p = Ext.urlEncode(p);
5064             }
5065             if(this.extraParams){
5066                 var extras = Ext.urlEncode(this.extraParams);
5067                 p = p ? (p + '&' + extras) : extras;
5068             }
5069
5070             var url = o.url || this.url;
5071             if(typeof url == 'function'){
5072                 url = url.call(o.scope||window, o);
5073             }
5074
5075             if(o.form){
5076                 var form = Ext.getDom(o.form);
5077                 url = url || form.action;
5078
5079                 var enctype = form.getAttribute("enctype");
5080                 if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
5081                     return this.doFormUpload(o, p, url);
5082                 }
5083                 var f = Ext.lib.Ajax.serializeForm(form);
5084                 p = p ? (p + '&' + f) : f;
5085             }
5086
5087             var hs = o.headers;
5088             if(this.defaultHeaders){
5089                 hs = Ext.apply(hs || {}, this.defaultHeaders);
5090                 if(!o.headers){
5091                     o.headers = hs;
5092                 }
5093             }
5094
5095             var cb = {
5096                 success: this.handleResponse,
5097                 failure: this.handleFailure,
5098                 scope: this,
5099                 argument: {options: o},
5100                 timeout : o.timeout || this.timeout
5101             };
5102
5103             var method = o.method||this.method||(p ? "POST" : "GET");
5104
5105             if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
5106                 url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime());
5107             }
5108
5109             if(typeof o.autoAbort == 'boolean'){ 
5110                 if(o.autoAbort){
5111                     this.abort();
5112                 }
5113             }else if(this.autoAbort !== false){
5114                 this.abort();
5115             }
5116             if((method == 'GET' && p) || o.xmlData || o.jsonData){
5117                 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
5118                 p = '';
5119             }
5120             this.transId = Ext.lib.Ajax.request(method, url, cb, p, o);
5121             return this.transId;
5122         }else{
5123             Ext.callback(o.callback, o.scope, [o, null, null]);
5124             return null;
5125         }
5126     },
5127
5128     
5129     isLoading : function(transId){
5130         if(transId){
5131             return Ext.lib.Ajax.isCallInProgress(transId);
5132         }else{
5133             return this.transId ? true : false;
5134         }
5135     },
5136
5137     
5138     abort : function(transId){
5139         if(transId || this.isLoading()){
5140             Ext.lib.Ajax.abort(transId || this.transId);
5141         }
5142     },
5143
5144     
5145     handleResponse : function(response){
5146         this.transId = false;
5147         var options = response.argument.options;
5148         response.argument = options ? options.argument : null;
5149         this.fireEvent("requestcomplete", this, response, options);
5150         Ext.callback(options.success, options.scope, [response, options]);
5151         Ext.callback(options.callback, options.scope, [options, true, response]);
5152     },
5153
5154     
5155     handleFailure : function(response, e){
5156         this.transId = false;
5157         var options = response.argument.options;
5158         response.argument = options ? options.argument : null;
5159         this.fireEvent("requestexception", this, response, options, e);
5160         Ext.callback(options.failure, options.scope, [response, options]);
5161         Ext.callback(options.callback, options.scope, [options, false, response]);
5162     },
5163
5164     
5165     doFormUpload : function(o, ps, url){
5166         var id = Ext.id();
5167         var frame = document.createElement('iframe');
5168         frame.id = id;
5169         frame.name = id;
5170         frame.className = 'x-hidden';
5171         if(Ext.isIE){
5172             frame.src = Ext.SSL_SECURE_URL;
5173         }
5174         document.body.appendChild(frame);
5175
5176         if(Ext.isIE){
5177            document.frames[id].name = id;
5178         }
5179
5180         var form = Ext.getDom(o.form);
5181         form.target = id;
5182         form.method = 'POST';
5183         form.enctype = form.encoding = 'multipart/form-data';
5184         if(url){
5185             form.action = url;
5186         }
5187
5188         var hiddens, hd;
5189         if(ps){ 
5190             hiddens = [];
5191             ps = Ext.urlDecode(ps, false);
5192             for(var k in ps){
5193                 if(ps.hasOwnProperty(k)){
5194                     hd = document.createElement('input');
5195                     hd.type = 'hidden';
5196                     hd.name = k;
5197                     hd.value = ps[k];
5198                     form.appendChild(hd);
5199                     hiddens.push(hd);
5200                 }
5201             }
5202         }
5203
5204         function cb(){
5205             var r = {  
5206                 responseText : '',
5207                 responseXML : null
5208             };
5209
5210             r.argument = o ? o.argument : null;
5211
5212             try { 
5213                 var doc;
5214                 if(Ext.isIE){
5215                     doc = frame.contentWindow.document;
5216                 }else {
5217                     doc = (frame.contentDocument || window.frames[id].document);
5218                 }
5219                 if(doc && doc.body){
5220                     r.responseText = doc.body.innerHTML;
5221                 }
5222                 if(doc && doc.XMLDocument){
5223                     r.responseXML = doc.XMLDocument;
5224                 }else {
5225                     r.responseXML = doc;
5226                 }
5227             }
5228             catch(e) {
5229                 
5230             }
5231
5232             Ext.EventManager.removeListener(frame, 'load', cb, this);
5233
5234             this.fireEvent("requestcomplete", this, r, o);
5235
5236             Ext.callback(o.success, o.scope, [r, o]);
5237             Ext.callback(o.callback, o.scope, [o, true, r]);
5238
5239             setTimeout(function(){Ext.removeNode(frame);}, 100);
5240         }
5241
5242         Ext.EventManager.on(frame, 'load', cb, this);
5243         form.submit();
5244
5245         if(hiddens){ 
5246             for(var i = 0, len = hiddens.length; i < len; i++){
5247                 Ext.removeNode(hiddens[i]);
5248             }
5249         }
5250     }
5251 });
5252
5253
5254 Ext.Ajax = new Ext.data.Connection({
5255     
5256     
5257     
5258     
5259     
5260     
5261
5262     
5263
5264     
5265     
5266     
5267     
5268     
5269     
5270
5271     
5272     autoAbort : false,
5273
5274     
5275     serializeForm : function(form){
5276         return Ext.lib.Ajax.serializeForm(form);
5277     }
5278 });
5279
5280 Ext.Updater = function(el, forceNew){
5281     el = Ext.get(el);
5282     if(!forceNew && el.updateManager){
5283         return el.updateManager;
5284     }
5285     
5286     this.el = el;
5287     
5288     this.defaultUrl = null;
5289
5290     this.addEvents(
5291         
5292         "beforeupdate",
5293         
5294         "update",
5295         
5296         "failure"
5297     );
5298     var d = Ext.Updater.defaults;
5299     
5300     this.sslBlankUrl = d.sslBlankUrl;
5301     
5302     this.disableCaching = d.disableCaching;
5303     
5304     this.indicatorText = d.indicatorText;
5305     
5306     this.showLoadIndicator = d.showLoadIndicator;
5307     
5308     this.timeout = d.timeout;
5309
5310     
5311     this.loadScripts = d.loadScripts;
5312
5313     
5314     this.transaction = null;
5315
5316     
5317     this.autoRefreshProcId = null;
5318     
5319     this.refreshDelegate = this.refresh.createDelegate(this);
5320     
5321     this.updateDelegate = this.update.createDelegate(this);
5322     
5323     this.formUpdateDelegate = this.formUpdate.createDelegate(this);
5324
5325     if(!this.renderer){
5326      
5327     this.renderer = new Ext.Updater.BasicRenderer();
5328     }
5329     Ext.Updater.superclass.constructor.call(this);
5330 };
5331
5332 Ext.extend(Ext.Updater, Ext.util.Observable, {
5333     
5334     getEl : function(){
5335         return this.el;
5336     },
5337     
5338     update : function(url, params, callback, discardUrl){
5339         if(this.fireEvent("beforeupdate", this.el, url, params) !== false){
5340             var method = this.method, cfg, callerScope;
5341             if(typeof url == "object"){ 
5342                 cfg = url;
5343                 url = cfg.url;
5344                 params = params || cfg.params;
5345                 callback = callback || cfg.callback;
5346                 discardUrl = discardUrl || cfg.discardUrl;
5347                     callerScope = cfg.scope;
5348                 if(typeof cfg.method != "undefined"){method = cfg.method;};
5349                 if(typeof cfg.nocache != "undefined"){this.disableCaching = cfg.nocache;};
5350                 if(typeof cfg.text != "undefined"){this.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
5351                 if(typeof cfg.scripts != "undefined"){this.loadScripts = cfg.scripts;};
5352                 if(typeof cfg.timeout != "undefined"){this.timeout = cfg.timeout;};
5353             }
5354             this.showLoading();
5355             if(!discardUrl){
5356                 this.defaultUrl = url;
5357             }
5358             if(typeof url == "function"){
5359                 url = url.call(this);
5360             }
5361
5362             method = method || (params ? "POST" : "GET");
5363             if(method == "GET"){
5364                 url = this.prepareUrl(url);
5365             }
5366
5367             var o = Ext.apply(cfg ||{}, {
5368                 url : url,
5369                 params: (typeof params == "function" && callerScope) ? params.createDelegate(callerScope) : params,
5370                 success: this.processSuccess,
5371                 failure: this.processFailure,
5372                 scope: this,
5373                 callback: undefined,
5374                 timeout: (this.timeout*1000),
5375                 argument: {
5376                         "options": cfg,
5377                         "url": url,
5378                         "form": null,
5379                         "callback": callback,
5380                         "scope": callerScope || window,
5381                         "params": params
5382                 }
5383             });
5384
5385             this.transaction = Ext.Ajax.request(o);
5386         }
5387     },
5388
5389     
5390     formUpdate : function(form, url, reset, callback){
5391         if(this.fireEvent("beforeupdate", this.el, form, url) !== false){
5392             if(typeof url == "function"){
5393                 url = url.call(this);
5394             }
5395             form = Ext.getDom(form)
5396             this.transaction = Ext.Ajax.request({
5397                 form: form,
5398                 url:url,
5399                 success: this.processSuccess,
5400                 failure: this.processFailure,
5401                 scope: this,
5402                 timeout: (this.timeout*1000),
5403                 argument: {
5404                         "url": url,
5405                         "form": form,
5406                         "callback": callback,
5407                         "reset": reset
5408                 }
5409             });
5410             this.showLoading.defer(1, this);
5411         }
5412     },
5413
5414     
5415     refresh : function(callback){
5416         if(this.defaultUrl == null){
5417             return;
5418         }
5419         this.update(this.defaultUrl, null, callback, true);
5420     },
5421
5422     
5423     startAutoRefresh : function(interval, url, params, callback, refreshNow){
5424         if(refreshNow){
5425             this.update(url || this.defaultUrl, params, callback, true);
5426         }
5427         if(this.autoRefreshProcId){
5428             clearInterval(this.autoRefreshProcId);
5429         }
5430         this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [url || this.defaultUrl, params, callback, true]), interval*1000);
5431     },
5432
5433     
5434      stopAutoRefresh : function(){
5435         if(this.autoRefreshProcId){
5436             clearInterval(this.autoRefreshProcId);
5437             delete this.autoRefreshProcId;
5438         }
5439     },
5440
5441     isAutoRefreshing : function(){
5442        return this.autoRefreshProcId ? true : false;
5443     },
5444     
5445     showLoading : function(){
5446         if(this.showLoadIndicator){
5447             this.el.update(this.indicatorText);
5448         }
5449     },
5450
5451     
5452     prepareUrl : function(url){
5453         if(this.disableCaching){
5454             var append = "_dc=" + (new Date().getTime());
5455             if(url.indexOf("?") !== -1){
5456                 url += "&" + append;
5457             }else{
5458                 url += "?" + append;
5459             }
5460         }
5461         return url;
5462     },
5463
5464     
5465     processSuccess : function(response){
5466         this.transaction = null;
5467         if(response.argument.form && response.argument.reset){
5468             try{ 
5469                 response.argument.form.reset();
5470             }catch(e){}
5471         }
5472         if(this.loadScripts){
5473             this.renderer.render(this.el, response, this,
5474                 this.updateComplete.createDelegate(this, [response]));
5475         }else{
5476             this.renderer.render(this.el, response, this);
5477             this.updateComplete(response);
5478         }
5479     },
5480
5481     updateComplete : function(response){
5482         this.fireEvent("update", this.el, response);
5483         if(typeof response.argument.callback == "function"){
5484             response.argument.callback.call(response.argument.scope, this.el, true, response, response.argument.options);
5485         }
5486     },
5487
5488     
5489     processFailure : function(response){
5490         this.transaction = null;
5491         this.fireEvent("failure", this.el, response);
5492         if(typeof response.argument.callback == "function"){
5493             response.argument.callback.call(response.argument.scope, this.el, false, response, response.argument.options);
5494         }
5495     },
5496
5497     
5498     setRenderer : function(renderer){
5499         this.renderer = renderer;
5500     },
5501
5502     getRenderer : function(){
5503        return this.renderer;
5504     },
5505
5506     
5507     setDefaultUrl : function(defaultUrl){
5508         this.defaultUrl = defaultUrl;
5509     },
5510
5511     
5512     abort : function(){
5513         if(this.transaction){
5514             Ext.Ajax.abort(this.transaction);
5515         }
5516     },
5517
5518     
5519     isUpdating : function(){
5520         if(this.transaction){
5521             return Ext.Ajax.isLoading(this.transaction);
5522         }
5523         return false;
5524     }
5525 });
5526
5527
5528    Ext.Updater.defaults = {
5529        
5530          timeout : 30,
5531
5532          
5533         loadScripts : false,
5534
5535         
5536         sslBlankUrl : (Ext.SSL_SECURE_URL || "javascript:false"),
5537         
5538         disableCaching : false,
5539         
5540         showLoadIndicator : true,
5541         
5542         indicatorText : '<div class="loading-indicator">Loading...</div>'
5543    };
5544
5545
5546 Ext.Updater.updateElement = function(el, url, params, options){
5547     var um = Ext.get(el).getUpdater();
5548     Ext.apply(um, options);
5549     um.update(url, params, options ? options.callback : null);
5550 };
5551
5552 Ext.Updater.update = Ext.Updater.updateElement;
5553
5554 Ext.Updater.BasicRenderer = function(){};
5555
5556 Ext.Updater.BasicRenderer.prototype = {
5557     
5558      render : function(el, response, updateManager, callback){
5559         el.update(response.responseText, updateManager.loadScripts, callback);
5560     }
5561 };
5562
5563 Ext.UpdateManager = Ext.Updater;
5564
5565
5566
5567
5568
5569 Date.parseFunctions = {count:0};
5570 Date.parseRegexes = [];
5571 Date.formatFunctions = {count:0};
5572
5573 Date.prototype.dateFormat = function(format) {
5574     if (Date.formatFunctions[format] == null) {
5575         Date.createNewFormat(format);
5576     }
5577     var func = Date.formatFunctions[format];
5578     return this[func]();
5579 };
5580
5581
5582
5583 Date.prototype.format = Date.prototype.dateFormat;
5584
5585 Date.createNewFormat = function(format) {
5586     var funcName = "format" + Date.formatFunctions.count++;
5587     Date.formatFunctions[format] = funcName;
5588     var code = "Date.prototype." + funcName + " = function(){return ";
5589     var special = false;
5590     var ch = '';
5591     for (var i = 0; i < format.length; ++i) {
5592         ch = format.charAt(i);
5593         if (!special && ch == "\\") {
5594             special = true;
5595         }
5596         else if (special) {
5597             special = false;
5598             code += "'" + String.escape(ch) + "' + ";
5599         }
5600         else {
5601             code += Date.getFormatCode(ch);
5602         }
5603     }
5604     eval(code.substring(0, code.length - 3) + ";}");
5605 };
5606
5607 Date.getFormatCode = function(character) {
5608     switch (character) {
5609     case "d":
5610         return "String.leftPad(this.getDate(), 2, '0') + ";
5611     case "D":
5612         return "Date.getShortDayName(this.getDay()) + ";     case "j":
5613         return "this.getDate() + ";
5614     case "l":
5615         return "Date.dayNames[this.getDay()] + ";
5616     case "N":
5617         return "(this.getDay() ? this.getDay() : 7) + ";
5618     case "S":
5619         return "this.getSuffix() + ";
5620     case "w":
5621         return "this.getDay() + ";
5622     case "z":
5623         return "this.getDayOfYear() + ";
5624     case "W":
5625         return "String.leftPad(this.getWeekOfYear(), 2, '0') + ";
5626     case "F":
5627         return "Date.monthNames[this.getMonth()] + ";
5628     case "m":
5629         return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
5630     case "M":
5631         return "Date.getShortMonthName(this.getMonth()) + ";     case "n":
5632         return "(this.getMonth() + 1) + ";
5633     case "t":
5634         return "this.getDaysInMonth() + ";
5635     case "L":
5636         return "(this.isLeapYear() ? 1 : 0) + ";
5637     case "o":
5638         return "(this.getFullYear() + (this.getWeekOfYear() == 1 && this.getMonth() > 0 ? +1 : (this.getWeekOfYear() >= 52 && this.getMonth() < 11 ? -1 : 0))) + ";
5639     case "Y":
5640         return "this.getFullYear() + ";
5641     case "y":
5642         return "('' + this.getFullYear()).substring(2, 4) + ";
5643     case "a":
5644         return "(this.getHours() < 12 ? 'am' : 'pm') + ";
5645     case "A":
5646         return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
5647     case "g":
5648         return "((this.getHours() % 12) ? this.getHours() % 12 : 12) + ";
5649     case "G":
5650         return "this.getHours() + ";
5651     case "h":
5652         return "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0') + ";
5653     case "H":
5654         return "String.leftPad(this.getHours(), 2, '0') + ";
5655     case "i":
5656         return "String.leftPad(this.getMinutes(), 2, '0') + ";
5657     case "s":
5658         return "String.leftPad(this.getSeconds(), 2, '0') + ";
5659     case "u":
5660         return "String.leftPad(this.getMilliseconds(), 3, '0') + ";
5661     case "O":
5662         return "this.getGMTOffset() + ";
5663     case "P":
5664         return "this.getGMTOffset(true) + ";
5665     case "T":
5666         return "this.getTimezone() + ";
5667     case "Z":
5668         return "(this.getTimezoneOffset() * -60) + ";
5669     case "c":
5670         for (var df = Date.getFormatCode, c = "Y-m-dTH:i:sP", code = "", i = 0, l = c.length; i < l; ++i) {
5671           var e = c.charAt(i);
5672           code += e == "T" ? "'T' + " : df(e);         }
5673         return code;
5674     case "U":
5675         return "Math.round(this.getTime() / 1000) + ";
5676     default:
5677         return "'" + String.escape(character) + "' + ";
5678     }
5679 };
5680
5681
5682 Date.parseDate = function(input, format) {
5683     if (Date.parseFunctions[format] == null) {
5684         Date.createParser(format);
5685     }
5686     var func = Date.parseFunctions[format];
5687     return Date[func](input);
5688 };
5689
5690 Date.createParser = function(format) {
5691     var funcName = "parse" + Date.parseFunctions.count++;
5692     var regexNum = Date.parseRegexes.length;
5693     var currentGroup = 1;
5694     Date.parseFunctions[format] = funcName;
5695
5696     var code = "Date." + funcName + " = function(input){\n"
5697         + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1, ms = -1, o, z, u, v;\n"
5698         + "input = String(input);var d = new Date();\n"
5699         + "y = d.getFullYear();\n"
5700         + "m = d.getMonth();\n"
5701         + "d = d.getDate();\n"
5702         + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
5703         + "if (results && results.length > 0) {";
5704     var regex = "";
5705
5706     var special = false;
5707     var ch = '';
5708     for (var i = 0; i < format.length; ++i) {
5709         ch = format.charAt(i);
5710         if (!special && ch == "\\") {
5711             special = true;
5712         }
5713         else if (special) {
5714             special = false;
5715             regex += String.escape(ch);
5716         }
5717         else {
5718             var obj = Date.formatCodeToRegex(ch, currentGroup);
5719             currentGroup += obj.g;
5720             regex += obj.s;
5721             if (obj.g && obj.c) {
5722                 code += obj.c;
5723             }
5724         }
5725     }
5726
5727     code += "if (u)\n"
5728         + "{v = new Date(u * 1000);}"         + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0 && ms >= 0)\n"
5729         + "{v = new Date(y, m, d, h, i, s, ms);}\n"
5730         + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n"
5731         + "{v = new Date(y, m, d, h, i, s);}\n"
5732         + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n"
5733         + "{v = new Date(y, m, d, h, i);}\n"
5734         + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0)\n"
5735         + "{v = new Date(y, m, d, h);}\n"
5736         + "else if (y >= 0 && m >= 0 && d > 0)\n"
5737         + "{v = new Date(y, m, d);}\n"
5738         + "else if (y >= 0 && m >= 0)\n"
5739         + "{v = new Date(y, m);}\n"
5740         + "else if (y >= 0)\n"
5741         + "{v = new Date(y);}\n"
5742         + "}return (v && (z || o))?\n"         + "    (z ? v.add(Date.SECOND, (v.getTimezoneOffset() * 60) + (z*1)) :\n"         + "        v.add(Date.HOUR, (v.getGMTOffset() / 100) + (o / -100))) : v\n"         + ";}";
5743
5744     Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$", "i");
5745     eval(code);
5746 };
5747
5748 Date.formatCodeToRegex = function(character, currentGroup) {
5749     
5750     switch (character) {
5751     case "d":
5752         return {g:1,
5753             c:"d = parseInt(results[" + currentGroup + "], 10);\n",
5754             s:"(\\d{2})"};     case "D":
5755         for (var a = [], i = 0; i < 7; a.push(Date.getShortDayName(i)), ++i);         return {g:0,
5756             c:null,
5757             s:"(?:" + a.join("|") +")"};
5758     case "j":
5759         return {g:1,
5760             c:"d = parseInt(results[" + currentGroup + "], 10);\n",
5761             s:"(\\d{1,2})"};     case "l":
5762         return {g:0,
5763             c:null,
5764             s:"(?:" + Date.dayNames.join("|") + ")"};
5765     case "N":
5766         return {g:0,
5767             c:null,
5768             s:"[1-7]"};     case "S":
5769         return {g:0,
5770             c:null,
5771             s:"(?:st|nd|rd|th)"};
5772     case "w":
5773         return {g:0,
5774             c:null,
5775             s:"[0-6]"};     case "z":
5776         return {g:0,
5777             c:null,
5778             s:"(?:\\d{1,3}"};     case "W":
5779         return {g:0,
5780             c:null,
5781             s:"(?:\\d{2})"};     case "F":
5782         return {g:1,
5783             c:"m = parseInt(Date.getMonthNumber(results[" + currentGroup + "]), 10);\n",             s:"(" + Date.monthNames.join("|") + ")"};
5784     case "m":
5785         return {g:1,
5786             c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
5787             s:"(\\d{2})"};     case "M":
5788         for (var a = [], i = 0; i < 12; a.push(Date.getShortMonthName(i)), ++i);         return {g:1,
5789             c:"m = parseInt(Date.getMonthNumber(results[" + currentGroup + "]), 10);\n",             s:"(" + a.join("|") + ")"};
5790     case "n":
5791         return {g:1,
5792             c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
5793             s:"(\\d{1,2})"};     case "t":
5794         return {g:0,
5795             c:null,
5796             s:"(?:\\d{2})"};     case "L":
5797         return {g:0,
5798             c:null,
5799             s:"(?:1|0)"};
5800     case "o":
5801     case "Y":
5802         return {g:1,
5803             c:"y = parseInt(results[" + currentGroup + "], 10);\n",
5804             s:"(\\d{4})"};     case "y":
5805         return {g:1,
5806             c:"var ty = parseInt(results[" + currentGroup + "], 10);\n"
5807                 + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
5808             s:"(\\d{1,2})"};     case "a":
5809         return {g:1,
5810             c:"if (results[" + currentGroup + "] == 'am') {\n"
5811                 + "if (h == 12) { h = 0; }\n"
5812                 + "} else { if (h < 12) { h += 12; }}",
5813             s:"(am|pm)"};
5814     case "A":
5815         return {g:1,
5816             c:"if (results[" + currentGroup + "] == 'AM') {\n"
5817                 + "if (h == 12) { h = 0; }\n"
5818                 + "} else { if (h < 12) { h += 12; }}",
5819             s:"(AM|PM)"};
5820     case "g":
5821     case "G":
5822         return {g:1,
5823             c:"h = parseInt(results[" + currentGroup + "], 10);\n",
5824             s:"(\\d{1,2})"};     case "h":
5825     case "H":
5826         return {g:1,
5827             c:"h = parseInt(results[" + currentGroup + "], 10);\n",
5828             s:"(\\d{2})"};     case "i":
5829         return {g:1,
5830             c:"i = parseInt(results[" + currentGroup + "], 10);\n",
5831             s:"(\\d{2})"};     case "s":
5832         return {g:1,
5833             c:"s = parseInt(results[" + currentGroup + "], 10);\n",
5834             s:"(\\d{2})"};     case "u":
5835         return {g:1,
5836             c:"ms = parseInt(results[" + currentGroup + "], 10);\n",
5837             s:"(\\d{3})"};     case "O":
5838         return {g:1,
5839             c:[
5840                 "o = results[", currentGroup, "];\n",
5841                 "var sn = o.substring(0,1);\n",                 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60);\n",                 "var mn = o.substring(3,5) % 60;\n",                 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n",                 "    (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n"
5842             ].join(""),
5843             s: "([+\-]\\d{4})"};     case "P":
5844         return {g:1,
5845             c:[
5846                 "o = results[", currentGroup, "];\n",
5847                 "var sn = o.substring(0,1);\n",                 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60);\n",                 "var mn = o.substring(4,6) % 60;\n",                 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n",                 "    (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n"
5848             ].join(""),
5849             s: "([+\-]\\d{2}:\\d{2})"};     case "T":
5850         return {g:0,
5851             c:null,
5852             s:"[A-Z]{1,4}"};     case "Z":
5853         return {g:1,
5854             c:"z = results[" + currentGroup + "] * 1;\n"                   + "z = (-43200 <= z && z <= 50400)? z : null;\n",
5855             s:"([+\-]?\\d{1,5})"};     case "c":
5856         var df = Date.formatCodeToRegex, calc = [];
5857         var arr = [df("Y", 1), df("m", 2), df("d", 3), df("h", 4), df("i", 5), df("s", 6), df("P", 7)];
5858         for (var i = 0, l = arr.length; i < l; ++i) {
5859           calc.push(arr[i].c);
5860         }
5861         return {g:1,
5862             c:calc.join(""),
5863             s:arr[0].s + "-" + arr[1].s + "-" + arr[2].s + "T" + arr[3].s + ":" + arr[4].s + ":" + arr[5].s + arr[6].s};
5864     case "U":
5865         return {g:1,
5866             c:"u = parseInt(results[" + currentGroup + "], 10);\n",
5867             s:"(-?\\d+)"};     default:
5868         return {g:0,
5869             c:null,
5870             s:Ext.escapeRe(character)};
5871     }
5872 };
5873
5874
5875 Date.prototype.getTimezone = function() {
5876                                                     return this.toString().replace(/^.* (?:\((.*)\)|([A-Z]{1,4})(?:[\-+][0-9]{4})?(?: -?\d+)?)$/, "$1$2").replace(/[^A-Z]/g, "");
5877 };
5878
5879
5880 Date.prototype.getGMTOffset = function(colon) {
5881     return (this.getTimezoneOffset() > 0 ? "-" : "+")
5882         + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
5883         + (colon ? ":" : "")
5884         + String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
5885 };
5886
5887
5888 Date.prototype.getDayOfYear = function() {
5889     var num = 0;
5890     Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
5891     for (var i = 0; i < this.getMonth(); ++i) {
5892         num += Date.daysInMonth[i];
5893     }
5894     return num + this.getDate() - 1;
5895 };
5896
5897
5898 Date.prototype.getWeekOfYear = function() {
5899         var ms1d = 864e5;     var ms7d = 7 * ms1d;     var DC3 = Date.UTC(this.getFullYear(), this.getMonth(), this.getDate() + 3) / ms1d;     var AWN = Math.floor(DC3 / 7);     var Wyr = new Date(AWN * ms7d).getUTCFullYear();
5900     return AWN - Math.floor(Date.UTC(Wyr, 0, 7) / ms7d) + 1;
5901 };
5902
5903
5904 Date.prototype.isLeapYear = function() {
5905     var year = this.getFullYear();
5906     return !!((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
5907 };
5908
5909
5910 Date.prototype.getFirstDayOfMonth = function() {
5911     var day = (this.getDay() - (this.getDate() - 1)) % 7;
5912     return (day < 0) ? (day + 7) : day;
5913 };
5914
5915
5916 Date.prototype.getLastDayOfMonth = function() {
5917     var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
5918     return (day < 0) ? (day + 7) : day;
5919 };
5920
5921
5922
5923 Date.prototype.getFirstDateOfMonth = function() {
5924     return new Date(this.getFullYear(), this.getMonth(), 1);
5925 };
5926
5927
5928 Date.prototype.getLastDateOfMonth = function() {
5929     return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
5930 };
5931
5932 Date.prototype.getDaysInMonth = function() {
5933     Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
5934     return Date.daysInMonth[this.getMonth()];
5935 };
5936
5937
5938 Date.prototype.getSuffix = function() {
5939     switch (this.getDate()) {
5940         case 1:
5941         case 21:
5942         case 31:
5943             return "st";
5944         case 2:
5945         case 22:
5946             return "nd";
5947         case 3:
5948         case 23:
5949             return "rd";
5950         default:
5951             return "th";
5952     }
5953 };
5954
5955 Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
5956
5957
5958 Date.monthNames =
5959    ["January",
5960     "February",
5961     "March",
5962     "April",
5963     "May",
5964     "June",
5965     "July",
5966     "August",
5967     "September",
5968     "October",
5969     "November",
5970     "December"];
5971
5972
5973 Date.getShortMonthName = function(month) {
5974     return Date.monthNames[month].substring(0, 3);
5975 }
5976
5977
5978 Date.dayNames =
5979    ["Sunday",
5980     "Monday",
5981     "Tuesday",
5982     "Wednesday",
5983     "Thursday",
5984     "Friday",
5985     "Saturday"];
5986
5987
5988 Date.getShortDayName = function(day) {
5989     return Date.dayNames[day].substring(0, 3);
5990 }
5991
5992 Date.y2kYear = 50;
5993
5994
5995 Date.monthNumbers = {
5996     Jan:0,
5997     Feb:1,
5998     Mar:2,
5999     Apr:3,
6000     May:4,
6001     Jun:5,
6002     Jul:6,
6003     Aug:7,
6004     Sep:8,
6005     Oct:9,
6006     Nov:10,
6007     Dec:11};
6008
6009
6010 Date.getMonthNumber = function(name) {
6011         return Date.monthNumbers[name.substring(0, 1).toUpperCase() + name.substring(1, 3).toLowerCase()];
6012 }
6013
6014
6015 Date.prototype.clone = function() {
6016   return new Date(this.getTime());
6017 };
6018
6019
6020 Date.prototype.clearTime = function(clone){
6021     if(clone){
6022         return this.clone().clearTime();
6023     }
6024     this.setHours(0);
6025     this.setMinutes(0);
6026     this.setSeconds(0);
6027     this.setMilliseconds(0);
6028     return this;
6029 };
6030
6031 if(Ext.isSafari){
6032     Date.brokenSetMonth = Date.prototype.setMonth;
6033   Date.prototype.setMonth = function(num){
6034     if(num <= -1){
6035       var n = Math.ceil(-num);
6036       var back_year = Math.ceil(n/12);
6037       var month = (n % 12) ? 12 - n % 12 : 0 ;
6038       this.setFullYear(this.getFullYear() - back_year);
6039       return Date.brokenSetMonth.call(this, month);
6040     } else {
6041       return Date.brokenSetMonth.apply(this, arguments);
6042     }
6043   };
6044 }
6045
6046
6047 Date.MILLI = "ms";
6048
6049 Date.SECOND = "s";
6050
6051 Date.MINUTE = "mi";
6052
6053 Date.HOUR = "h";
6054
6055 Date.DAY = "d";
6056
6057 Date.MONTH = "mo";
6058
6059 Date.YEAR = "y";
6060
6061
6062 Date.prototype.add = function(interval, value){
6063   var d = this.clone();
6064   if (!interval || value === 0) return d;
6065   switch(interval.toLowerCase()){
6066     case Date.MILLI:
6067       d.setMilliseconds(this.getMilliseconds() + value);
6068       break;
6069     case Date.SECOND:
6070       d.setSeconds(this.getSeconds() + value);
6071       break;
6072     case Date.MINUTE:
6073       d.setMinutes(this.getMinutes() + value);
6074       break;
6075     case Date.HOUR:
6076       d.setHours(this.getHours() + value);
6077       break;
6078     case Date.DAY:
6079       d.setDate(this.getDate() + value);
6080       break;
6081     case Date.MONTH:
6082       var day = this.getDate();
6083       if(day > 28){
6084           day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
6085       }
6086       d.setDate(day);
6087       d.setMonth(this.getMonth() + value);
6088       break;
6089     case Date.YEAR:
6090       d.setFullYear(this.getFullYear() + value);
6091       break;
6092   }
6093   return d;
6094 };
6095
6096
6097 Date.prototype.between = function(start, end){
6098     var t = this.getTime();
6099     return start.getTime() <= t && t <= end.getTime();
6100 }
6101
6102 Ext.util.DelayedTask = function(fn, scope, args){
6103     var id = null, d, t;
6104
6105     var call = function(){
6106         var now = new Date().getTime();
6107         if(now - t >= d){
6108             clearInterval(id);
6109             id = null;
6110             fn.apply(scope, args || []);
6111         }
6112     };
6113     
6114     this.delay = function(delay, newFn, newScope, newArgs){
6115         if(id && delay != d){
6116             this.cancel();
6117         }
6118         d = delay;
6119         t = new Date().getTime();
6120         fn = newFn || fn;
6121         scope = newScope || scope;
6122         args = newArgs || args;
6123         if(!id){
6124             id = setInterval(call, d);
6125         }
6126     };
6127
6128     
6129     this.cancel = function(){
6130         if(id){
6131             clearInterval(id);
6132             id = null;
6133         }
6134     };
6135 };
6136
6137 Ext.util.TaskRunner = function(interval){
6138     interval = interval || 10;
6139     var tasks = [], removeQueue = [];
6140     var id = 0;
6141     var running = false;
6142
6143         var stopThread = function(){
6144         running = false;
6145         clearInterval(id);
6146         id = 0;
6147     };
6148
6149         var startThread = function(){
6150         if(!running){
6151             running = true;
6152             id = setInterval(runTasks, interval);
6153         }
6154     };
6155
6156         var removeTask = function(t){
6157         removeQueue.push(t);
6158         if(t.onStop){
6159             t.onStop.apply(t.scope || t);
6160         }
6161     };
6162
6163         var runTasks = function(){
6164         if(removeQueue.length > 0){
6165             for(var i = 0, len = removeQueue.length; i < len; i++){
6166                 tasks.remove(removeQueue[i]);
6167             }
6168             removeQueue = [];
6169             if(tasks.length < 1){
6170                 stopThread();
6171                 return;
6172             }
6173         }
6174         var now = new Date().getTime();
6175         for(var i = 0, len = tasks.length; i < len; ++i){
6176             var t = tasks[i];
6177             var itime = now - t.taskRunTime;
6178             if(t.interval <= itime){
6179                 var rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
6180                 t.taskRunTime = now;
6181                 if(rt === false || t.taskRunCount === t.repeat){
6182                     removeTask(t);
6183                     return;
6184                 }
6185             }
6186             if(t.duration && t.duration <= (now - t.taskStartTime)){
6187                 removeTask(t);
6188             }
6189         }
6190     };
6191
6192     
6193     this.start = function(task){
6194         tasks.push(task);
6195         task.taskStartTime = new Date().getTime();
6196         task.taskRunTime = 0;
6197         task.taskRunCount = 0;
6198         startThread();
6199         return task;
6200     };
6201
6202     
6203     this.stop = function(task){
6204         removeTask(task);
6205         return task;
6206     };
6207
6208     
6209     this.stopAll = function(){
6210         stopThread();
6211         for(var i = 0, len = tasks.length; i < len; i++){
6212             if(tasks[i].onStop){
6213                 tasks[i].onStop();
6214             }
6215         }
6216         tasks = [];
6217         removeQueue = [];
6218     };
6219 };
6220
6221
6222 Ext.TaskMgr = new Ext.util.TaskRunner();
6223
6224 Ext.util.MixedCollection = function(allowFunctions, keyFn){
6225     this.items = [];
6226     this.map = {};
6227     this.keys = [];
6228     this.length = 0;
6229     this.addEvents(
6230         
6231         "clear",
6232         
6233         "add",
6234         
6235         "replace",
6236         
6237         "remove",
6238         "sort"
6239     );
6240     this.allowFunctions = allowFunctions === true;
6241     if(keyFn){
6242         this.getKey = keyFn;
6243     }
6244     Ext.util.MixedCollection.superclass.constructor.call(this);
6245 };
6246
6247 Ext.extend(Ext.util.MixedCollection, Ext.util.Observable, {
6248     allowFunctions : false,
6249
6250
6251     add : function(key, o){
6252         if(arguments.length == 1){
6253             o = arguments[0];
6254             key = this.getKey(o);
6255         }
6256         if(typeof key == "undefined" || key === null){
6257             this.length++;
6258             this.items.push(o);
6259             this.keys.push(null);
6260         }else{
6261             var old = this.map[key];
6262             if(old){
6263                 return this.replace(key, o);
6264             }
6265             this.length++;
6266             this.items.push(o);
6267             this.map[key] = o;
6268             this.keys.push(key);
6269         }
6270         this.fireEvent("add", this.length-1, o, key);
6271         return o;
6272     },
6273
6274
6275     getKey : function(o){
6276          return o.id;
6277     },
6278
6279
6280     replace : function(key, o){
6281         if(arguments.length == 1){
6282             o = arguments[0];
6283             key = this.getKey(o);
6284         }
6285         var old = this.item(key);
6286         if(typeof key == "undefined" || key === null || typeof old == "undefined"){
6287              return this.add(key, o);
6288         }
6289         var index = this.indexOfKey(key);
6290         this.items[index] = o;
6291         this.map[key] = o;
6292         this.fireEvent("replace", key, old, o);
6293         return o;
6294     },
6295
6296
6297     addAll : function(objs){
6298         if(arguments.length > 1 || Ext.isArray(objs)){
6299             var args = arguments.length > 1 ? arguments : objs;
6300             for(var i = 0, len = args.length; i < len; i++){
6301                 this.add(args[i]);
6302             }
6303         }else{
6304             for(var key in objs){
6305                 if(this.allowFunctions || typeof objs[key] != "function"){
6306                     this.add(key, objs[key]);
6307                 }
6308             }
6309         }
6310     },
6311
6312
6313     each : function(fn, scope){
6314         var items = [].concat(this.items); 
6315         for(var i = 0, len = items.length; i < len; i++){
6316             if(fn.call(scope || items[i], items[i], i, len) === false){
6317                 break;
6318             }
6319         }
6320     },
6321
6322
6323     eachKey : function(fn, scope){
6324         for(var i = 0, len = this.keys.length; i < len; i++){
6325             fn.call(scope || window, this.keys[i], this.items[i], i, len);
6326         }
6327     },
6328
6329     
6330     find : function(fn, scope){
6331         for(var i = 0, len = this.items.length; i < len; i++){
6332             if(fn.call(scope || window, this.items[i], this.keys[i])){
6333                 return this.items[i];
6334             }
6335         }
6336         return null;
6337     },
6338
6339
6340     insert : function(index, key, o){
6341         if(arguments.length == 2){
6342             o = arguments[1];
6343             key = this.getKey(o);
6344         }
6345         if(index >= this.length){
6346             return this.add(key, o);
6347         }
6348         this.length++;
6349         this.items.splice(index, 0, o);
6350         if(typeof key != "undefined" && key != null){
6351             this.map[key] = o;
6352         }
6353         this.keys.splice(index, 0, key);
6354         this.fireEvent("add", index, o, key);
6355         return o;
6356     },
6357
6358
6359     remove : function(o){
6360         return this.removeAt(this.indexOf(o));
6361     },
6362
6363
6364     removeAt : function(index){
6365         if(index < this.length && index >= 0){
6366             this.length--;
6367             var o = this.items[index];
6368             this.items.splice(index, 1);
6369             var key = this.keys[index];
6370             if(typeof key != "undefined"){
6371                 delete this.map[key];
6372             }
6373             this.keys.splice(index, 1);
6374             this.fireEvent("remove", o, key);
6375             return o;
6376         }
6377         return false;
6378     },
6379
6380
6381     removeKey : function(key){
6382         return this.removeAt(this.indexOfKey(key));
6383     },
6384
6385
6386     getCount : function(){
6387         return this.length;
6388     },
6389
6390
6391     indexOf : function(o){
6392         return this.items.indexOf(o);
6393     },
6394
6395
6396     indexOfKey : function(key){
6397         return this.keys.indexOf(key);
6398     },
6399
6400
6401     item : function(key){
6402         var item = typeof this.map[key] != "undefined" ? this.map[key] : this.items[key];
6403         return typeof item != 'function' || this.allowFunctions ? item : null; 
6404     },
6405
6406
6407     itemAt : function(index){
6408         return this.items[index];
6409     },
6410
6411
6412     key : function(key){
6413         return this.map[key];
6414     },
6415
6416
6417     contains : function(o){
6418         return this.indexOf(o) != -1;
6419     },
6420
6421
6422     containsKey : function(key){
6423         return typeof this.map[key] != "undefined";
6424     },
6425
6426
6427     clear : function(){
6428         this.length = 0;
6429         this.items = [];
6430         this.keys = [];
6431         this.map = {};
6432         this.fireEvent("clear");
6433     },
6434
6435
6436     first : function(){
6437         return this.items[0];
6438     },
6439
6440
6441     last : function(){
6442         return this.items[this.length-1];
6443     },
6444
6445     
6446     _sort : function(property, dir, fn){
6447         var dsc = String(dir).toUpperCase() == "DESC" ? -1 : 1;
6448         fn = fn || function(a, b){
6449             return a-b;
6450         };
6451         var c = [], k = this.keys, items = this.items;
6452         for(var i = 0, len = items.length; i < len; i++){
6453             c[c.length] = {key: k[i], value: items[i], index: i};
6454         }
6455         c.sort(function(a, b){
6456             var v = fn(a[property], b[property]) * dsc;
6457             if(v == 0){
6458                 v = (a.index < b.index ? -1 : 1);
6459             }
6460             return v;
6461         });
6462         for(var i = 0, len = c.length; i < len; i++){
6463             items[i] = c[i].value;
6464             k[i] = c[i].key;
6465         }
6466         this.fireEvent("sort", this);
6467     },
6468
6469     
6470     sort : function(dir, fn){
6471         this._sort("value", dir, fn);
6472     },
6473
6474     
6475     keySort : function(dir, fn){
6476         this._sort("key", dir, fn || function(a, b){
6477             return String(a).toUpperCase()-String(b).toUpperCase();
6478         });
6479     },
6480
6481     
6482     getRange : function(start, end){
6483         var items = this.items;
6484         if(items.length < 1){
6485             return [];
6486         }
6487         start = start || 0;
6488         end = Math.min(typeof end == "undefined" ? this.length-1 : end, this.length-1);
6489         var r = [];
6490         if(start <= end){
6491             for(var i = start; i <= end; i++) {
6492                     r[r.length] = items[i];
6493             }
6494         }else{
6495             for(var i = start; i >= end; i--) {
6496                     r[r.length] = items[i];
6497             }
6498         }
6499         return r;
6500     },
6501
6502     
6503     filter : function(property, value, anyMatch, caseSensitive){
6504         if(Ext.isEmpty(value, false)){
6505             return this.clone();
6506         }
6507         value = this.createValueMatcher(value, anyMatch, caseSensitive);
6508         return this.filterBy(function(o){
6509             return o && value.test(o[property]);
6510         });
6511         },
6512
6513     
6514     filterBy : function(fn, scope){
6515         var r = new Ext.util.MixedCollection();
6516         r.getKey = this.getKey;
6517         var k = this.keys, it = this.items;
6518         for(var i = 0, len = it.length; i < len; i++){
6519             if(fn.call(scope||this, it[i], k[i])){
6520                                 r.add(k[i], it[i]);
6521                         }
6522         }
6523         return r;
6524     },
6525
6526     
6527     findIndex : function(property, value, start, anyMatch, caseSensitive){
6528         if(Ext.isEmpty(value, false)){
6529             return -1;
6530         }
6531         value = this.createValueMatcher(value, anyMatch, caseSensitive);
6532         return this.findIndexBy(function(o){
6533             return o && value.test(o[property]);
6534         }, null, start);
6535         },
6536
6537     
6538     findIndexBy : function(fn, scope, start){
6539         var k = this.keys, it = this.items;
6540         for(var i = (start||0), len = it.length; i < len; i++){
6541             if(fn.call(scope||this, it[i], k[i])){
6542                                 return i;
6543             }
6544         }
6545         if(typeof start == 'number' && start > 0){
6546             for(var i = 0; i < start; i++){
6547                 if(fn.call(scope||this, it[i], k[i])){
6548                     return i;
6549                 }
6550             }
6551         }
6552         return -1;
6553     },
6554
6555     
6556     createValueMatcher : function(value, anyMatch, caseSensitive){
6557         if(!value.exec){ 
6558             value = String(value);
6559             value = new RegExp((anyMatch === true ? '' : '^') + Ext.escapeRe(value), caseSensitive ? '' : 'i');
6560         }
6561         return value;
6562     },
6563
6564     
6565     clone : function(){
6566         var r = new Ext.util.MixedCollection();
6567         var k = this.keys, it = this.items;
6568         for(var i = 0, len = it.length; i < len; i++){
6569             r.add(k[i], it[i]);
6570         }
6571         r.getKey = this.getKey;
6572         return r;
6573     }
6574 });
6575
6576 Ext.util.MixedCollection.prototype.get = Ext.util.MixedCollection.prototype.item;
6577
6578 Ext.util.JSON = new (function(){
6579     var useHasOwn = {}.hasOwnProperty ? true : false;
6580     
6581     
6582     
6583     
6584     var pad = function(n) {
6585         return n < 10 ? "0" + n : n;
6586     };
6587     
6588     var m = {
6589         "\b": '\\b',
6590         "\t": '\\t',
6591         "\n": '\\n',
6592         "\f": '\\f',
6593         "\r": '\\r',
6594         '"' : '\\"',
6595         "\\": '\\\\'
6596     };
6597
6598     var encodeString = function(s){
6599         if (/["\\\x00-\x1f]/.test(s)) {
6600             return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
6601                 var c = m[b];
6602                 if(c){
6603                     return c;
6604                 }
6605                 c = b.charCodeAt();
6606                 return "\\u00" +
6607                     Math.floor(c / 16).toString(16) +
6608                     (c % 16).toString(16);
6609             }) + '"';
6610         }
6611         return '"' + s + '"';
6612     };
6613     
6614     var encodeArray = function(o){
6615         var a = ["["], b, i, l = o.length, v;
6616             for (i = 0; i < l; i += 1) {
6617                 v = o[i];
6618                 switch (typeof v) {
6619                     case "undefined":
6620                     case "function":
6621                     case "unknown":
6622                         break;
6623                     default:
6624                         if (b) {
6625                             a.push(',');
6626                         }
6627                         a.push(v === null ? "null" : Ext.util.JSON.encode(v));
6628                         b = true;
6629                 }
6630             }
6631             a.push("]");
6632             return a.join("");
6633     };
6634     
6635     var encodeDate = function(o){
6636         return '"' + o.getFullYear() + "-" +
6637                 pad(o.getMonth() + 1) + "-" +
6638                 pad(o.getDate()) + "T" +
6639                 pad(o.getHours()) + ":" +
6640                 pad(o.getMinutes()) + ":" +
6641                 pad(o.getSeconds()) + '"';
6642     };
6643     
6644     
6645     this.encode = function(o){
6646         if(typeof o == "undefined" || o === null){
6647             return "null";
6648         }else if(Ext.isArray(o)){
6649             return encodeArray(o);
6650         }else if(Ext.isDate(o)){
6651             return encodeDate(o);
6652         }else if(typeof o == "string"){
6653             return encodeString(o);
6654         }else if(typeof o == "number"){
6655             return isFinite(o) ? String(o) : "null";
6656         }else if(typeof o == "boolean"){
6657             return String(o);
6658         }else {
6659             var a = ["{"], b, i, v;
6660             for (i in o) {
6661                 if(!useHasOwn || o.hasOwnProperty(i)) {
6662                     v = o[i];
6663                     switch (typeof v) {
6664                     case "undefined":
6665                     case "function":
6666                     case "unknown":
6667                         break;
6668                     default:
6669                         if(b){
6670                             a.push(',');
6671                         }
6672                         a.push(this.encode(i), ":",
6673                                 v === null ? "null" : this.encode(v));
6674                         b = true;
6675                     }
6676                 }
6677             }
6678             a.push("}");
6679             return a.join("");
6680         }
6681     };
6682     
6683     
6684     this.decode = function(json){
6685         return eval("(" + json + ')');
6686     };
6687 })();
6688
6689 Ext.encode = Ext.util.JSON.encode;
6690
6691 Ext.decode = Ext.util.JSON.decode;
6692
6693
6694 Ext.util.Format = function(){
6695     var trimRe = /^\s+|\s+$/g;
6696     return {
6697         
6698         ellipsis : function(value, len){
6699             if(value && value.length > len){
6700                 return value.substr(0, len-3)+"...";
6701             }
6702             return value;
6703         },
6704
6705         
6706         undef : function(value){
6707             return value !== undefined ? value : "";
6708         },
6709
6710         
6711         defaultValue : function(value, defaultValue){
6712             return value !== undefined && value !== '' ? value : defaultValue;
6713         },
6714
6715         
6716         htmlEncode : function(value){
6717             return !value ? value : String(value).replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/</g, "&lt;").replace(/"/g, "&quot;");
6718         },
6719
6720         
6721         htmlDecode : function(value){
6722             return !value ? value : String(value).replace(/&amp;/g, "&").replace(/&gt;/g, ">").replace(/&lt;/g, "<").replace(/&quot;/g, '"');
6723         },
6724
6725         
6726         trim : function(value){
6727             return String(value).replace(trimRe, "");
6728         },
6729
6730         
6731         substr : function(value, start, length){
6732             return String(value).substr(start, length);
6733         },
6734
6735         
6736         lowercase : function(value){
6737             return String(value).toLowerCase();
6738         },
6739
6740         
6741         uppercase : function(value){
6742             return String(value).toUpperCase();
6743         },
6744
6745         
6746         capitalize : function(value){
6747             return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
6748         },
6749
6750         
6751         call : function(value, fn){
6752             if(arguments.length > 2){
6753                 var args = Array.prototype.slice.call(arguments, 2);
6754                 args.unshift(value);
6755                 return eval(fn).apply(window, args);
6756             }else{
6757                 return eval(fn).call(window, value);
6758             }
6759         },
6760
6761         
6762         usMoney : function(v){
6763             v = (Math.round((v-0)*100))/100;
6764             v = (v == Math.floor(v)) ? v + ".00" : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
6765             v = String(v);
6766             var ps = v.split('.');
6767             var whole = ps[0];
6768             var sub = ps[1] ? '.'+ ps[1] : '.00';
6769             var r = /(\d+)(\d{3})/;
6770             while (r.test(whole)) {
6771                 whole = whole.replace(r, '$1' + ',' + '$2');
6772             }
6773             v = whole + sub;
6774             if(v.charAt(0) == '-'){
6775                 return '-$' + v.substr(1);
6776             }
6777             return "$" +  v;
6778         },
6779
6780         
6781         date : function(v, format){
6782             if(!v){
6783                 return "";
6784             }
6785             if(!Ext.isDate(v)){
6786                 v = new Date(Date.parse(v));
6787             }
6788             return v.dateFormat(format || "m/d/Y");
6789         },
6790
6791         
6792         dateRenderer : function(format){
6793             return function(v){
6794                 return Ext.util.Format.date(v, format);
6795             };
6796         },
6797
6798         
6799         stripTagsRE : /<\/?[^>]+>/gi,
6800         
6801         
6802         stripTags : function(v){
6803             return !v ? v : String(v).replace(this.stripTagsRE, "");
6804         },
6805
6806         stripScriptsRe : /(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig,
6807
6808         
6809         stripScripts : function(v){
6810             return !v ? v : String(v).replace(this.stripScriptsRe, "");
6811         },
6812
6813         
6814         fileSize : function(size){
6815             if(size < 1024) {
6816                 return size + " bytes";
6817             } else if(size < 1048576) {
6818                 return (Math.round(((size*10) / 1024))/10) + " KB";
6819             } else {
6820                 return (Math.round(((size*10) / 1048576))/10) + " MB";
6821             }
6822         },
6823
6824         math : function(){
6825             var fns = {};
6826             return function(v, a){
6827                 if(!fns[a]){
6828                     fns[a] = new Function('v', 'return v ' + a + ';');
6829                 }
6830                 return fns[a](v);
6831             }
6832         }()
6833     };
6834 }();
6835
6836 Ext.XTemplate = function(){
6837     Ext.XTemplate.superclass.constructor.apply(this, arguments);
6838     var s = this.html;
6839
6840     s = ['<tpl>', s, '</tpl>'].join('');
6841
6842     var re = /<tpl\b[^>]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/;
6843
6844     var nameRe = /^<tpl\b[^>]*?for="(.*?)"/;
6845     var ifRe = /^<tpl\b[^>]*?if="(.*?)"/;
6846     var execRe = /^<tpl\b[^>]*?exec="(.*?)"/;
6847     var m, id = 0;
6848     var tpls = [];
6849
6850     while(m = s.match(re)){
6851        var m2 = m[0].match(nameRe);
6852        var m3 = m[0].match(ifRe);
6853        var m4 = m[0].match(execRe);
6854        var exp = null, fn = null, exec = null;
6855        var name = m2 && m2[1] ? m2[1] : '';
6856        if(m3){
6857            exp = m3 && m3[1] ? m3[1] : null;
6858            if(exp){
6859                fn = new Function('values', 'parent', 'xindex', 'xcount', 'with(values){ return '+(Ext.util.Format.htmlDecode(exp))+'; }');
6860            }
6861        }
6862        if(m4){
6863            exp = m4 && m4[1] ? m4[1] : null;
6864            if(exp){
6865                exec = new Function('values', 'parent', 'xindex', 'xcount', 'with(values){ '+(Ext.util.Format.htmlDecode(exp))+'; }');
6866            }
6867        }
6868        if(name){
6869            switch(name){
6870                case '.': name = new Function('values', 'parent', 'with(values){ return values; }'); break;
6871                case '..': name = new Function('values', 'parent', 'with(values){ return parent; }'); break;
6872                default: name = new Function('values', 'parent', 'with(values){ return '+name+'; }');
6873            }
6874        }
6875        tpls.push({
6876             id: id,
6877             target: name,
6878             exec: exec,
6879             test: fn,
6880             body: m[1]||''
6881         });
6882        s = s.replace(m[0], '{xtpl'+ id + '}');
6883        ++id;
6884     }
6885     for(var i = tpls.length-1; i >= 0; --i){
6886         this.compileTpl(tpls[i]);
6887     }
6888     this.master = tpls[tpls.length-1];
6889     this.tpls = tpls;
6890 };
6891 Ext.extend(Ext.XTemplate, Ext.Template, {
6892     
6893     re : /\{([\w-\.\#]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?(\s?[\+\-\*\\]\s?[\d\.\+\-\*\\\(\)]+)?\}/g,
6894     
6895     codeRe : /\{\[((?:\\\]|.|\n)*?)\]\}/g,
6896
6897     
6898     applySubTemplate : function(id, values, parent, xindex, xcount){
6899         var t = this.tpls[id];
6900         if(t.test && !t.test.call(this, values, parent, xindex, xcount)){
6901             return '';
6902         }
6903         if(t.exec && t.exec.call(this, values, parent, xindex, xcount)){
6904             return '';
6905         }
6906         var vs = t.target ? t.target.call(this, values, parent) : values;
6907         parent = t.target ? values : parent;
6908         if(t.target && Ext.isArray(vs)){
6909             var buf = [];
6910             for(var i = 0, len = vs.length; i < len; i++){
6911                 buf[buf.length] = t.compiled.call(this, vs[i], parent, i+1, len);
6912             }
6913             return buf.join('');
6914         }
6915         return t.compiled.call(this, vs, parent, xindex, xcount);
6916     },
6917
6918     
6919     compileTpl : function(tpl){
6920         var fm = Ext.util.Format;
6921         var useF = this.disableFormats !== true;
6922         var sep = Ext.isGecko ? "+" : ",";
6923         var fn = function(m, name, format, args, math){
6924             if(name.substr(0, 4) == 'xtpl'){
6925                 return "'"+ sep +'this.applySubTemplate('+name.substr(4)+', values, parent, xindex, xcount)'+sep+"'";
6926             }
6927             var v;
6928             if(name === '.'){
6929                 v = 'values';
6930             }else if(name === '#'){
6931                 v = 'xindex';
6932             }else if(name.indexOf('.') != -1){
6933                 v = name;
6934             }else{
6935                 v = "values['" + name + "']";
6936             }
6937             if(math){
6938                 v = '(' + v + math + ')';
6939             }
6940             if(format && useF){
6941                 args = args ? ',' + args : "";
6942                 if(format.substr(0, 5) != "this."){
6943                     format = "fm." + format + '(';
6944                 }else{
6945                     format = 'this.call("'+ format.substr(5) + '", ';
6946                     args = ", values";
6947                 }
6948             }else{
6949                 args= ''; format = "("+v+" === undefined ? '' : ";
6950             }
6951             return "'"+ sep + format + v + args + ")"+sep+"'";
6952         };
6953         var codeFn = function(m, code){
6954             return "'"+ sep +'('+code+')'+sep+"'";
6955         };
6956
6957         var body;
6958         
6959         if(Ext.isGecko){
6960             body = "tpl.compiled = function(values, parent, xindex, xcount){ return '" +
6961                    tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn).replace(this.codeRe, codeFn) +
6962                     "';};";
6963         }else{
6964             body = ["tpl.compiled = function(values, parent, xindex, xcount){ return ['"];
6965             body.push(tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn).replace(this.codeRe, codeFn));
6966             body.push("'].join('');};");
6967             body = body.join('');
6968         }
6969         eval(body);
6970         return this;
6971     },
6972
6973     
6974     apply : function(values){
6975         return this.master.compiled.call(this, values, {}, 1, 1);
6976     },
6977
6978     
6979     applyTemplate : function(values){
6980         return this.master.compiled.call(this, values, {}, 1, 1);
6981     },
6982
6983     
6984     compile : function(){return this;}
6985
6986     
6987     
6988     
6989     
6990 });
6991
6992
6993 Ext.XTemplate.from = function(el){
6994     el = Ext.getDom(el);
6995     return new Ext.XTemplate(el.value || el.innerHTML);
6996 };
6997
6998 Ext.util.CSS = function(){
6999         var rules = null;
7000         var doc = document;
7001
7002     var camelRe = /(-[a-z])/gi;
7003     var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
7004
7005    return {
7006    
7007    createStyleSheet : function(cssText, id){
7008        var ss;
7009        var head = doc.getElementsByTagName("head")[0];
7010        var rules = doc.createElement("style");
7011        rules.setAttribute("type", "text/css");
7012        if(id){
7013            rules.setAttribute("id", id);
7014        }
7015        if(Ext.isIE){
7016            head.appendChild(rules);
7017            ss = rules.styleSheet;
7018            ss.cssText = cssText;
7019        }else{
7020            try{
7021                 rules.appendChild(doc.createTextNode(cssText));
7022            }catch(e){
7023                rules.cssText = cssText;
7024            }
7025            head.appendChild(rules);
7026            ss = rules.styleSheet ? rules.styleSheet : (rules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
7027        }
7028        this.cacheStyleSheet(ss);
7029        return ss;
7030    },
7031
7032    
7033    removeStyleSheet : function(id){
7034        var existing = doc.getElementById(id);
7035        if(existing){
7036            existing.parentNode.removeChild(existing);
7037        }
7038    },
7039
7040    
7041    swapStyleSheet : function(id, url){
7042        this.removeStyleSheet(id);
7043        var ss = doc.createElement("link");
7044        ss.setAttribute("rel", "stylesheet");
7045        ss.setAttribute("type", "text/css");
7046        ss.setAttribute("id", id);
7047        ss.setAttribute("href", url);
7048        doc.getElementsByTagName("head")[0].appendChild(ss);
7049    },
7050    
7051    
7052    refreshCache : function(){
7053        return this.getRules(true);
7054    },
7055
7056    
7057    cacheStyleSheet : function(ss){
7058        if(!rules){
7059            rules = {};
7060        }
7061        try{
7062            var ssRules = ss.cssRules || ss.rules;
7063            for(var j = ssRules.length-1; j >= 0; --j){
7064                rules[ssRules[j].selectorText] = ssRules[j];
7065            }
7066        }catch(e){}
7067    },
7068    
7069    
7070    getRules : function(refreshCache){
7071                 if(rules == null || refreshCache){
7072                         rules = {};
7073                         var ds = doc.styleSheets;
7074                         for(var i =0, len = ds.length; i < len; i++){
7075                             try{
7076                         this.cacheStyleSheet(ds[i]);
7077                     }catch(e){} 
7078                 }
7079                 }
7080                 return rules;
7081         },
7082         
7083         
7084    getRule : function(selector, refreshCache){
7085                 var rs = this.getRules(refreshCache);
7086                 if(!Ext.isArray(selector)){
7087                     return rs[selector];
7088                 }
7089                 for(var i = 0; i < selector.length; i++){
7090                         if(rs[selector[i]]){
7091                                 return rs[selector[i]];
7092                         }
7093                 }
7094                 return null;
7095         },
7096         
7097         
7098         
7099    updateRule : function(selector, property, value){
7100                 if(!Ext.isArray(selector)){
7101                         var rule = this.getRule(selector);
7102                         if(rule){
7103                                 rule.style[property.replace(camelRe, camelFn)] = value;
7104                                 return true;
7105                         }
7106                 }else{
7107                         for(var i = 0; i < selector.length; i++){
7108                                 if(this.updateRule(selector[i], property, value)){
7109                                         return true;
7110                                 }
7111                         }
7112                 }
7113                 return false;
7114         }
7115    };   
7116 }();
7117
7118 Ext.util.ClickRepeater = function(el, config)
7119 {
7120     this.el = Ext.get(el);
7121     this.el.unselectable();
7122
7123     Ext.apply(this, config);
7124
7125     this.addEvents(
7126     
7127         "mousedown",
7128     
7129         "click",
7130     
7131         "mouseup"
7132     );
7133
7134     this.el.on("mousedown", this.handleMouseDown, this);
7135     if(this.preventDefault || this.stopDefault){
7136         this.el.on("click", function(e){
7137             if(this.preventDefault){
7138                 e.preventDefault();
7139             }
7140             if(this.stopDefault){
7141                 e.stopEvent();
7142             }
7143         }, this);
7144     }
7145
7146         if(this.handler){
7147         this.on("click", this.handler,  this.scope || this);
7148     }
7149
7150     Ext.util.ClickRepeater.superclass.constructor.call(this);
7151 };
7152
7153 Ext.extend(Ext.util.ClickRepeater, Ext.util.Observable, {
7154     interval : 20,
7155     delay: 250,
7156     preventDefault : true,
7157     stopDefault : false,
7158     timer : 0,
7159
7160         handleMouseDown : function(){
7161         clearTimeout(this.timer);
7162         this.el.blur();
7163         if(this.pressClass){
7164             this.el.addClass(this.pressClass);
7165         }
7166         this.mousedownTime = new Date();
7167
7168         Ext.getDoc().on("mouseup", this.handleMouseUp, this);
7169         this.el.on("mouseout", this.handleMouseOut, this);
7170
7171         this.fireEvent("mousedown", this);
7172         this.fireEvent("click", this);
7173
7174         if (this.accelerate) {
7175             this.delay = 400;
7176             }
7177         this.timer = this.click.defer(this.delay || this.interval, this);
7178     },
7179
7180         click : function(){
7181         this.fireEvent("click", this);
7182         this.timer = this.click.defer(this.accelerate ?
7183             this.easeOutExpo(this.mousedownTime.getElapsed(),
7184                 400,
7185                 -390,
7186                 12000) :
7187             this.interval, this);
7188     },
7189
7190     easeOutExpo : function (t, b, c, d) {
7191         return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
7192     },
7193
7194         handleMouseOut : function(){
7195         clearTimeout(this.timer);
7196         if(this.pressClass){
7197             this.el.removeClass(this.pressClass);
7198         }
7199         this.el.on("mouseover", this.handleMouseReturn, this);
7200     },
7201
7202         handleMouseReturn : function(){
7203         this.el.un("mouseover", this.handleMouseReturn);
7204         if(this.pressClass){
7205             this.el.addClass(this.pressClass);
7206         }
7207         this.click();
7208     },
7209
7210         handleMouseUp : function(){
7211         clearTimeout(this.timer);
7212         this.el.un("mouseover", this.handleMouseReturn);
7213         this.el.un("mouseout", this.handleMouseOut);
7214         Ext.getDoc().un("mouseup", this.handleMouseUp);
7215         this.el.removeClass(this.pressClass);
7216         this.fireEvent("mouseup", this);
7217     }
7218 });
7219
7220 Ext.KeyNav = function(el, config){
7221     this.el = Ext.get(el);
7222     Ext.apply(this, config);
7223     if(!this.disabled){
7224         this.disabled = true;
7225         this.enable();
7226     }
7227 };
7228
7229 Ext.KeyNav.prototype = {
7230     
7231     disabled : false,
7232     
7233     defaultEventAction: "stopEvent",
7234     
7235     forceKeyDown : false,
7236
7237         prepareEvent : function(e){
7238         var k = e.getKey();
7239         var h = this.keyToHandler[k];
7240                                 if(Ext.isSafari && h && k >= 37 && k <= 40){
7241             e.stopEvent();
7242         }
7243     },
7244
7245         relay : function(e){
7246         var k = e.getKey();
7247         var h = this.keyToHandler[k];
7248         if(h && this[h]){
7249             if(this.doRelay(e, this[h], h) !== true){
7250                 e[this.defaultEventAction]();
7251             }
7252         }
7253     },
7254
7255         doRelay : function(e, h, hname){
7256         return h.call(this.scope || this, e);
7257     },
7258
7259         enter : false,
7260     left : false,
7261     right : false,
7262     up : false,
7263     down : false,
7264     tab : false,
7265     esc : false,
7266     pageUp : false,
7267     pageDown : false,
7268     del : false,
7269     home : false,
7270     end : false,
7271
7272         keyToHandler : {
7273         37 : "left",
7274         39 : "right",
7275         38 : "up",
7276         40 : "down",
7277         33 : "pageUp",
7278         34 : "pageDown",
7279         46 : "del",
7280         36 : "home",
7281         35 : "end",
7282         13 : "enter",
7283         27 : "esc",
7284         9  : "tab"
7285     },
7286
7287         
7288         enable: function(){
7289                 if(this.disabled){
7290                                     if(this.forceKeyDown || Ext.isIE || Ext.isAir){
7291                 this.el.on("keydown", this.relay,  this);
7292             }else{
7293                 this.el.on("keydown", this.prepareEvent,  this);
7294                 this.el.on("keypress", this.relay,  this);
7295             }
7296                     this.disabled = false;
7297                 }
7298         },
7299
7300         
7301         disable: function(){
7302                 if(!this.disabled){
7303                     if(this.forceKeyDown || Ext.isIE || Ext.isAir){
7304                 this.el.un("keydown", this.relay);
7305             }else{
7306                 this.el.un("keydown", this.prepareEvent);
7307                 this.el.un("keypress", this.relay);
7308             }
7309                     this.disabled = true;
7310                 }
7311         }
7312 };
7313
7314 Ext.KeyMap = function(el, config, eventName){
7315     this.el  = Ext.get(el);
7316     this.eventName = eventName || "keydown";
7317     this.bindings = [];
7318     if(config){
7319         this.addBinding(config);
7320     }
7321     this.enable();
7322 };
7323
7324 Ext.KeyMap.prototype = {
7325     
7326     stopEvent : false,
7327
7328     
7329         addBinding : function(config){
7330         if(Ext.isArray(config)){
7331             for(var i = 0, len = config.length; i < len; i++){
7332                 this.addBinding(config[i]);
7333             }
7334             return;
7335         }
7336         var keyCode = config.key,
7337             shift = config.shift,
7338             ctrl = config.ctrl,
7339             alt = config.alt,
7340             fn = config.fn || config.handler,
7341             scope = config.scope;
7342
7343         if(typeof keyCode == "string"){
7344             var ks = [];
7345             var keyString = keyCode.toUpperCase();
7346             for(var j = 0, len = keyString.length; j < len; j++){
7347                 ks.push(keyString.charCodeAt(j));
7348             }
7349             keyCode = ks;
7350         }
7351         var keyArray = Ext.isArray(keyCode);
7352         
7353         var handler = function(e){
7354             if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) &&  (!alt || e.altKey)){
7355                 var k = e.getKey();
7356                 if(keyArray){
7357                     for(var i = 0, len = keyCode.length; i < len; i++){
7358                         if(keyCode[i] == k){
7359                           if(this.stopEvent){
7360                               e.stopEvent();
7361                           }
7362                           fn.call(scope || window, k, e);
7363                           return;
7364                         }
7365                     }
7366                 }else{
7367                     if(k == keyCode){
7368                         if(this.stopEvent){
7369                            e.stopEvent();
7370                         }
7371                         fn.call(scope || window, k, e);
7372                     }
7373                 }
7374             }
7375         };
7376         this.bindings.push(handler);
7377         },
7378
7379     
7380     on : function(key, fn, scope){
7381         var keyCode, shift, ctrl, alt;
7382         if(typeof key == "object" && !Ext.isArray(key)){
7383             keyCode = key.key;
7384             shift = key.shift;
7385             ctrl = key.ctrl;
7386             alt = key.alt;
7387         }else{
7388             keyCode = key;
7389         }
7390         this.addBinding({
7391             key: keyCode,
7392             shift: shift,
7393             ctrl: ctrl,
7394             alt: alt,
7395             fn: fn,
7396             scope: scope
7397         })
7398     },
7399
7400     
7401     handleKeyDown : function(e){
7402             if(this.enabled){ 
7403             var b = this.bindings;
7404             for(var i = 0, len = b.length; i < len; i++){
7405                 b[i].call(this, e);
7406             }
7407             }
7408         },
7409
7410         
7411         isEnabled : function(){
7412             return this.enabled;
7413         },
7414
7415         
7416         enable: function(){
7417                 if(!this.enabled){
7418                     this.el.on(this.eventName, this.handleKeyDown, this);
7419                     this.enabled = true;
7420                 }
7421         },
7422
7423         
7424         disable: function(){
7425                 if(this.enabled){
7426                     this.el.removeListener(this.eventName, this.handleKeyDown, this);
7427                     this.enabled = false;
7428                 }
7429         }
7430 };
7431
7432 Ext.util.TextMetrics = function(){
7433     var shared;
7434     return {
7435         
7436         measure : function(el, text, fixedWidth){
7437             if(!shared){
7438                 shared = Ext.util.TextMetrics.Instance(el, fixedWidth);
7439             }
7440             shared.bind(el);
7441             shared.setFixedWidth(fixedWidth || 'auto');
7442             return shared.getSize(text);
7443         },
7444
7445         
7446         createInstance : function(el, fixedWidth){
7447             return Ext.util.TextMetrics.Instance(el, fixedWidth);
7448         }
7449     };
7450 }();
7451
7452 Ext.util.TextMetrics.Instance = function(bindTo, fixedWidth){
7453     var ml = new Ext.Element(document.createElement('div'));
7454     document.body.appendChild(ml.dom);
7455     ml.position('absolute');
7456     ml.setLeftTop(-1000, -1000);
7457     ml.hide();
7458
7459     if(fixedWidth){
7460         ml.setWidth(fixedWidth);
7461     }
7462
7463     var instance = {
7464         
7465         getSize : function(text){
7466             ml.update(text);
7467             var s = ml.getSize();
7468             ml.update('');
7469             return s;
7470         },
7471
7472         
7473         bind : function(el){
7474             ml.setStyle(
7475                 Ext.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height')
7476             );
7477         },
7478
7479         
7480         setFixedWidth : function(width){
7481             ml.setWidth(width);
7482         },
7483
7484         
7485         getWidth : function(text){
7486             ml.dom.style.width = 'auto';
7487             return this.getSize(text).width;
7488         },
7489
7490         
7491         getHeight : function(text){
7492             return this.getSize(text).height;
7493         }
7494     };
7495
7496     instance.bind(bindTo);
7497
7498     return instance;
7499 };
7500
7501 Ext.Element.measureText = Ext.util.TextMetrics.measure;
7502
7503
7504 (function() {
7505
7506 var Event=Ext.EventManager;
7507 var Dom=Ext.lib.Dom;
7508
7509
7510 Ext.dd.DragDrop = function(id, sGroup, config) {
7511     if(id) {
7512         this.init(id, sGroup, config);
7513     }
7514 };
7515
7516 Ext.dd.DragDrop.prototype = {
7517
7518     
7519     id: null,
7520
7521     
7522     config: null,
7523
7524     
7525     dragElId: null,
7526
7527     
7528     handleElId: null,
7529
7530     
7531     invalidHandleTypes: null,
7532
7533     
7534     invalidHandleIds: null,
7535
7536     
7537     invalidHandleClasses: null,
7538
7539     
7540     startPageX: 0,
7541
7542     
7543     startPageY: 0,
7544
7545     
7546     groups: null,
7547
7548     
7549     locked: false,
7550
7551     
7552     lock: function() { this.locked = true; },
7553
7554     
7555     unlock: function() { this.locked = false; },
7556
7557     
7558     isTarget: true,
7559
7560     
7561     padding: null,
7562
7563     
7564     _domRef: null,
7565
7566     
7567     __ygDragDrop: true,
7568
7569     
7570     constrainX: false,
7571
7572     
7573     constrainY: false,
7574
7575     
7576     minX: 0,
7577
7578     
7579     maxX: 0,
7580
7581     
7582     minY: 0,
7583
7584     
7585     maxY: 0,
7586
7587     
7588     maintainOffset: false,
7589
7590     
7591     xTicks: null,
7592
7593     
7594     yTicks: null,
7595
7596     
7597     primaryButtonOnly: true,
7598
7599     
7600     available: false,
7601
7602     
7603     hasOuterHandles: false,
7604
7605     
7606     b4StartDrag: function(x, y) { },
7607
7608     
7609     startDrag: function(x, y) {  },
7610
7611     
7612     b4Drag: function(e) { },
7613
7614     
7615     onDrag: function(e) {  },
7616
7617     
7618     onDragEnter: function(e, id) {  },
7619
7620     
7621     b4DragOver: function(e) { },
7622
7623     
7624     onDragOver: function(e, id) {  },
7625
7626     
7627     b4DragOut: function(e) { },
7628
7629     
7630     onDragOut: function(e, id) {  },
7631
7632     
7633     b4DragDrop: function(e) { },
7634
7635     
7636     onDragDrop: function(e, id) {  },
7637
7638     
7639     onInvalidDrop: function(e) {  },
7640
7641     
7642     b4EndDrag: function(e) { },
7643
7644     
7645     endDrag: function(e) {  },
7646
7647     
7648     b4MouseDown: function(e) {  },
7649
7650     
7651     onMouseDown: function(e) {  },
7652
7653     
7654     onMouseUp: function(e) {  },
7655
7656     
7657     onAvailable: function () {
7658     },
7659
7660     
7661     defaultPadding : {left:0, right:0, top:0, bottom:0},
7662
7663     
7664     constrainTo : function(constrainTo, pad, inContent){
7665         if(typeof pad == "number"){
7666             pad = {left: pad, right:pad, top:pad, bottom:pad};
7667         }
7668         pad = pad || this.defaultPadding;
7669         var b = Ext.get(this.getEl()).getBox();
7670         var ce = Ext.get(constrainTo);
7671         var s = ce.getScroll();
7672         var c, cd = ce.dom;
7673         if(cd == document.body){
7674             c = { x: s.left, y: s.top, width: Ext.lib.Dom.getViewWidth(), height: Ext.lib.Dom.getViewHeight()};
7675         }else{
7676             var xy = ce.getXY();
7677             c = {x : xy[0]+s.left, y: xy[1]+s.top, width: cd.clientWidth, height: cd.clientHeight};
7678         }
7679
7680
7681         var topSpace = b.y - c.y;
7682         var leftSpace = b.x - c.x;
7683
7684         this.resetConstraints();
7685         this.setXConstraint(leftSpace - (pad.left||0), 
7686                 c.width - leftSpace - b.width - (pad.right||0), 
7687                                 this.xTickSize
7688         );
7689         this.setYConstraint(topSpace - (pad.top||0), 
7690                 c.height - topSpace - b.height - (pad.bottom||0), 
7691                                 this.yTickSize
7692         );
7693     },
7694
7695     
7696     getEl: function() {
7697         if (!this._domRef) {
7698             this._domRef = Ext.getDom(this.id);
7699         }
7700
7701         return this._domRef;
7702     },
7703
7704     
7705     getDragEl: function() {
7706         return Ext.getDom(this.dragElId);
7707     },
7708
7709     
7710     init: function(id, sGroup, config) {
7711         this.initTarget(id, sGroup, config);
7712         Event.on(this.id, "mousedown", this.handleMouseDown, this);
7713         
7714     },
7715
7716     
7717     initTarget: function(id, sGroup, config) {
7718
7719         
7720         this.config = config || {};
7721
7722         
7723         this.DDM = Ext.dd.DDM;
7724         
7725         this.groups = {};
7726
7727         
7728         
7729         if (typeof id !== "string") {
7730             id = Ext.id(id);
7731         }
7732
7733         
7734         this.id = id;
7735
7736         
7737         this.addToGroup((sGroup) ? sGroup : "default");
7738
7739         
7740         
7741         this.handleElId = id;
7742
7743         
7744         this.setDragElId(id);
7745
7746         
7747         this.invalidHandleTypes = { A: "A" };
7748         this.invalidHandleIds = {};
7749         this.invalidHandleClasses = [];
7750
7751         this.applyConfig();
7752
7753         this.handleOnAvailable();
7754     },
7755
7756     
7757     applyConfig: function() {
7758
7759         
7760         
7761         this.padding           = this.config.padding || [0, 0, 0, 0];
7762         this.isTarget          = (this.config.isTarget !== false);
7763         this.maintainOffset    = (this.config.maintainOffset);
7764         this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
7765
7766     },
7767
7768     
7769     handleOnAvailable: function() {
7770         this.available = true;
7771         this.resetConstraints();
7772         this.onAvailable();
7773     },
7774
7775      
7776     setPadding: function(iTop, iRight, iBot, iLeft) {
7777         
7778         if (!iRight && 0 !== iRight) {
7779             this.padding = [iTop, iTop, iTop, iTop];
7780         } else if (!iBot && 0 !== iBot) {
7781             this.padding = [iTop, iRight, iTop, iRight];
7782         } else {
7783             this.padding = [iTop, iRight, iBot, iLeft];
7784         }
7785     },
7786
7787     
7788     setInitPosition: function(diffX, diffY) {
7789         var el = this.getEl();
7790
7791         if (!this.DDM.verifyEl(el)) {
7792             return;
7793         }
7794
7795         var dx = diffX || 0;
7796         var dy = diffY || 0;
7797
7798         var p = Dom.getXY( el );
7799
7800         this.initPageX = p[0] - dx;
7801         this.initPageY = p[1] - dy;
7802
7803         this.lastPageX = p[0];
7804         this.lastPageY = p[1];
7805
7806
7807         this.setStartPosition(p);
7808     },
7809
7810     
7811     setStartPosition: function(pos) {
7812         var p = pos || Dom.getXY( this.getEl() );
7813         this.deltaSetXY = null;
7814
7815         this.startPageX = p[0];
7816         this.startPageY = p[1];
7817     },
7818
7819     
7820     addToGroup: function(sGroup) {
7821         this.groups[sGroup] = true;
7822         this.DDM.regDragDrop(this, sGroup);
7823     },
7824
7825     
7826     removeFromGroup: function(sGroup) {
7827         if (this.groups[sGroup]) {
7828             delete this.groups[sGroup];
7829         }
7830
7831         this.DDM.removeDDFromGroup(this, sGroup);
7832     },
7833
7834     
7835     setDragElId: function(id) {
7836         this.dragElId = id;
7837     },
7838
7839     
7840     setHandleElId: function(id) {
7841         if (typeof id !== "string") {
7842             id = Ext.id(id);
7843         }
7844         this.handleElId = id;
7845         this.DDM.regHandle(this.id, id);
7846     },
7847
7848     
7849     setOuterHandleElId: function(id) {
7850         if (typeof id !== "string") {
7851             id = Ext.id(id);
7852         }
7853         Event.on(id, "mousedown",
7854                 this.handleMouseDown, this);
7855         this.setHandleElId(id);
7856
7857         this.hasOuterHandles = true;
7858     },
7859
7860     
7861     unreg: function() {
7862         Event.un(this.id, "mousedown",
7863                 this.handleMouseDown);
7864         this._domRef = null;
7865         this.DDM._remove(this);
7866     },
7867
7868     destroy : function(){
7869         this.unreg();
7870     },
7871
7872     
7873     isLocked: function() {
7874         return (this.DDM.isLocked() || this.locked);
7875     },
7876
7877     
7878     handleMouseDown: function(e, oDD){
7879         if (this.primaryButtonOnly && e.button != 0) {
7880             return;
7881         }
7882
7883         if (this.isLocked()) {
7884             return;
7885         }
7886
7887         this.DDM.refreshCache(this.groups);
7888
7889         var pt = new Ext.lib.Point(Ext.lib.Event.getPageX(e), Ext.lib.Event.getPageY(e));
7890         if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) )  {
7891         } else {
7892             if (this.clickValidator(e)) {
7893
7894                 
7895                 this.setStartPosition();
7896
7897
7898                 this.b4MouseDown(e);
7899                 this.onMouseDown(e);
7900
7901                 this.DDM.handleMouseDown(e, this);
7902
7903                 this.DDM.stopEvent(e);
7904             } else {
7905
7906
7907             }
7908         }
7909     },
7910
7911     clickValidator: function(e) {
7912         var target = e.getTarget();
7913         return ( this.isValidHandleChild(target) &&
7914                     (this.id == this.handleElId ||
7915                         this.DDM.handleWasClicked(target, this.id)) );
7916     },
7917
7918     
7919     addInvalidHandleType: function(tagName) {
7920         var type = tagName.toUpperCase();
7921         this.invalidHandleTypes[type] = type;
7922     },
7923
7924     
7925     addInvalidHandleId: function(id) {
7926         if (typeof id !== "string") {
7927             id = Ext.id(id);
7928         }
7929         this.invalidHandleIds[id] = id;
7930     },
7931
7932     
7933     addInvalidHandleClass: function(cssClass) {
7934         this.invalidHandleClasses.push(cssClass);
7935     },
7936
7937     
7938     removeInvalidHandleType: function(tagName) {
7939         var type = tagName.toUpperCase();
7940         
7941         delete this.invalidHandleTypes[type];
7942     },
7943
7944     
7945     removeInvalidHandleId: function(id) {
7946         if (typeof id !== "string") {
7947             id = Ext.id(id);
7948         }
7949         delete this.invalidHandleIds[id];
7950     },
7951
7952     
7953     removeInvalidHandleClass: function(cssClass) {
7954         for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {
7955             if (this.invalidHandleClasses[i] == cssClass) {
7956                 delete this.invalidHandleClasses[i];
7957             }
7958         }
7959     },
7960
7961     
7962     isValidHandleChild: function(node) {
7963
7964         var valid = true;
7965         
7966         var nodeName;
7967         try {
7968             nodeName = node.nodeName.toUpperCase();
7969         } catch(e) {
7970             nodeName = node.nodeName;
7971         }
7972         valid = valid && !this.invalidHandleTypes[nodeName];
7973         valid = valid && !this.invalidHandleIds[node.id];
7974
7975         for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {
7976             valid = !Dom.hasClass(node, this.invalidHandleClasses[i]);
7977         }
7978
7979
7980         return valid;
7981
7982     },
7983
7984     
7985     setXTicks: function(iStartX, iTickSize) {
7986         this.xTicks = [];
7987         this.xTickSize = iTickSize;
7988
7989         var tickMap = {};
7990
7991         for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
7992             if (!tickMap[i]) {
7993                 this.xTicks[this.xTicks.length] = i;
7994                 tickMap[i] = true;
7995             }
7996         }
7997
7998         for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
7999             if (!tickMap[i]) {
8000                 this.xTicks[this.xTicks.length] = i;
8001                 tickMap[i] = true;
8002             }
8003         }
8004
8005         this.xTicks.sort(this.DDM.numericSort) ;
8006     },
8007
8008     
8009     setYTicks: function(iStartY, iTickSize) {
8010         this.yTicks = [];
8011         this.yTickSize = iTickSize;
8012
8013         var tickMap = {};
8014
8015         for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
8016             if (!tickMap[i]) {
8017                 this.yTicks[this.yTicks.length] = i;
8018                 tickMap[i] = true;
8019             }
8020         }
8021
8022         for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
8023             if (!tickMap[i]) {
8024                 this.yTicks[this.yTicks.length] = i;
8025                 tickMap[i] = true;
8026             }
8027         }
8028
8029         this.yTicks.sort(this.DDM.numericSort) ;
8030     },
8031
8032     
8033     setXConstraint: function(iLeft, iRight, iTickSize) {
8034         this.leftConstraint = iLeft;
8035         this.rightConstraint = iRight;
8036
8037         this.minX = this.initPageX - iLeft;
8038         this.maxX = this.initPageX + iRight;
8039         if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
8040
8041         this.constrainX = true;
8042     },
8043
8044     
8045     clearConstraints: function() {
8046         this.constrainX = false;
8047         this.constrainY = false;
8048         this.clearTicks();
8049     },
8050
8051     
8052     clearTicks: function() {
8053         this.xTicks = null;
8054         this.yTicks = null;
8055         this.xTickSize = 0;
8056         this.yTickSize = 0;
8057     },
8058
8059     
8060     setYConstraint: function(iUp, iDown, iTickSize) {
8061         this.topConstraint = iUp;
8062         this.bottomConstraint = iDown;
8063
8064         this.minY = this.initPageY - iUp;
8065         this.maxY = this.initPageY + iDown;
8066         if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
8067
8068         this.constrainY = true;
8069
8070     },
8071
8072     
8073     resetConstraints: function() {
8074
8075
8076         
8077         if (this.initPageX || this.initPageX === 0) {
8078             
8079             var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
8080             var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
8081
8082             this.setInitPosition(dx, dy);
8083
8084         
8085         } else {
8086             this.setInitPosition();
8087         }
8088
8089         if (this.constrainX) {
8090             this.setXConstraint( this.leftConstraint,
8091                                  this.rightConstraint,
8092                                  this.xTickSize        );
8093         }
8094
8095         if (this.constrainY) {
8096             this.setYConstraint( this.topConstraint,
8097                                  this.bottomConstraint,
8098                                  this.yTickSize         );
8099         }
8100     },
8101
8102     
8103     getTick: function(val, tickArray) {
8104
8105         if (!tickArray) {
8106             
8107             
8108             return val;
8109         } else if (tickArray[0] >= val) {
8110             
8111             
8112             return tickArray[0];
8113         } else {
8114             for (var i=0, len=tickArray.length; i<len; ++i) {
8115                 var next = i + 1;
8116                 if (tickArray[next] && tickArray[next] >= val) {
8117                     var diff1 = val - tickArray[i];
8118                     var diff2 = tickArray[next] - val;
8119                     return (diff2 > diff1) ? tickArray[i] : tickArray[next];
8120                 }
8121             }
8122
8123             
8124             
8125             return tickArray[tickArray.length - 1];
8126         }
8127     },
8128
8129     
8130     toString: function() {
8131         return ("DragDrop " + this.id);
8132     }
8133
8134 };
8135
8136 })();
8137
8138
8139
8140
8141 if (!Ext.dd.DragDropMgr) {
8142
8143
8144 Ext.dd.DragDropMgr = function() {
8145
8146     var Event = Ext.EventManager;
8147
8148     return {
8149
8150         
8151         ids: {},
8152
8153         
8154         handleIds: {},
8155
8156         
8157         dragCurrent: null,
8158
8159         
8160         dragOvers: {},
8161
8162         
8163         deltaX: 0,
8164
8165         
8166         deltaY: 0,
8167
8168         
8169         preventDefault: true,
8170
8171         
8172         stopPropagation: true,
8173
8174         
8175         initalized: false,
8176
8177         
8178         locked: false,
8179
8180         
8181         init: function() {
8182             this.initialized = true;
8183         },
8184
8185         
8186         POINT: 0,
8187
8188         
8189         INTERSECT: 1,
8190
8191         
8192         mode: 0,
8193
8194         
8195         _execOnAll: function(sMethod, args) {
8196             for (var i in this.ids) {
8197                 for (var j in this.ids[i]) {
8198                     var oDD = this.ids[i][j];
8199                     if (! this.isTypeOfDD(oDD)) {
8200                         continue;
8201                     }
8202                     oDD[sMethod].apply(oDD, args);
8203                 }
8204             }
8205         },
8206
8207         
8208         _onLoad: function() {
8209
8210             this.init();
8211
8212
8213             Event.on(document, "mouseup",   this.handleMouseUp, this, true);
8214             Event.on(document, "mousemove", this.handleMouseMove, this, true);
8215             Event.on(window,   "unload",    this._onUnload, this, true);
8216             Event.on(window,   "resize",    this._onResize, this, true);
8217             
8218
8219         },
8220
8221         
8222         _onResize: function(e) {
8223             this._execOnAll("resetConstraints", []);
8224         },
8225
8226         
8227         lock: function() { this.locked = true; },
8228
8229         
8230         unlock: function() { this.locked = false; },
8231
8232         
8233         isLocked: function() { return this.locked; },
8234
8235         
8236         locationCache: {},
8237
8238         
8239         useCache: true,
8240
8241         
8242         clickPixelThresh: 3,
8243
8244         
8245         clickTimeThresh: 350,
8246
8247         
8248         dragThreshMet: false,
8249
8250         
8251         clickTimeout: null,
8252
8253         
8254         startX: 0,
8255
8256         
8257         startY: 0,
8258
8259         
8260         regDragDrop: function(oDD, sGroup) {
8261             if (!this.initialized) { this.init(); }
8262
8263             if (!this.ids[sGroup]) {
8264                 this.ids[sGroup] = {};
8265             }
8266             this.ids[sGroup][oDD.id] = oDD;
8267         },
8268
8269         
8270         removeDDFromGroup: function(oDD, sGroup) {
8271             if (!this.ids[sGroup]) {
8272                 this.ids[sGroup] = {};
8273             }
8274
8275             var obj = this.ids[sGroup];
8276             if (obj && obj[oDD.id]) {
8277                 delete obj[oDD.id];
8278             }
8279         },
8280
8281         
8282         _remove: function(oDD) {
8283             for (var g in oDD.groups) {
8284                 if (g && this.ids[g][oDD.id]) {
8285                     delete this.ids[g][oDD.id];
8286                 }
8287             }
8288             delete this.handleIds[oDD.id];
8289         },
8290
8291         
8292         regHandle: function(sDDId, sHandleId) {
8293             if (!this.handleIds[sDDId]) {
8294                 this.handleIds[sDDId] = {};
8295             }
8296             this.handleIds[sDDId][sHandleId] = sHandleId;
8297         },
8298
8299         
8300         isDragDrop: function(id) {
8301             return ( this.getDDById(id) ) ? true : false;
8302         },
8303
8304         
8305         getRelated: function(p_oDD, bTargetsOnly) {
8306             var oDDs = [];
8307             for (var i in p_oDD.groups) {
8308                 for (j in this.ids[i]) {
8309                     var dd = this.ids[i][j];
8310                     if (! this.isTypeOfDD(dd)) {
8311                         continue;
8312                     }
8313                     if (!bTargetsOnly || dd.isTarget) {
8314                         oDDs[oDDs.length] = dd;
8315                     }
8316                 }
8317             }
8318
8319             return oDDs;
8320         },
8321
8322         
8323         isLegalTarget: function (oDD, oTargetDD) {
8324             var targets = this.getRelated(oDD, true);
8325             for (var i=0, len=targets.length;i<len;++i) {
8326                 if (targets[i].id == oTargetDD.id) {
8327                     return true;
8328                 }
8329             }
8330
8331             return false;
8332         },
8333
8334         
8335         isTypeOfDD: function (oDD) {
8336             return (oDD && oDD.__ygDragDrop);
8337         },
8338
8339         
8340         isHandle: function(sDDId, sHandleId) {
8341             return ( this.handleIds[sDDId] &&
8342                             this.handleIds[sDDId][sHandleId] );
8343         },
8344
8345         
8346         getDDById: function(id) {
8347             for (var i in this.ids) {
8348                 if (this.ids[i][id]) {
8349                     return this.ids[i][id];
8350                 }
8351             }
8352             return null;
8353         },
8354
8355         
8356         handleMouseDown: function(e, oDD) {
8357             if(Ext.QuickTips){
8358                 Ext.QuickTips.disable();
8359             }
8360             this.currentTarget = e.getTarget();
8361
8362             this.dragCurrent = oDD;
8363
8364             var el = oDD.getEl();
8365
8366             
8367             this.startX = e.getPageX();
8368             this.startY = e.getPageY();
8369
8370             this.deltaX = this.startX - el.offsetLeft;
8371             this.deltaY = this.startY - el.offsetTop;
8372
8373             this.dragThreshMet = false;
8374
8375             this.clickTimeout = setTimeout(
8376                     function() {
8377                         var DDM = Ext.dd.DDM;
8378                         DDM.startDrag(DDM.startX, DDM.startY);
8379                     },
8380                     this.clickTimeThresh );
8381         },
8382
8383         
8384         startDrag: function(x, y) {
8385             clearTimeout(this.clickTimeout);
8386             if (this.dragCurrent) {
8387                 this.dragCurrent.b4StartDrag(x, y);
8388                 this.dragCurrent.startDrag(x, y);
8389             }
8390             this.dragThreshMet = true;
8391         },
8392
8393         
8394         handleMouseUp: function(e) {
8395
8396             if(Ext.QuickTips){
8397                 Ext.QuickTips.enable();
8398             }
8399             if (! this.dragCurrent) {
8400                 return;
8401             }
8402
8403             clearTimeout(this.clickTimeout);
8404
8405             if (this.dragThreshMet) {
8406                 this.fireEvents(e, true);
8407             } else {
8408             }
8409
8410             this.stopDrag(e);
8411
8412             this.stopEvent(e);
8413         },
8414
8415         
8416         stopEvent: function(e){
8417             if(this.stopPropagation) {
8418                 e.stopPropagation();
8419             }
8420
8421             if (this.preventDefault) {
8422                 e.preventDefault();
8423             }
8424         },
8425
8426         
8427         stopDrag: function(e) {
8428             
8429             if (this.dragCurrent) {
8430                 if (this.dragThreshMet) {
8431                     this.dragCurrent.b4EndDrag(e);
8432                     this.dragCurrent.endDrag(e);
8433                 }
8434
8435                 this.dragCurrent.onMouseUp(e);
8436             }
8437
8438             this.dragCurrent = null;
8439             this.dragOvers = {};
8440         },
8441
8442         
8443         handleMouseMove: function(e) {
8444             if (! this.dragCurrent) {
8445                 return true;
8446             }
8447
8448             
8449
8450             
8451             if (Ext.isIE && (e.button !== 0 && e.button !== 1 && e.button !== 2)) {
8452                 this.stopEvent(e);
8453                 return this.handleMouseUp(e);
8454             }
8455
8456             if (!this.dragThreshMet) {
8457                 var diffX = Math.abs(this.startX - e.getPageX());
8458                 var diffY = Math.abs(this.startY - e.getPageY());
8459                 if (diffX > this.clickPixelThresh ||
8460                             diffY > this.clickPixelThresh) {
8461                     this.startDrag(this.startX, this.startY);
8462                 }
8463             }
8464
8465             if (this.dragThreshMet) {
8466                 this.dragCurrent.b4Drag(e);
8467                 this.dragCurrent.onDrag(e);
8468                 if(!this.dragCurrent.moveOnly){
8469                     this.fireEvents(e, false);
8470                 }
8471             }
8472
8473             this.stopEvent(e);
8474
8475             return true;
8476         },
8477
8478         
8479         fireEvents: function(e, isDrop) {
8480             var dc = this.dragCurrent;
8481
8482             
8483             
8484             if (!dc || dc.isLocked()) {
8485                 return;
8486             }
8487
8488             var pt = e.getPoint();
8489
8490             
8491             var oldOvers = [];
8492
8493             var outEvts   = [];
8494             var overEvts  = [];
8495             var dropEvts  = [];
8496             var enterEvts = [];
8497
8498             
8499             
8500             for (var i in this.dragOvers) {
8501
8502                 var ddo = this.dragOvers[i];
8503
8504                 if (! this.isTypeOfDD(ddo)) {
8505                     continue;
8506                 }
8507
8508                 if (! this.isOverTarget(pt, ddo, this.mode)) {
8509                     outEvts.push( ddo );
8510                 }
8511
8512                 oldOvers[i] = true;
8513                 delete this.dragOvers[i];
8514             }
8515
8516             for (var sGroup in dc.groups) {
8517
8518                 if ("string" != typeof sGroup) {
8519                     continue;
8520                 }
8521
8522                 for (i in this.ids[sGroup]) {
8523                     var oDD = this.ids[sGroup][i];
8524                     if (! this.isTypeOfDD(oDD)) {
8525                         continue;
8526                     }
8527
8528                     if (oDD.isTarget && !oDD.isLocked() && oDD != dc) {
8529                         if (this.isOverTarget(pt, oDD, this.mode)) {
8530                             
8531                             if (isDrop) {
8532                                 dropEvts.push( oDD );
8533                             
8534                             } else {
8535
8536                                 
8537                                 if (!oldOvers[oDD.id]) {
8538                                     enterEvts.push( oDD );
8539                                 
8540                                 } else {
8541                                     overEvts.push( oDD );
8542                                 }
8543
8544                                 this.dragOvers[oDD.id] = oDD;
8545                             }
8546                         }
8547                     }
8548                 }
8549             }
8550
8551             if (this.mode) {
8552                 if (outEvts.length) {
8553                     dc.b4DragOut(e, outEvts);
8554                     dc.onDragOut(e, outEvts);
8555                 }
8556
8557                 if (enterEvts.length) {
8558                     dc.onDragEnter(e, enterEvts);
8559                 }
8560
8561                 if (overEvts.length) {
8562                     dc.b4DragOver(e, overEvts);
8563                     dc.onDragOver(e, overEvts);
8564                 }
8565
8566                 if (dropEvts.length) {
8567                     dc.b4DragDrop(e, dropEvts);
8568                     dc.onDragDrop(e, dropEvts);
8569                 }
8570
8571             } else {
8572                 
8573                 var len = 0;
8574                 for (i=0, len=outEvts.length; i<len; ++i) {
8575                     dc.b4DragOut(e, outEvts[i].id);
8576                     dc.onDragOut(e, outEvts[i].id);
8577                 }
8578
8579                 
8580                 for (i=0,len=enterEvts.length; i<len; ++i) {
8581                     
8582                     dc.onDragEnter(e, enterEvts[i].id);
8583                 }
8584
8585                 
8586                 for (i=0,len=overEvts.length; i<len; ++i) {
8587                     dc.b4DragOver(e, overEvts[i].id);
8588                     dc.onDragOver(e, overEvts[i].id);
8589                 }
8590
8591                 
8592                 for (i=0, len=dropEvts.length; i<len; ++i) {
8593                     dc.b4DragDrop(e, dropEvts[i].id);
8594                     dc.onDragDrop(e, dropEvts[i].id);
8595                 }
8596
8597             }
8598
8599             
8600             if (isDrop && !dropEvts.length) {
8601                 dc.onInvalidDrop(e);
8602             }
8603
8604         },
8605
8606         
8607         getBestMatch: function(dds) {
8608             var winner = null;
8609             
8610             
8611                
8612             
8613             
8614
8615             var len = dds.length;
8616
8617             if (len == 1) {
8618                 winner = dds[0];
8619             } else {
8620                 
8621                 for (var i=0; i<len; ++i) {
8622                     var dd = dds[i];
8623                     
8624                     
8625                     
8626                     if (dd.cursorIsOver) {
8627                         winner = dd;
8628                         break;
8629                     
8630                     } else {
8631                         if (!winner ||
8632                             winner.overlap.getArea() < dd.overlap.getArea()) {
8633                             winner = dd;
8634                         }
8635                     }
8636                 }
8637             }
8638
8639             return winner;
8640         },
8641
8642         
8643         refreshCache: function(groups) {
8644             for (var sGroup in groups) {
8645                 if ("string" != typeof sGroup) {
8646                     continue;
8647                 }
8648                 for (var i in this.ids[sGroup]) {
8649                     var oDD = this.ids[sGroup][i];
8650
8651                     if (this.isTypeOfDD(oDD)) {
8652                     
8653                         var loc = this.getLocation(oDD);
8654                         if (loc) {
8655                             this.locationCache[oDD.id] = loc;
8656                         } else {
8657                             delete this.locationCache[oDD.id];
8658                             
8659                             
8660                             
8661                         }
8662                     }
8663                 }
8664             }
8665         },
8666
8667         
8668         verifyEl: function(el) {
8669             if (el) {
8670                 var parent;
8671                 if(Ext.isIE){
8672                     try{
8673                         parent = el.offsetParent;
8674                     }catch(e){}
8675                 }else{
8676                     parent = el.offsetParent;
8677                 }
8678                 if (parent) {
8679                     return true;
8680                 }
8681             }
8682
8683             return false;
8684         },
8685
8686         
8687         getLocation: function(oDD) {
8688             if (! this.isTypeOfDD(oDD)) {
8689                 return null;
8690             }
8691
8692             var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
8693
8694             try {
8695                 pos= Ext.lib.Dom.getXY(el);
8696             } catch (e) { }
8697
8698             if (!pos) {
8699                 return null;
8700             }
8701
8702             x1 = pos[0];
8703             x2 = x1 + el.offsetWidth;
8704             y1 = pos[1];
8705             y2 = y1 + el.offsetHeight;
8706
8707             t = y1 - oDD.padding[0];
8708             r = x2 + oDD.padding[1];
8709             b = y2 + oDD.padding[2];
8710             l = x1 - oDD.padding[3];
8711
8712             return new Ext.lib.Region( t, r, b, l );
8713         },
8714
8715         
8716         isOverTarget: function(pt, oTarget, intersect) {
8717             
8718             var loc = this.locationCache[oTarget.id];
8719             if (!loc || !this.useCache) {
8720                 loc = this.getLocation(oTarget);
8721                 this.locationCache[oTarget.id] = loc;
8722
8723             }
8724
8725             if (!loc) {
8726                 return false;
8727             }
8728
8729             oTarget.cursorIsOver = loc.contains( pt );
8730
8731             
8732             
8733             
8734             
8735             
8736             var dc = this.dragCurrent;
8737             if (!dc || !dc.getTargetCoord ||
8738                     (!intersect && !dc.constrainX && !dc.constrainY)) {
8739                 return oTarget.cursorIsOver;
8740             }
8741
8742             oTarget.overlap = null;
8743
8744             
8745             
8746             
8747             
8748             var pos = dc.getTargetCoord(pt.x, pt.y);
8749
8750             var el = dc.getDragEl();
8751             var curRegion = new Ext.lib.Region( pos.y,
8752                                                    pos.x + el.offsetWidth,
8753                                                    pos.y + el.offsetHeight,
8754                                                    pos.x );
8755
8756             var overlap = curRegion.intersect(loc);
8757
8758             if (overlap) {
8759                 oTarget.overlap = overlap;
8760                 return (intersect) ? true : oTarget.cursorIsOver;
8761             } else {
8762                 return false;
8763             }
8764         },
8765
8766         
8767         _onUnload: function(e, me) {
8768             Ext.dd.DragDropMgr.unregAll();
8769         },
8770
8771         
8772         unregAll: function() {
8773
8774             if (this.dragCurrent) {
8775                 this.stopDrag();
8776                 this.dragCurrent = null;
8777             }
8778
8779             this._execOnAll("unreg", []);
8780
8781             for (var i in this.elementCache) {
8782                 delete this.elementCache[i];
8783             }
8784
8785             this.elementCache = {};
8786             this.ids = {};
8787         },
8788
8789         
8790         elementCache: {},
8791
8792         
8793         getElWrapper: function(id) {
8794             var oWrapper = this.elementCache[id];
8795             if (!oWrapper || !oWrapper.el) {
8796                 oWrapper = this.elementCache[id] =
8797                     new this.ElementWrapper(Ext.getDom(id));
8798             }
8799             return oWrapper;
8800         },
8801
8802         
8803         getElement: function(id) {
8804             return Ext.getDom(id);
8805         },
8806
8807         
8808         getCss: function(id) {
8809             var el = Ext.getDom(id);
8810             return (el) ? el.style : null;
8811         },
8812
8813         
8814         ElementWrapper: function(el) {
8815                 
8816                 this.el = el || null;
8817                 
8818                 this.id = this.el && el.id;
8819                 
8820                 this.css = this.el && el.style;
8821             },
8822
8823         
8824         getPosX: function(el) {
8825             return Ext.lib.Dom.getX(el);
8826         },
8827
8828         
8829         getPosY: function(el) {
8830             return Ext.lib.Dom.getY(el);
8831         },
8832
8833         
8834         swapNode: function(n1, n2) {
8835             if (n1.swapNode) {
8836                 n1.swapNode(n2);
8837             } else {
8838                 var p = n2.parentNode;
8839                 var s = n2.nextSibling;
8840
8841                 if (s == n1) {
8842                     p.insertBefore(n1, n2);
8843                 } else if (n2 == n1.nextSibling) {
8844                     p.insertBefore(n2, n1);
8845                 } else {
8846                     n1.parentNode.replaceChild(n2, n1);
8847                     p.insertBefore(n1, s);
8848                 }
8849             }
8850         },
8851
8852         
8853         getScroll: function () {
8854             var t, l, dde=document.documentElement, db=document.body;
8855             if (dde && (dde.scrollTop || dde.scrollLeft)) {
8856                 t = dde.scrollTop;
8857                 l = dde.scrollLeft;
8858             } else if (db) {
8859                 t = db.scrollTop;
8860                 l = db.scrollLeft;
8861             } else {
8862
8863             }
8864             return { top: t, left: l };
8865         },
8866
8867         
8868         getStyle: function(el, styleProp) {
8869             return Ext.fly(el).getStyle(styleProp);
8870         },
8871
8872         
8873         getScrollTop: function () { return this.getScroll().top; },
8874
8875         
8876         getScrollLeft: function () { return this.getScroll().left; },
8877
8878         
8879         moveToEl: function (moveEl, targetEl) {
8880             var aCoord = Ext.lib.Dom.getXY(targetEl);
8881             Ext.lib.Dom.setXY(moveEl, aCoord);
8882         },
8883
8884         
8885         numericSort: function(a, b) { return (a - b); },
8886
8887         
8888         _timeoutCount: 0,
8889
8890         
8891         _addListeners: function() {
8892             var DDM = Ext.dd.DDM;
8893             if ( Ext.lib.Event && document ) {
8894                 DDM._onLoad();
8895             } else {
8896                 if (DDM._timeoutCount > 2000) {
8897                 } else {
8898                     setTimeout(DDM._addListeners, 10);
8899                     if (document && document.body) {
8900                         DDM._timeoutCount += 1;
8901                     }
8902                 }
8903             }
8904         },
8905
8906         
8907         handleWasClicked: function(node, id) {
8908             if (this.isHandle(id, node.id)) {
8909                 return true;
8910             } else {
8911                 
8912                 var p = node.parentNode;
8913
8914                 while (p) {
8915                     if (this.isHandle(id, p.id)) {
8916                         return true;
8917                     } else {
8918                         p = p.parentNode;
8919                     }
8920                 }
8921             }
8922
8923             return false;
8924         }
8925
8926     };
8927
8928 }();
8929
8930
8931 Ext.dd.DDM = Ext.dd.DragDropMgr;
8932 Ext.dd.DDM._addListeners();
8933
8934 }
8935
8936
8937 Ext.dd.DD = function(id, sGroup, config) {
8938     if (id) {
8939         this.init(id, sGroup, config);
8940     }
8941 };
8942
8943 Ext.extend(Ext.dd.DD, Ext.dd.DragDrop, {
8944
8945     
8946     scroll: true,
8947
8948     
8949     autoOffset: function(iPageX, iPageY) {
8950         var x = iPageX - this.startPageX;
8951         var y = iPageY - this.startPageY;
8952         this.setDelta(x, y);
8953     },
8954
8955     
8956     setDelta: function(iDeltaX, iDeltaY) {
8957         this.deltaX = iDeltaX;
8958         this.deltaY = iDeltaY;
8959     },
8960
8961     
8962     setDragElPos: function(iPageX, iPageY) {
8963         
8964         
8965
8966         var el = this.getDragEl();
8967         this.alignElWithMouse(el, iPageX, iPageY);
8968     },
8969
8970     
8971     alignElWithMouse: function(el, iPageX, iPageY) {
8972         var oCoord = this.getTargetCoord(iPageX, iPageY);
8973         var fly = el.dom ? el : Ext.fly(el, '_dd');
8974         if (!this.deltaSetXY) {
8975             var aCoord = [oCoord.x, oCoord.y];
8976             fly.setXY(aCoord);
8977             var newLeft = fly.getLeft(true);
8978             var newTop  = fly.getTop(true);
8979             this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ];
8980         } else {
8981             fly.setLeftTop(oCoord.x + this.deltaSetXY[0], oCoord.y + this.deltaSetXY[1]);
8982         }
8983
8984         this.cachePosition(oCoord.x, oCoord.y);
8985         this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
8986         return oCoord;
8987     },
8988
8989     
8990     cachePosition: function(iPageX, iPageY) {
8991         if (iPageX) {
8992             this.lastPageX = iPageX;
8993             this.lastPageY = iPageY;
8994         } else {
8995             var aCoord = Ext.lib.Dom.getXY(this.getEl());
8996             this.lastPageX = aCoord[0];
8997             this.lastPageY = aCoord[1];
8998         }
8999     },
9000
9001     
9002     autoScroll: function(x, y, h, w) {
9003
9004         if (this.scroll) {
9005             
9006             var clientH = Ext.lib.Dom.getViewHeight();
9007
9008             
9009             var clientW = Ext.lib.Dom.getViewWidth();
9010
9011             
9012             var st = this.DDM.getScrollTop();
9013
9014             
9015             var sl = this.DDM.getScrollLeft();
9016
9017             
9018             var bot = h + y;
9019
9020             
9021             var right = w + x;
9022
9023             
9024             
9025             
9026             var toBot = (clientH + st - y - this.deltaY);
9027
9028             
9029             var toRight = (clientW + sl - x - this.deltaX);
9030
9031
9032             
9033             
9034             var thresh = 40;
9035
9036             
9037             
9038             
9039             var scrAmt = (document.all) ? 80 : 30;
9040
9041             
9042             
9043             if ( bot > clientH && toBot < thresh ) {
9044                 window.scrollTo(sl, st + scrAmt);
9045             }
9046
9047             
9048             
9049             if ( y < st && st > 0 && y - st < thresh ) {
9050                 window.scrollTo(sl, st - scrAmt);
9051             }
9052
9053             
9054             
9055             if ( right > clientW && toRight < thresh ) {
9056                 window.scrollTo(sl + scrAmt, st);
9057             }
9058
9059             
9060             
9061             if ( x < sl && sl > 0 && x - sl < thresh ) {
9062                 window.scrollTo(sl - scrAmt, st);
9063             }
9064         }
9065     },
9066
9067     
9068     getTargetCoord: function(iPageX, iPageY) {
9069
9070
9071         var x = iPageX - this.deltaX;
9072         var y = iPageY - this.deltaY;
9073
9074         if (this.constrainX) {
9075             if (x < this.minX) { x = this.minX; }
9076             if (x > this.maxX) { x = this.maxX; }
9077         }
9078
9079         if (this.constrainY) {
9080             if (y < this.minY) { y = this.minY; }
9081             if (y > this.maxY) { y = this.maxY; }
9082         }
9083
9084         x = this.getTick(x, this.xTicks);
9085         y = this.getTick(y, this.yTicks);
9086
9087
9088         return {x:x, y:y};
9089     },
9090
9091     
9092     applyConfig: function() {
9093         Ext.dd.DD.superclass.applyConfig.call(this);
9094         this.scroll = (this.config.scroll !== false);
9095     },
9096
9097     
9098     b4MouseDown: function(e) {
9099         
9100         this.autoOffset(e.getPageX(),
9101                             e.getPageY());
9102     },
9103
9104     
9105     b4Drag: function(e) {
9106         this.setDragElPos(e.getPageX(),
9107                             e.getPageY());
9108     },
9109
9110     toString: function() {
9111         return ("DD " + this.id);
9112     }
9113
9114     
9115     
9116     
9117     
9118
9119 });
9120
9121 Ext.dd.DDProxy = function(id, sGroup, config) {
9122     if (id) {
9123         this.init(id, sGroup, config);
9124         this.initFrame();
9125     }
9126 };
9127
9128
9129 Ext.dd.DDProxy.dragElId = "ygddfdiv";
9130
9131 Ext.extend(Ext.dd.DDProxy, Ext.dd.DD, {
9132
9133     
9134     resizeFrame: true,
9135
9136     
9137     centerFrame: false,
9138
9139     
9140     createFrame: function() {
9141         var self = this;
9142         var body = document.body;
9143
9144         if (!body || !body.firstChild) {
9145             setTimeout( function() { self.createFrame(); }, 50 );
9146             return;
9147         }
9148
9149         var div = this.getDragEl();
9150
9151         if (!div) {
9152             div    = document.createElement("div");
9153             div.id = this.dragElId;
9154             var s  = div.style;
9155
9156             s.position   = "absolute";
9157             s.visibility = "hidden";
9158             s.cursor     = "move";
9159             s.border     = "2px solid #aaa";
9160             s.zIndex     = 999;
9161
9162             
9163             
9164             
9165             body.insertBefore(div, body.firstChild);
9166         }
9167     },
9168
9169     
9170     initFrame: function() {
9171         this.createFrame();
9172     },
9173
9174     applyConfig: function() {
9175         Ext.dd.DDProxy.superclass.applyConfig.call(this);
9176
9177         this.resizeFrame = (this.config.resizeFrame !== false);
9178         this.centerFrame = (this.config.centerFrame);
9179         this.setDragElId(this.config.dragElId || Ext.dd.DDProxy.dragElId);
9180     },
9181
9182     
9183     showFrame: function(iPageX, iPageY) {
9184         var el = this.getEl();
9185         var dragEl = this.getDragEl();
9186         var s = dragEl.style;
9187
9188         this._resizeProxy();
9189
9190         if (this.centerFrame) {
9191             this.setDelta( Math.round(parseInt(s.width,  10)/2),
9192                            Math.round(parseInt(s.height, 10)/2) );
9193         }
9194
9195         this.setDragElPos(iPageX, iPageY);
9196
9197         Ext.fly(dragEl).show();
9198     },
9199
9200     
9201     _resizeProxy: function() {
9202         if (this.resizeFrame) {
9203             var el = this.getEl();
9204             Ext.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);
9205         }
9206     },
9207
9208     
9209     b4MouseDown: function(e) {
9210         var x = e.getPageX();
9211         var y = e.getPageY();
9212         this.autoOffset(x, y);
9213         this.setDragElPos(x, y);
9214     },
9215
9216     
9217     b4StartDrag: function(x, y) {
9218         
9219         this.showFrame(x, y);
9220     },
9221
9222     
9223     b4EndDrag: function(e) {
9224         Ext.fly(this.getDragEl()).hide();
9225     },
9226
9227     
9228     
9229     
9230     endDrag: function(e) {
9231
9232         var lel = this.getEl();
9233         var del = this.getDragEl();
9234
9235         
9236         del.style.visibility = "";
9237
9238         this.beforeMove();
9239         
9240         
9241         lel.style.visibility = "hidden";
9242         Ext.dd.DDM.moveToEl(lel, del);
9243         del.style.visibility = "hidden";
9244         lel.style.visibility = "";
9245
9246         this.afterDrag();
9247     },
9248
9249     beforeMove : function(){
9250
9251     },
9252
9253     afterDrag : function(){
9254
9255     },
9256
9257     toString: function() {
9258         return ("DDProxy " + this.id);
9259     }
9260
9261 });
9262
9263 Ext.dd.DDTarget = function(id, sGroup, config) {
9264     if (id) {
9265         this.initTarget(id, sGroup, config);
9266     }
9267 };
9268
9269
9270 Ext.extend(Ext.dd.DDTarget, Ext.dd.DragDrop, {
9271     toString: function() {
9272         return ("DDTarget " + this.id);
9273     }
9274 });
9275
9276 Ext.dd.DragTracker = function(config){
9277     Ext.apply(this, config);
9278     this.addEvents(
9279         'mousedown',
9280         'mouseup',
9281         'mousemove',
9282         'dragstart',
9283         'dragend',
9284         'drag'
9285     );
9286
9287     this.dragRegion = new Ext.lib.Region(0,0,0,0);
9288
9289     if(this.el){
9290         this.initEl(this.el);
9291     }
9292 }
9293
9294 Ext.extend(Ext.dd.DragTracker, Ext.util.Observable,  {
9295     active: false,
9296     tolerance: 5,
9297     autoStart: false,
9298
9299     initEl: function(el){
9300         this.el = Ext.get(el);
9301         el.on('mousedown', this.onMouseDown, this,
9302                 this.delegate ? {delegate: this.delegate} : undefined);
9303     },
9304
9305     destroy : function(){
9306         this.el.un('mousedown', this.onMouseDown, this);
9307     },
9308
9309     onMouseDown: function(e, target){
9310         if(this.fireEvent('mousedown', this, e) !== false && this.onBeforeStart(e) !== false){
9311             this.startXY = this.lastXY = e.getXY();
9312             this.dragTarget = this.delegate ? target : this.el.dom;
9313             e.preventDefault();
9314             var doc = Ext.getDoc();
9315             doc.on('mouseup', this.onMouseUp, this);
9316             doc.on('mousemove', this.onMouseMove, this);
9317             doc.on('selectstart', this.stopSelect, this);
9318             if(this.autoStart){
9319                 this.timer = this.triggerStart.defer(this.autoStart === true ? 1000 : this.autoStart, this);
9320             }
9321         }
9322     },
9323
9324     onMouseMove: function(e, target){
9325         e.preventDefault();
9326         var xy = e.getXY(), s = this.startXY;
9327         this.lastXY = xy;
9328         if(!this.active){
9329             if(Math.abs(s[0]-xy[0]) > this.tolerance || Math.abs(s[1]-xy[1]) > this.tolerance){
9330                 this.triggerStart();
9331             }else{
9332                 return;
9333             }
9334         }
9335         this.fireEvent('mousemove', this, e);
9336         this.onDrag(e);
9337         this.fireEvent('drag', this, e);
9338     },
9339
9340     onMouseUp: function(e){
9341         var doc = Ext.getDoc();
9342         doc.un('mousemove', this.onMouseMove, this);
9343         doc.un('mouseup', this.onMouseUp, this);
9344         doc.un('selectstart', this.stopSelect, this);
9345         e.preventDefault();
9346         this.clearStart();
9347         this.active = false;
9348         delete this.elRegion;
9349         this.fireEvent('mouseup', this, e);
9350         this.onEnd(e);
9351         this.fireEvent('dragend', this, e);
9352     },
9353
9354     triggerStart: function(isTimer){
9355         this.clearStart();
9356         this.active = true;
9357         this.onStart(this.startXY);
9358         this.fireEvent('dragstart', this, this.startXY);
9359     },
9360
9361     clearStart : function(){
9362         if(this.timer){
9363             clearTimeout(this.timer);
9364             delete this.timer;
9365         }
9366     },
9367
9368     stopSelect : function(e){
9369         e.stopEvent();
9370         return false;
9371     },
9372
9373     onBeforeStart : function(e){
9374
9375     },
9376
9377     onStart : function(xy){
9378
9379     },
9380
9381     onDrag : function(e){
9382
9383     },
9384
9385     onEnd : function(e){
9386
9387     },
9388
9389     getDragTarget : function(){
9390         return this.dragTarget;
9391     },
9392
9393     getDragCt : function(){
9394         return this.el;
9395     },
9396
9397     getXY : function(constrain){
9398         return constrain ?
9399                this.constrainModes[constrain].call(this, this.lastXY) : this.lastXY;
9400     },
9401
9402     getOffset : function(constrain){
9403         var xy = this.getXY(constrain);
9404         var s = this.startXY;
9405         return [s[0]-xy[0], s[1]-xy[1]];
9406     },
9407
9408     constrainModes: {
9409         'point' : function(xy){
9410
9411             if(!this.elRegion){
9412                 this.elRegion = this.getDragCt().getRegion();
9413             }
9414
9415             var dr = this.dragRegion;
9416
9417             dr.left = xy[0];
9418             dr.top = xy[1];
9419             dr.right = xy[0];
9420             dr.bottom = xy[1];
9421
9422             dr.constrainTo(this.elRegion);
9423
9424             return [dr.left, dr.top];
9425         }
9426     }
9427 });
9428
9429 Ext.dd.ScrollManager = function(){
9430     var ddm = Ext.dd.DragDropMgr;
9431     var els = {};
9432     var dragEl = null;
9433     var proc = {};
9434     
9435     var onStop = function(e){
9436         dragEl = null;
9437         clearProc();
9438     };
9439     
9440     var triggerRefresh = function(){
9441         if(ddm.dragCurrent){
9442              ddm.refreshCache(ddm.dragCurrent.groups);
9443         }
9444     };
9445     
9446     var doScroll = function(){
9447         if(ddm.dragCurrent){
9448             var dds = Ext.dd.ScrollManager;
9449             var inc = proc.el.ddScrollConfig ?
9450                       proc.el.ddScrollConfig.increment : dds.increment;
9451             if(!dds.animate){
9452                 if(proc.el.scroll(proc.dir, inc)){
9453                     triggerRefresh();
9454                 }
9455             }else{
9456                 proc.el.scroll(proc.dir, inc, true, dds.animDuration, triggerRefresh);
9457             }
9458         }
9459     };
9460     
9461     var clearProc = function(){
9462         if(proc.id){
9463             clearInterval(proc.id);
9464         }
9465         proc.id = 0;
9466         proc.el = null;
9467         proc.dir = "";
9468     };
9469     
9470     var startProc = function(el, dir){
9471         clearProc();
9472         proc.el = el;
9473         proc.dir = dir;
9474         proc.id = setInterval(doScroll, Ext.dd.ScrollManager.frequency);
9475     };
9476     
9477     var onFire = function(e, isDrop){
9478         if(isDrop || !ddm.dragCurrent){ return; }
9479         var dds = Ext.dd.ScrollManager;
9480         if(!dragEl || dragEl != ddm.dragCurrent){
9481             dragEl = ddm.dragCurrent;
9482             
9483             dds.refreshCache();
9484         }
9485         
9486         var xy = Ext.lib.Event.getXY(e);
9487         var pt = new Ext.lib.Point(xy[0], xy[1]);
9488         for(var id in els){
9489             var el = els[id], r = el._region;
9490             var c = el.ddScrollConfig ? el.ddScrollConfig : dds;
9491             if(r && r.contains(pt) && el.isScrollable()){
9492                 if(r.bottom - pt.y <= c.vthresh){
9493                     if(proc.el != el){
9494                         startProc(el, "down");
9495                     }
9496                     return;
9497                 }else if(r.right - pt.x <= c.hthresh){
9498                     if(proc.el != el){
9499                         startProc(el, "left");
9500                     }
9501                     return;
9502                 }else if(pt.y - r.top <= c.vthresh){
9503                     if(proc.el != el){
9504                         startProc(el, "up");
9505                     }
9506                     return;
9507                 }else if(pt.x - r.left <= c.hthresh){
9508                     if(proc.el != el){
9509                         startProc(el, "right");
9510                     }
9511                     return;
9512                 }
9513             }
9514         }
9515         clearProc();
9516     };
9517     
9518     ddm.fireEvents = ddm.fireEvents.createSequence(onFire, ddm);
9519     ddm.stopDrag = ddm.stopDrag.createSequence(onStop, ddm);
9520     
9521     return {
9522         
9523         register : function(el){
9524             if(Ext.isArray(el)){
9525                 for(var i = 0, len = el.length; i < len; i++) {
9526                         this.register(el[i]);
9527                 }
9528             }else{
9529                 el = Ext.get(el);
9530                 els[el.id] = el;
9531             }
9532         },
9533         
9534         
9535         unregister : function(el){
9536             if(Ext.isArray(el)){
9537                 for(var i = 0, len = el.length; i < len; i++) {
9538                         this.unregister(el[i]);
9539                 }
9540             }else{
9541                 el = Ext.get(el);
9542                 delete els[el.id];
9543             }
9544         },
9545         
9546         
9547         vthresh : 25,
9548         
9549         hthresh : 25,
9550
9551         
9552         increment : 100,
9553         
9554         
9555         frequency : 500,
9556         
9557         
9558         animate: true,
9559         
9560         
9561         animDuration: .4,
9562         
9563         
9564         refreshCache : function(){
9565             for(var id in els){
9566                 if(typeof els[id] == 'object'){ 
9567                     els[id]._region = els[id].getRegion();
9568                 }
9569             }
9570         }
9571     };
9572 }();
9573
9574 Ext.dd.Registry = function(){
9575     var elements = {}; 
9576     var handles = {}; 
9577     var autoIdSeed = 0;
9578
9579     var getId = function(el, autogen){
9580         if(typeof el == "string"){
9581             return el;
9582         }
9583         var id = el.id;
9584         if(!id && autogen !== false){
9585             id = "extdd-" + (++autoIdSeed);
9586             el.id = id;
9587         }
9588         return id;
9589     };
9590     
9591     return {
9592     
9593         register : function(el, data){
9594             data = data || {};
9595             if(typeof el == "string"){
9596                 el = document.getElementById(el);
9597             }
9598             data.ddel = el;
9599             elements[getId(el)] = data;
9600             if(data.isHandle !== false){
9601                 handles[data.ddel.id] = data;
9602             }
9603             if(data.handles){
9604                 var hs = data.handles;
9605                 for(var i = 0, len = hs.length; i < len; i++){
9606                         handles[getId(hs[i])] = data;
9607                 }
9608             }
9609         },
9610
9611     
9612         unregister : function(el){
9613             var id = getId(el, false);
9614             var data = elements[id];
9615             if(data){
9616                 delete elements[id];
9617                 if(data.handles){
9618                     var hs = data.handles;
9619                     for(var i = 0, len = hs.length; i < len; i++){
9620                         delete handles[getId(hs[i], false)];
9621                     }
9622                 }
9623             }
9624         },
9625
9626     
9627         getHandle : function(id){
9628             if(typeof id != "string"){ 
9629                 id = id.id;
9630             }
9631             return handles[id];
9632         },
9633
9634     
9635         getHandleFromEvent : function(e){
9636             var t = Ext.lib.Event.getTarget(e);
9637             return t ? handles[t.id] : null;
9638         },
9639
9640     
9641         getTarget : function(id){
9642             if(typeof id != "string"){ 
9643                 id = id.id;
9644             }
9645             return elements[id];
9646         },
9647
9648     
9649         getTargetFromEvent : function(e){
9650             var t = Ext.lib.Event.getTarget(e);
9651             return t ? elements[t.id] || handles[t.id] : null;
9652         }
9653     };
9654 }();
9655
9656 Ext.dd.StatusProxy = function(config){
9657     Ext.apply(this, config);
9658     this.id = this.id || Ext.id();
9659     this.el = new Ext.Layer({
9660         dh: {
9661             id: this.id, tag: "div", cls: "x-dd-drag-proxy "+this.dropNotAllowed, children: [
9662                 {tag: "div", cls: "x-dd-drop-icon"},
9663                 {tag: "div", cls: "x-dd-drag-ghost"}
9664             ]
9665         }, 
9666         shadow: !config || config.shadow !== false
9667     });
9668     this.ghost = Ext.get(this.el.dom.childNodes[1]);
9669     this.dropStatus = this.dropNotAllowed;
9670 };
9671
9672 Ext.dd.StatusProxy.prototype = {
9673     
9674     dropAllowed : "x-dd-drop-ok",
9675     
9676     dropNotAllowed : "x-dd-drop-nodrop",
9677
9678     
9679     setStatus : function(cssClass){
9680         cssClass = cssClass || this.dropNotAllowed;
9681         if(this.dropStatus != cssClass){
9682             this.el.replaceClass(this.dropStatus, cssClass);
9683             this.dropStatus = cssClass;
9684         }
9685     },
9686
9687     
9688     reset : function(clearGhost){
9689         this.el.dom.className = "x-dd-drag-proxy " + this.dropNotAllowed;
9690         this.dropStatus = this.dropNotAllowed;
9691         if(clearGhost){
9692             this.ghost.update("");
9693         }
9694     },
9695
9696     
9697     update : function(html){
9698         if(typeof html == "string"){
9699             this.ghost.update(html);
9700         }else{
9701             this.ghost.update("");
9702             html.style.margin = "0";
9703             this.ghost.dom.appendChild(html);
9704         }        
9705     },
9706
9707     
9708     getEl : function(){
9709         return this.el;
9710     },
9711
9712     
9713     getGhost : function(){
9714         return this.ghost;
9715     },
9716
9717     
9718     hide : function(clear){
9719         this.el.hide();
9720         if(clear){
9721             this.reset(true);
9722         }
9723     },
9724
9725     
9726     stop : function(){
9727         if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){
9728             this.anim.stop();
9729         }
9730     },
9731
9732     
9733     show : function(){
9734         this.el.show();
9735     },
9736
9737     
9738     sync : function(){
9739         this.el.sync();
9740     },
9741
9742     
9743     repair : function(xy, callback, scope){
9744         this.callback = callback;
9745         this.scope = scope;
9746         if(xy && this.animRepair !== false){
9747             this.el.addClass("x-dd-drag-repair");
9748             this.el.hideUnders(true);
9749             this.anim = this.el.shift({
9750                 duration: this.repairDuration || .5,
9751                 easing: 'easeOut',
9752                 xy: xy,
9753                 stopFx: true,
9754                 callback: this.afterRepair,
9755                 scope: this
9756             });
9757         }else{
9758             this.afterRepair();
9759         }
9760     },
9761
9762     
9763     afterRepair : function(){
9764         this.hide(true);
9765         if(typeof this.callback == "function"){
9766             this.callback.call(this.scope || this);
9767         }
9768         this.callback = null;
9769         this.scope = null;
9770     }
9771 };
9772
9773 Ext.dd.DragSource = function(el, config){
9774     this.el = Ext.get(el);
9775     if(!this.dragData){
9776         this.dragData = {};
9777     }
9778     
9779     Ext.apply(this, config);
9780     
9781     if(!this.proxy){
9782         this.proxy = new Ext.dd.StatusProxy();
9783     }
9784     Ext.dd.DragSource.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group, 
9785           {dragElId : this.proxy.id, resizeFrame: false, isTarget: false, scroll: this.scroll === true});
9786     
9787     this.dragging = false;
9788 };
9789
9790 Ext.extend(Ext.dd.DragSource, Ext.dd.DDProxy, {
9791     
9792     
9793     dropAllowed : "x-dd-drop-ok",
9794     
9795     dropNotAllowed : "x-dd-drop-nodrop",
9796
9797     
9798     getDragData : function(e){
9799         return this.dragData;
9800     },
9801
9802     
9803     onDragEnter : function(e, id){
9804         var target = Ext.dd.DragDropMgr.getDDById(id);
9805         this.cachedTarget = target;
9806         if(this.beforeDragEnter(target, e, id) !== false){
9807             if(target.isNotifyTarget){
9808                 var status = target.notifyEnter(this, e, this.dragData);
9809                 this.proxy.setStatus(status);
9810             }else{
9811                 this.proxy.setStatus(this.dropAllowed);
9812             }
9813             
9814             if(this.afterDragEnter){
9815                 
9816                 this.afterDragEnter(target, e, id);
9817             }
9818         }
9819     },
9820
9821     
9822     beforeDragEnter : function(target, e, id){
9823         return true;
9824     },
9825
9826     
9827     alignElWithMouse: function() {
9828         Ext.dd.DragSource.superclass.alignElWithMouse.apply(this, arguments);
9829         this.proxy.sync();
9830     },
9831
9832     
9833     onDragOver : function(e, id){
9834         var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
9835         if(this.beforeDragOver(target, e, id) !== false){
9836             if(target.isNotifyTarget){
9837                 var status = target.notifyOver(this, e, this.dragData);
9838                 this.proxy.setStatus(status);
9839             }
9840
9841             if(this.afterDragOver){
9842                 
9843                 this.afterDragOver(target, e, id);
9844             }
9845         }
9846     },
9847
9848     
9849     beforeDragOver : function(target, e, id){
9850         return true;
9851     },
9852
9853     
9854     onDragOut : function(e, id){
9855         var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
9856         if(this.beforeDragOut(target, e, id) !== false){
9857             if(target.isNotifyTarget){
9858                 target.notifyOut(this, e, this.dragData);
9859             }
9860             this.proxy.reset();
9861             if(this.afterDragOut){
9862                 
9863                 this.afterDragOut(target, e, id);
9864             }
9865         }
9866         this.cachedTarget = null;
9867     },
9868
9869     
9870     beforeDragOut : function(target, e, id){
9871         return true;
9872     },
9873     
9874     
9875     onDragDrop : function(e, id){
9876         var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
9877         if(this.beforeDragDrop(target, e, id) !== false){
9878             if(target.isNotifyTarget){
9879                 if(target.notifyDrop(this, e, this.dragData)){ 
9880                     this.onValidDrop(target, e, id);
9881                 }else{
9882                     this.onInvalidDrop(target, e, id);
9883                 }
9884             }else{
9885                 this.onValidDrop(target, e, id);
9886             }
9887             
9888             if(this.afterDragDrop){
9889                 
9890                 this.afterDragDrop(target, e, id);
9891             }
9892         }
9893         delete this.cachedTarget;
9894     },
9895
9896     
9897     beforeDragDrop : function(target, e, id){
9898         return true;
9899     },
9900
9901     
9902     onValidDrop : function(target, e, id){
9903         this.hideProxy();
9904         if(this.afterValidDrop){
9905             
9906             this.afterValidDrop(target, e, id);
9907         }
9908     },
9909
9910     
9911     getRepairXY : function(e, data){
9912         return this.el.getXY();  
9913     },
9914
9915     
9916     onInvalidDrop : function(target, e, id){
9917         this.beforeInvalidDrop(target, e, id);
9918         if(this.cachedTarget){
9919             if(this.cachedTarget.isNotifyTarget){
9920                 this.cachedTarget.notifyOut(this, e, this.dragData);
9921             }
9922             this.cacheTarget = null;
9923         }
9924         this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);
9925
9926         if(this.afterInvalidDrop){
9927             
9928             this.afterInvalidDrop(e, id);
9929         }
9930     },
9931
9932     
9933     afterRepair : function(){
9934         if(Ext.enableFx){
9935             this.el.highlight(this.hlColor || "c3daf9");
9936         }
9937         this.dragging = false;
9938     },
9939
9940     
9941     beforeInvalidDrop : function(target, e, id){
9942         return true;
9943     },
9944
9945     
9946     handleMouseDown : function(e){
9947         if(this.dragging) {
9948             return;
9949         }
9950         var data = this.getDragData(e);
9951         if(data && this.onBeforeDrag(data, e) !== false){
9952             this.dragData = data;
9953             this.proxy.stop();
9954             Ext.dd.DragSource.superclass.handleMouseDown.apply(this, arguments);
9955         } 
9956     },
9957
9958     
9959     onBeforeDrag : function(data, e){
9960         return true;
9961     },
9962
9963     
9964     onStartDrag : Ext.emptyFn,
9965
9966     
9967     startDrag : function(x, y){
9968         this.proxy.reset();
9969         this.dragging = true;
9970         this.proxy.update("");
9971         this.onInitDrag(x, y);
9972         this.proxy.show();
9973     },
9974
9975     
9976     onInitDrag : function(x, y){
9977         var clone = this.el.dom.cloneNode(true);
9978         clone.id = Ext.id(); 
9979         this.proxy.update(clone);
9980         this.onStartDrag(x, y);
9981         return true;
9982     },
9983
9984     
9985     getProxy : function(){
9986         return this.proxy;  
9987     },
9988
9989     
9990     hideProxy : function(){
9991         this.proxy.hide();  
9992         this.proxy.reset(true);
9993         this.dragging = false;
9994     },
9995
9996     
9997     triggerCacheRefresh : function(){
9998         Ext.dd.DDM.refreshCache(this.groups);
9999     },
10000
10001     
10002     b4EndDrag: function(e) {
10003     },
10004
10005     
10006     endDrag : function(e){
10007         this.onEndDrag(this.dragData, e);
10008     },
10009
10010     
10011     onEndDrag : function(data, e){
10012     },
10013     
10014     
10015     autoOffset : function(x, y) {
10016         this.setDelta(-12, -20);
10017     }    
10018 });
10019
10020 Ext.dd.DropTarget = function(el, config){
10021     this.el = Ext.get(el);
10022     
10023     Ext.apply(this, config);
10024     
10025     if(this.containerScroll){
10026         Ext.dd.ScrollManager.register(this.el);
10027     }
10028     
10029     Ext.dd.DropTarget.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group, 
10030           {isTarget: true});
10031
10032 };
10033
10034 Ext.extend(Ext.dd.DropTarget, Ext.dd.DDTarget, {
10035     
10036     
10037     
10038     dropAllowed : "x-dd-drop-ok",
10039     
10040     dropNotAllowed : "x-dd-drop-nodrop",
10041
10042     
10043     isTarget : true,
10044
10045     
10046     isNotifyTarget : true,
10047
10048     
10049     notifyEnter : function(dd, e, data){
10050         if(this.overClass){
10051             this.el.addClass(this.overClass);
10052         }
10053         return this.dropAllowed;
10054     },
10055
10056     
10057     notifyOver : function(dd, e, data){
10058         return this.dropAllowed;
10059     },
10060
10061     
10062     notifyOut : function(dd, e, data){
10063         if(this.overClass){
10064             this.el.removeClass(this.overClass);
10065         }
10066     },
10067
10068     
10069     notifyDrop : function(dd, e, data){
10070         return false;
10071     }
10072 });
10073
10074 Ext.dd.DragZone = function(el, config){
10075     Ext.dd.DragZone.superclass.constructor.call(this, el, config);
10076     if(this.containerScroll){
10077         Ext.dd.ScrollManager.register(this.el);
10078     }
10079 };
10080
10081 Ext.extend(Ext.dd.DragZone, Ext.dd.DragSource, {
10082     
10083     
10084
10085     
10086     getDragData : function(e){
10087         return Ext.dd.Registry.getHandleFromEvent(e);
10088     },
10089     
10090     
10091     onInitDrag : function(x, y){
10092         this.proxy.update(this.dragData.ddel.cloneNode(true));
10093         this.onStartDrag(x, y);
10094         return true;
10095     },
10096     
10097     
10098     afterRepair : function(){
10099         if(Ext.enableFx){
10100             Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
10101         }
10102         this.dragging = false;
10103     },
10104
10105     
10106     getRepairXY : function(e){
10107         return Ext.Element.fly(this.dragData.ddel).getXY();  
10108     }
10109 });
10110
10111 Ext.dd.DropZone = function(el, config){
10112     Ext.dd.DropZone.superclass.constructor.call(this, el, config);
10113 };
10114
10115 Ext.extend(Ext.dd.DropZone, Ext.dd.DropTarget, {
10116     
10117     getTargetFromEvent : function(e){
10118         return Ext.dd.Registry.getTargetFromEvent(e);
10119     },
10120
10121     
10122     onNodeEnter : function(n, dd, e, data){
10123         
10124     },
10125
10126     
10127     onNodeOver : function(n, dd, e, data){
10128         return this.dropAllowed;
10129     },
10130
10131     
10132     onNodeOut : function(n, dd, e, data){
10133         
10134     },
10135
10136     
10137     onNodeDrop : function(n, dd, e, data){
10138         return false;
10139     },
10140
10141     
10142     onContainerOver : function(dd, e, data){
10143         return this.dropNotAllowed;
10144     },
10145
10146     
10147     onContainerDrop : function(dd, e, data){
10148         return false;
10149     },
10150
10151     
10152     notifyEnter : function(dd, e, data){
10153         return this.dropNotAllowed;
10154     },
10155
10156     
10157     notifyOver : function(dd, e, data){
10158         var n = this.getTargetFromEvent(e);
10159         if(!n){ 
10160             if(this.lastOverNode){
10161                 this.onNodeOut(this.lastOverNode, dd, e, data);
10162                 this.lastOverNode = null;
10163             }
10164             return this.onContainerOver(dd, e, data);
10165         }
10166         if(this.lastOverNode != n){
10167             if(this.lastOverNode){
10168                 this.onNodeOut(this.lastOverNode, dd, e, data);
10169             }
10170             this.onNodeEnter(n, dd, e, data);
10171             this.lastOverNode = n;
10172         }
10173         return this.onNodeOver(n, dd, e, data);
10174     },
10175
10176     
10177     notifyOut : function(dd, e, data){
10178         if(this.lastOverNode){
10179             this.onNodeOut(this.lastOverNode, dd, e, data);
10180             this.lastOverNode = null;
10181         }
10182     },
10183
10184     
10185     notifyDrop : function(dd, e, data){
10186         if(this.lastOverNode){
10187             this.onNodeOut(this.lastOverNode, dd, e, data);
10188             this.lastOverNode = null;
10189         }
10190         var n = this.getTargetFromEvent(e);
10191         return n ?
10192             this.onNodeDrop(n, dd, e, data) :
10193             this.onContainerDrop(dd, e, data);
10194     },
10195
10196     
10197     triggerCacheRefresh : function(){
10198         Ext.dd.DDM.refreshCache(this.groups);
10199     }  
10200 });
10201
10202
10203 Ext.data.SortTypes = {
10204     
10205     none : function(s){
10206         return s;
10207     },
10208     
10209     
10210     stripTagsRE : /<\/?[^>]+>/gi,
10211     
10212     
10213     asText : function(s){
10214         return String(s).replace(this.stripTagsRE, "");
10215     },
10216     
10217     
10218     asUCText : function(s){
10219         return String(s).toUpperCase().replace(this.stripTagsRE, "");
10220     },
10221     
10222     
10223     asUCString : function(s) {
10224         return String(s).toUpperCase();
10225     },
10226     
10227     
10228     asDate : function(s) {
10229         if(!s){
10230             return 0;
10231         }
10232         if(Ext.isDate(s)){
10233             return s.getTime();
10234         }
10235         return Date.parse(String(s));
10236     },
10237     
10238     
10239     asFloat : function(s) {
10240         var val = parseFloat(String(s).replace(/,/g, ""));
10241         if(isNaN(val)) val = 0;
10242         return val;
10243     },
10244     
10245     
10246     asInt : function(s) {
10247         var val = parseInt(String(s).replace(/,/g, ""));
10248         if(isNaN(val)) val = 0;
10249         return val;
10250     }
10251 };
10252
10253 Ext.data.Record = function(data, id){
10254     this.id = (id || id === 0) ? id : ++Ext.data.Record.AUTO_ID;
10255     this.data = data;
10256 };
10257
10258
10259 Ext.data.Record.create = function(o){
10260     var f = Ext.extend(Ext.data.Record, {});
10261         var p = f.prototype;
10262     p.fields = new Ext.util.MixedCollection(false, function(field){
10263         return field.name;
10264     });
10265     for(var i = 0, len = o.length; i < len; i++){
10266         p.fields.add(new Ext.data.Field(o[i]));
10267     }
10268     f.getField = function(name){
10269         return p.fields.get(name);
10270     };
10271     return f;
10272 };
10273
10274 Ext.data.Record.AUTO_ID = 1000;
10275 Ext.data.Record.EDIT = 'edit';
10276 Ext.data.Record.REJECT = 'reject';
10277 Ext.data.Record.COMMIT = 'commit';
10278
10279 Ext.data.Record.prototype = {
10280         
10281     
10282     
10283     dirty : false,
10284     editing : false,
10285     error: null,
10286     
10287     modified: null,
10288
10289     
10290     join : function(store){
10291         this.store = store;
10292     },
10293
10294     
10295     set : function(name, value){
10296         if(String(this.data[name]) == String(value)){
10297             return;
10298         }
10299         this.dirty = true;
10300         if(!this.modified){
10301             this.modified = {};
10302         }
10303         if(typeof this.modified[name] == 'undefined'){
10304             this.modified[name] = this.data[name];
10305         }
10306         this.data[name] = value;
10307         if(!this.editing && this.store){
10308             this.store.afterEdit(this);
10309         }
10310     },
10311
10312     
10313     get : function(name){
10314         return this.data[name];
10315     },
10316
10317     
10318     beginEdit : function(){
10319         this.editing = true;
10320         this.modified = {};
10321     },
10322
10323     
10324     cancelEdit : function(){
10325         this.editing = false;
10326         delete this.modified;
10327     },
10328
10329     
10330     endEdit : function(){
10331         this.editing = false;
10332         if(this.dirty && this.store){
10333             this.store.afterEdit(this);
10334         }
10335     },
10336
10337     
10338     reject : function(silent){
10339         var m = this.modified;
10340         for(var n in m){
10341             if(typeof m[n] != "function"){
10342                 this.data[n] = m[n];
10343             }
10344         }
10345         this.dirty = false;
10346         delete this.modified;
10347         this.editing = false;
10348         if(this.store && silent !== true){
10349             this.store.afterReject(this);
10350         }
10351     },
10352
10353     
10354     commit : function(silent){
10355         this.dirty = false;
10356         delete this.modified;
10357         this.editing = false;
10358         if(this.store && silent !== true){
10359             this.store.afterCommit(this);
10360         }
10361     },
10362
10363     
10364     getChanges : function(){
10365         var m = this.modified, cs = {};
10366         for(var n in m){
10367             if(m.hasOwnProperty(n)){
10368                 cs[n] = this.data[n];
10369             }
10370         }
10371         return cs;
10372     },
10373
10374     
10375     hasError : function(){
10376         return this.error != null;
10377     },
10378
10379     
10380     clearError : function(){
10381         this.error = null;
10382     },
10383
10384     
10385     copy : function(newId) {
10386         return new this.constructor(Ext.apply({}, this.data), newId || this.id);
10387     },
10388
10389     
10390     isModified : function(fieldName){
10391         return this.modified && this.modified.hasOwnProperty(fieldName);
10392     }
10393 };
10394
10395 Ext.StoreMgr = Ext.apply(new Ext.util.MixedCollection(), {
10396     register : function(){
10397         for(var i = 0, s; s = arguments[i]; i++){
10398             this.add(s);
10399         }
10400     },
10401
10402     unregister : function(){
10403         for(var i = 0, s; s = arguments[i]; i++){
10404             this.remove(this.lookup(s));
10405         }
10406     },
10407
10408     
10409     lookup : function(id){
10410         return typeof id == "object" ? id : this.get(id);
10411     },
10412
10413     
10414     getKey : function(o){
10415          return o.storeId || o.id; 
10416     }
10417 });
10418
10419 Ext.data.Store = function(config){
10420     this.data = new Ext.util.MixedCollection(false);
10421     this.data.getKey = function(o){
10422         return o.id;
10423     };
10424     
10425     this.baseParams = {};
10426     
10427     this.paramNames = {
10428         "start" : "start",
10429         "limit" : "limit",
10430         "sort" : "sort",
10431         "dir" : "dir"
10432     };
10433
10434     if(config && config.data){
10435         this.inlineData = config.data;
10436         delete config.data;
10437     }
10438
10439     Ext.apply(this, config);
10440
10441     if(this.url && !this.proxy){
10442         this.proxy = new Ext.data.HttpProxy({url: this.url});
10443     }
10444
10445     if(this.reader){ 
10446         if(!this.recordType){
10447             this.recordType = this.reader.recordType;
10448         }
10449         if(this.reader.onMetaChange){
10450             this.reader.onMetaChange = this.onMetaChange.createDelegate(this);
10451         }
10452     }
10453
10454     if(this.recordType){
10455         this.fields = this.recordType.prototype.fields;
10456     }
10457     this.modified = [];
10458
10459     this.addEvents(
10460         
10461         'datachanged',
10462         
10463         'metachange',
10464         
10465         'add',
10466         
10467         'remove',
10468         
10469         'update',
10470         
10471         'clear',
10472         
10473         'beforeload',
10474         
10475         'load',
10476         
10477         'loadexception'
10478     );
10479
10480     if(this.proxy){
10481         this.relayEvents(this.proxy,  ["loadexception"]);
10482     }
10483     
10484     this.sortToggle = {};
10485         if(this.sortInfo){
10486                 this.setDefaultSort(this.sortInfo.field, this.sortInfo.direction);
10487         }
10488         
10489     Ext.data.Store.superclass.constructor.call(this);
10490
10491     if(this.storeId || this.id){
10492         Ext.StoreMgr.register(this);
10493     }
10494     if(this.inlineData){
10495         this.loadData(this.inlineData);
10496         delete this.inlineData;
10497     }else if(this.autoLoad){
10498         this.load.defer(10, this, [
10499             typeof this.autoLoad == 'object' ?
10500                 this.autoLoad : undefined]);
10501     }
10502 };
10503 Ext.extend(Ext.data.Store, Ext.util.Observable, {
10504     
10505     
10506     
10507     
10508     
10509     
10510     
10511     
10512     
10513     remoteSort : false,
10514
10515     
10516     pruneModifiedRecords : false,
10517
10518     
10519    lastOptions : null,
10520
10521     destroy : function(){
10522         if(this.id){
10523             Ext.StoreMgr.unregister(this);
10524         }
10525         this.data = null;
10526         this.purgeListeners();
10527     },
10528
10529     
10530     add : function(records){
10531         records = [].concat(records);
10532         if(records.length < 1){
10533             return;
10534         }
10535         for(var i = 0, len = records.length; i < len; i++){
10536             records[i].join(this);
10537         }
10538         var index = this.data.length;
10539         this.data.addAll(records);
10540         if(this.snapshot){
10541             this.snapshot.addAll(records);
10542         }
10543         this.fireEvent("add", this, records, index);
10544     },
10545
10546     
10547     addSorted : function(record){
10548         var index = this.findInsertIndex(record);
10549         this.insert(index, record);
10550     },
10551
10552     
10553     remove : function(record){
10554         var index = this.data.indexOf(record);
10555         this.data.removeAt(index);
10556         if(this.pruneModifiedRecords){
10557             this.modified.remove(record);
10558         }
10559         if(this.snapshot){
10560             this.snapshot.remove(record);
10561         }
10562         this.fireEvent("remove", this, record, index);
10563     },
10564
10565     
10566     removeAll : function(){
10567         this.data.clear();
10568         if(this.snapshot){
10569             this.snapshot.clear();
10570         }
10571         if(this.pruneModifiedRecords){
10572             this.modified = [];
10573         }
10574         this.fireEvent("clear", this);
10575     },
10576
10577     
10578     insert : function(index, records){
10579         records = [].concat(records);
10580         for(var i = 0, len = records.length; i < len; i++){
10581             this.data.insert(index, records[i]);
10582             records[i].join(this);
10583         }
10584         this.fireEvent("add", this, records, index);
10585     },
10586
10587     
10588     indexOf : function(record){
10589         return this.data.indexOf(record);
10590     },
10591
10592     
10593     indexOfId : function(id){
10594         return this.data.indexOfKey(id);
10595     },
10596
10597     
10598     getById : function(id){
10599         return this.data.key(id);
10600     },
10601
10602     
10603     getAt : function(index){
10604         return this.data.itemAt(index);
10605     },
10606
10607     
10608     getRange : function(start, end){
10609         return this.data.getRange(start, end);
10610     },
10611
10612     
10613     storeOptions : function(o){
10614         o = Ext.apply({}, o);
10615         delete o.callback;
10616         delete o.scope;
10617         this.lastOptions = o;
10618     },
10619
10620     
10621     load : function(options){
10622         options = options || {};
10623         if(this.fireEvent("beforeload", this, options) !== false){
10624             this.storeOptions(options);
10625             var p = Ext.apply(options.params || {}, this.baseParams);
10626             if(this.sortInfo && this.remoteSort){
10627                 var pn = this.paramNames;
10628                 p[pn["sort"]] = this.sortInfo.field;
10629                 p[pn["dir"]] = this.sortInfo.direction;
10630             }
10631             this.proxy.load(p, this.reader, this.loadRecords, this, options);
10632             return true;
10633         } else {
10634           return false;
10635         }
10636     },
10637
10638     
10639     reload : function(options){
10640         this.load(Ext.applyIf(options||{}, this.lastOptions));
10641     },
10642
10643     
10644     
10645     loadRecords : function(o, options, success){
10646         if(!o || success === false){
10647             if(success !== false){
10648                 this.fireEvent("load", this, [], options);
10649             }
10650             if(options.callback){
10651                 options.callback.call(options.scope || this, [], options, false);
10652             }
10653             return;
10654         }
10655         var r = o.records, t = o.totalRecords || r.length;
10656         if(!options || options.add !== true){
10657             if(this.pruneModifiedRecords){
10658                 this.modified = [];
10659             }
10660             for(var i = 0, len = r.length; i < len; i++){
10661                 r[i].join(this);
10662             }
10663             if(this.snapshot){
10664                 this.data = this.snapshot;
10665                 delete this.snapshot;
10666             }
10667             this.data.clear();
10668             this.data.addAll(r);
10669             this.totalLength = t;
10670             this.applySort();
10671             this.fireEvent("datachanged", this);
10672         }else{
10673             this.totalLength = Math.max(t, this.data.length+r.length);
10674             this.add(r);
10675         }
10676         this.fireEvent("load", this, r, options);
10677         if(options.callback){
10678             options.callback.call(options.scope || this, r, options, true);
10679         }
10680     },
10681
10682     
10683     loadData : function(o, append){
10684         var r = this.reader.readRecords(o);
10685         this.loadRecords(r, {add: append}, true);
10686     },
10687
10688     
10689     getCount : function(){
10690         return this.data.length || 0;
10691     },
10692
10693     
10694     getTotalCount : function(){
10695         return this.totalLength || 0;
10696     },
10697
10698     
10699     getSortState : function(){
10700         return this.sortInfo;
10701     },
10702
10703     
10704     applySort : function(){
10705         if(this.sortInfo && !this.remoteSort){
10706             var s = this.sortInfo, f = s.field;
10707             this.sortData(f, s.direction);
10708         }
10709     },
10710
10711     
10712     sortData : function(f, direction){
10713         direction = direction || 'ASC';
10714         var st = this.fields.get(f).sortType;
10715         var fn = function(r1, r2){
10716             var v1 = st(r1.data[f]), v2 = st(r2.data[f]);
10717             return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
10718         };
10719         this.data.sort(direction, fn);
10720         if(this.snapshot && this.snapshot != this.data){
10721             this.snapshot.sort(direction, fn);
10722         }
10723     },
10724
10725     
10726     setDefaultSort : function(field, dir){
10727         dir = dir ? dir.toUpperCase() : "ASC";
10728         this.sortInfo = {field: field, direction: dir};
10729         this.sortToggle[field] = dir;
10730     },
10731
10732     
10733     sort : function(fieldName, dir){
10734         var f = this.fields.get(fieldName);
10735         if(!f){
10736             return false;
10737         }
10738         if(!dir){
10739             if(this.sortInfo && this.sortInfo.field == f.name){ 
10740                 dir = (this.sortToggle[f.name] || "ASC").toggle("ASC", "DESC");
10741             }else{
10742                 dir = f.sortDir;
10743             }
10744         }
10745         var st = (this.sortToggle) ? this.sortToggle[f.name] : null;
10746         var si = (this.sortInfo) ? this.sortInfo : null;
10747         
10748         this.sortToggle[f.name] = dir;
10749         this.sortInfo = {field: f.name, direction: dir};
10750         if(!this.remoteSort){
10751             this.applySort();
10752             this.fireEvent("datachanged", this);
10753         }else{
10754             if (!this.load(this.lastOptions)) {
10755                 if (st) {
10756                     this.sortToggle[f.name] = st;
10757                 }
10758                 if (si) {
10759                     this.sortInfo = si;
10760                 }
10761             }
10762         }
10763     },
10764
10765     
10766     each : function(fn, scope){
10767         this.data.each(fn, scope);
10768     },
10769
10770     
10771     getModifiedRecords : function(){
10772         return this.modified;
10773     },
10774
10775     
10776     createFilterFn : function(property, value, anyMatch, caseSensitive){
10777         if(Ext.isEmpty(value, false)){
10778             return false;
10779         }
10780         value = this.data.createValueMatcher(value, anyMatch, caseSensitive);
10781         return function(r){
10782             return value.test(r.data[property]);
10783         };
10784     },
10785
10786     
10787     sum : function(property, start, end){
10788         var rs = this.data.items, v = 0;
10789         start = start || 0;
10790         end = (end || end === 0) ? end : rs.length-1;
10791
10792         for(var i = start; i <= end; i++){
10793             v += (rs[i].data[property] || 0);
10794         }
10795         return v;
10796     },
10797
10798     
10799     filter : function(property, value, anyMatch, caseSensitive){
10800         var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
10801         return fn ? this.filterBy(fn) : this.clearFilter();
10802     },
10803
10804     
10805     filterBy : function(fn, scope){
10806         this.snapshot = this.snapshot || this.data;
10807         this.data = this.queryBy(fn, scope||this);
10808         this.fireEvent("datachanged", this);
10809     },
10810
10811     
10812     query : function(property, value, anyMatch, caseSensitive){
10813         var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
10814         return fn ? this.queryBy(fn) : this.data.clone();
10815     },
10816
10817     
10818     queryBy : function(fn, scope){
10819         var data = this.snapshot || this.data;
10820         return data.filterBy(fn, scope||this);
10821     },
10822
10823     
10824     find : function(property, value, start, anyMatch, caseSensitive){
10825         var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
10826         return fn ? this.data.findIndexBy(fn, null, start) : -1;
10827     },
10828
10829     
10830     findBy : function(fn, scope, start){
10831         return this.data.findIndexBy(fn, scope, start);
10832     },
10833
10834     
10835     collect : function(dataIndex, allowNull, bypassFilter){
10836         var d = (bypassFilter === true && this.snapshot) ?
10837                 this.snapshot.items : this.data.items;
10838         var v, sv, r = [], l = {};
10839         for(var i = 0, len = d.length; i < len; i++){
10840             v = d[i].data[dataIndex];
10841             sv = String(v);
10842             if((allowNull || !Ext.isEmpty(v)) && !l[sv]){
10843                 l[sv] = true;
10844                 r[r.length] = v;
10845             }
10846         }
10847         return r;
10848     },
10849
10850     
10851     clearFilter : function(suppressEvent){
10852         if(this.isFiltered()){
10853             this.data = this.snapshot;
10854             delete this.snapshot;
10855             if(suppressEvent !== true){
10856                 this.fireEvent("datachanged", this);
10857             }
10858         }
10859     },
10860
10861     
10862     isFiltered : function(){
10863         return this.snapshot && this.snapshot != this.data;
10864     },
10865
10866     
10867     afterEdit : function(record){
10868         if(this.modified.indexOf(record) == -1){
10869             this.modified.push(record);
10870         }
10871         this.fireEvent("update", this, record, Ext.data.Record.EDIT);
10872     },
10873
10874     
10875     afterReject : function(record){
10876         this.modified.remove(record);
10877         this.fireEvent("update", this, record, Ext.data.Record.REJECT);
10878     },
10879
10880     
10881     afterCommit : function(record){
10882         this.modified.remove(record);
10883         this.fireEvent("update", this, record, Ext.data.Record.COMMIT);
10884     },
10885
10886     
10887     commitChanges : function(){
10888         var m = this.modified.slice(0);
10889         this.modified = [];
10890         for(var i = 0, len = m.length; i < len; i++){
10891             m[i].commit();
10892         }
10893     },
10894
10895     
10896     rejectChanges : function(){
10897         var m = this.modified.slice(0);
10898         this.modified = [];
10899         for(var i = 0, len = m.length; i < len; i++){
10900             m[i].reject();
10901         }
10902     },
10903
10904     
10905     onMetaChange : function(meta, rtype, o){
10906         this.recordType = rtype;
10907         this.fields = rtype.prototype.fields;
10908         delete this.snapshot;
10909         this.sortInfo = meta.sortInfo;
10910         this.modified = [];
10911         this.fireEvent('metachange', this, this.reader.meta);
10912     },
10913
10914     
10915     findInsertIndex : function(record){
10916         this.suspendEvents();
10917         var data = this.data.clone();
10918         this.data.add(record);
10919         this.applySort();
10920         var index = this.data.indexOf(record);
10921         this.data = data;
10922         this.resumeEvents();
10923         return index;
10924     }
10925 });
10926
10927 Ext.data.SimpleStore = function(config){
10928     Ext.data.SimpleStore.superclass.constructor.call(this, Ext.apply(config, {
10929         reader: new Ext.data.ArrayReader({
10930                 id: config.id
10931             },
10932             Ext.data.Record.create(config.fields)
10933         )
10934     }));
10935 };
10936 Ext.extend(Ext.data.SimpleStore, Ext.data.Store, {
10937     loadData : function(data, append){
10938         if(this.expandData === true){
10939             var r = [];
10940             for(var i = 0, len = data.length; i < len; i++){
10941                 r[r.length] = [data[i]];
10942             }
10943             data = r;
10944         }
10945         Ext.data.SimpleStore.superclass.loadData.call(this, data, append);
10946     }
10947 });
10948
10949 Ext.data.JsonStore = function(c){
10950     Ext.data.JsonStore.superclass.constructor.call(this, Ext.apply(c, {
10951         proxy: !c.data ? new Ext.data.HttpProxy({url: c.url}) : undefined,
10952         reader: new Ext.data.JsonReader(c, c.fields)
10953     }));
10954 };
10955 Ext.extend(Ext.data.JsonStore, Ext.data.Store);
10956
10957
10958
10959 Ext.data.Field = function(config){
10960     if(typeof config == "string"){
10961         config = {name: config};
10962     }
10963     Ext.apply(this, config);
10964     
10965     if(!this.type){
10966         this.type = "auto";
10967     }
10968     
10969     var st = Ext.data.SortTypes;
10970     
10971     if(typeof this.sortType == "string"){
10972         this.sortType = st[this.sortType];
10973     }
10974     
10975     
10976     if(!this.sortType){
10977         switch(this.type){
10978             case "string":
10979                 this.sortType = st.asUCString;
10980                 break;
10981             case "date":
10982                 this.sortType = st.asDate;
10983                 break;
10984             default:
10985                 this.sortType = st.none;
10986         }
10987     }
10988
10989     
10990     var stripRe = /[\$,%]/g;
10991
10992     
10993     
10994     if(!this.convert){
10995         var cv, dateFormat = this.dateFormat;
10996         switch(this.type){
10997             case "":
10998             case "auto":
10999             case undefined:
11000                 cv = function(v){ return v; };
11001                 break;
11002             case "string":
11003                 cv = function(v){ return (v === undefined || v === null) ? '' : String(v); };
11004                 break;
11005             case "int":
11006                 cv = function(v){
11007                     return v !== undefined && v !== null && v !== '' ?
11008                            parseInt(String(v).replace(stripRe, ""), 10) : '';
11009                     };
11010                 break;
11011             case "float":
11012                 cv = function(v){
11013                     return v !== undefined && v !== null && v !== '' ?
11014                            parseFloat(String(v).replace(stripRe, ""), 10) : ''; 
11015                     };
11016                 break;
11017             case "bool":
11018             case "boolean":
11019                 cv = function(v){ return v === true || v === "true" || v == 1; };
11020                 break;
11021             case "date":
11022                 cv = function(v){
11023                     if(!v){
11024                         return '';
11025                     }
11026                     if(Ext.isDate(v)){
11027                         return v;
11028                     }
11029                     if(dateFormat){
11030                         if(dateFormat == "timestamp"){
11031                             return new Date(v*1000);
11032                         }
11033                         if(dateFormat == "time"){
11034                             return new Date(parseInt(v, 10));
11035                         }
11036                         return Date.parseDate(v, dateFormat);
11037                     }
11038                     var parsed = Date.parse(v);
11039                     return parsed ? new Date(parsed) : null;
11040                 };
11041              break;
11042             
11043         }
11044         this.convert = cv;
11045     }
11046 };
11047
11048 Ext.data.Field.prototype = {
11049     dateFormat: null,
11050     defaultValue: "",
11051     mapping: null,
11052     sortType : null,
11053     sortDir : "ASC"
11054 };
11055
11056 Ext.data.DataReader = function(meta, recordType){
11057     
11058     this.meta = meta;
11059     this.recordType = Ext.isArray(recordType) ? 
11060         Ext.data.Record.create(recordType) : recordType;
11061 };
11062
11063 Ext.data.DataReader.prototype = {
11064     
11065 };
11066
11067 Ext.data.DataProxy = function(){
11068     this.addEvents(
11069         
11070         'beforeload',
11071         
11072         'load',
11073         
11074         'loadexception'
11075     );
11076     Ext.data.DataProxy.superclass.constructor.call(this);
11077 };
11078
11079 Ext.extend(Ext.data.DataProxy, Ext.util.Observable);
11080
11081 Ext.data.MemoryProxy = function(data){
11082     Ext.data.MemoryProxy.superclass.constructor.call(this);
11083     this.data = data;
11084 };
11085
11086 Ext.extend(Ext.data.MemoryProxy, Ext.data.DataProxy, {
11087     
11088     load : function(params, reader, callback, scope, arg){
11089         params = params || {};
11090         var result;
11091         try {
11092             result = reader.readRecords(this.data);
11093         }catch(e){
11094             this.fireEvent("loadexception", this, arg, null, e);
11095             callback.call(scope, null, arg, false);
11096             return;
11097         }
11098         callback.call(scope, result, arg, true);
11099     },
11100     
11101     
11102     update : function(params, records){
11103         
11104     }
11105 });
11106
11107 Ext.data.HttpProxy = function(conn){
11108     Ext.data.HttpProxy.superclass.constructor.call(this);
11109     
11110     this.conn = conn;
11111     this.useAjax = !conn || !conn.events;
11112 };
11113
11114 Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {
11115     
11116     getConnection : function(){
11117         return this.useAjax ? Ext.Ajax : this.conn;
11118     },
11119
11120     
11121     load : function(params, reader, callback, scope, arg){
11122         if(this.fireEvent("beforeload", this, params) !== false){
11123             var  o = {
11124                 params : params || {},
11125                 request: {
11126                     callback : callback,
11127                     scope : scope,
11128                     arg : arg
11129                 },
11130                 reader: reader,
11131                 callback : this.loadResponse,
11132                 scope: this
11133             };
11134             if(this.useAjax){
11135                 Ext.applyIf(o, this.conn);
11136                 if(this.activeRequest){
11137                     Ext.Ajax.abort(this.activeRequest);
11138                 }
11139                 this.activeRequest = Ext.Ajax.request(o);
11140             }else{
11141                 this.conn.request(o);
11142             }
11143         }else{
11144             callback.call(scope||this, null, arg, false);
11145         }
11146     },
11147
11148     
11149     loadResponse : function(o, success, response){
11150         delete this.activeRequest;
11151         if(!success){
11152             this.fireEvent("loadexception", this, o, response);
11153             o.request.callback.call(o.request.scope, null, o.request.arg, false);
11154             return;
11155         }
11156         var result;
11157         try {
11158             result = o.reader.read(response);
11159         }catch(e){
11160             this.fireEvent("loadexception", this, o, response, e);
11161             o.request.callback.call(o.request.scope, null, o.request.arg, false);
11162             return;
11163         }
11164         this.fireEvent("load", this, o, o.request.arg);
11165         o.request.callback.call(o.request.scope, result, o.request.arg, true);
11166     },
11167     
11168     
11169     update : function(dataSet){
11170         
11171     },
11172     
11173     
11174     updateResponse : function(dataSet){
11175         
11176     }
11177 });
11178
11179 Ext.data.ScriptTagProxy = function(config){
11180     Ext.data.ScriptTagProxy.superclass.constructor.call(this);
11181     Ext.apply(this, config);
11182     this.head = document.getElementsByTagName("head")[0];
11183 };
11184
11185 Ext.data.ScriptTagProxy.TRANS_ID = 1000;
11186
11187 Ext.extend(Ext.data.ScriptTagProxy, Ext.data.DataProxy, {
11188     
11189     
11190     timeout : 30000,
11191     
11192     callbackParam : "callback",
11193     
11194     nocache : true,
11195
11196     
11197     load : function(params, reader, callback, scope, arg){
11198         if(this.fireEvent("beforeload", this, params) !== false){
11199
11200             var p = Ext.urlEncode(Ext.apply(params, this.extraParams));
11201
11202             var url = this.url;
11203             url += (url.indexOf("?") != -1 ? "&" : "?") + p;
11204             if(this.nocache){
11205                 url += "&_dc=" + (new Date().getTime());
11206             }
11207             var transId = ++Ext.data.ScriptTagProxy.TRANS_ID;
11208             var trans = {
11209                 id : transId,
11210                 cb : "stcCallback"+transId,
11211                 scriptId : "stcScript"+transId,
11212                 params : params,
11213                 arg : arg,
11214                 url : url,
11215                 callback : callback,
11216                 scope : scope,
11217                 reader : reader
11218             };
11219             var conn = this;
11220
11221             window[trans.cb] = function(o){
11222                 conn.handleResponse(o, trans);
11223             };
11224
11225             url += String.format("&{0}={1}", this.callbackParam, trans.cb);
11226
11227             if(this.autoAbort !== false){
11228                 this.abort();
11229             }
11230
11231             trans.timeoutId = this.handleFailure.defer(this.timeout, this, [trans]);
11232
11233             var script = document.createElement("script");
11234             script.setAttribute("src", url);
11235             script.setAttribute("type", "text/javascript");
11236             script.setAttribute("id", trans.scriptId);
11237             this.head.appendChild(script);
11238
11239             this.trans = trans;
11240         }else{
11241             callback.call(scope||this, null, arg, false);
11242         }
11243     },
11244
11245     
11246     isLoading : function(){
11247         return this.trans ? true : false;
11248     },
11249
11250     
11251     abort : function(){
11252         if(this.isLoading()){
11253             this.destroyTrans(this.trans);
11254         }
11255     },
11256
11257     
11258     destroyTrans : function(trans, isLoaded){
11259         this.head.removeChild(document.getElementById(trans.scriptId));
11260         clearTimeout(trans.timeoutId);
11261         if(isLoaded){
11262             window[trans.cb] = undefined;
11263             try{
11264                 delete window[trans.cb];
11265             }catch(e){}
11266         }else{
11267             
11268             window[trans.cb] = function(){
11269                 window[trans.cb] = undefined;
11270                 try{
11271                     delete window[trans.cb];
11272                 }catch(e){}
11273             };
11274         }
11275     },
11276
11277     
11278     handleResponse : function(o, trans){
11279         this.trans = false;
11280         this.destroyTrans(trans, true);
11281         var result;
11282         try {
11283             result = trans.reader.readRecords(o);
11284         }catch(e){
11285             this.fireEvent("loadexception", this, o, trans.arg, e);
11286             trans.callback.call(trans.scope||window, null, trans.arg, false);
11287             return;
11288         }
11289         this.fireEvent("load", this, o, trans.arg);
11290         trans.callback.call(trans.scope||window, result, trans.arg, true);
11291     },
11292
11293     
11294     handleFailure : function(trans){
11295         this.trans = false;
11296         this.destroyTrans(trans, false);
11297         this.fireEvent("loadexception", this, null, trans.arg);
11298         trans.callback.call(trans.scope||window, null, trans.arg, false);
11299     }
11300 });
11301
11302 Ext.data.JsonReader = function(meta, recordType){
11303     meta = meta || {};
11304     Ext.data.JsonReader.superclass.constructor.call(this, meta, recordType || meta.fields);
11305 };
11306 Ext.extend(Ext.data.JsonReader, Ext.data.DataReader, {
11307     
11308     
11309     read : function(response){
11310         var json = response.responseText;
11311         var o = eval("("+json+")");
11312         if(!o) {
11313             throw {message: "JsonReader.read: Json object not found"};
11314         }
11315         if(o.metaData){
11316             delete this.ef;
11317             this.meta = o.metaData;
11318             this.recordType = Ext.data.Record.create(o.metaData.fields);
11319             this.onMetaChange(this.meta, this.recordType, o);
11320         }
11321         return this.readRecords(o);
11322     },
11323
11324     
11325     onMetaChange : function(meta, recordType, o){
11326
11327     },
11328
11329     
11330     simpleAccess: function(obj, subsc) {
11331         return obj[subsc];
11332     },
11333
11334         
11335     getJsonAccessor: function(){
11336         var re = /[\[\.]/;
11337         return function(expr) {
11338             try {
11339                 return(re.test(expr))
11340                     ? new Function("obj", "return obj." + expr)
11341                     : function(obj){
11342                         return obj[expr];
11343                     };
11344             } catch(e){}
11345             return Ext.emptyFn;
11346         };
11347     }(),
11348
11349     
11350     readRecords : function(o){
11351         
11352         this.jsonData = o;
11353         var s = this.meta, Record = this.recordType,
11354             f = Record.prototype.fields, fi = f.items, fl = f.length;
11355
11356
11357         if (!this.ef) {
11358             if(s.totalProperty) {
11359                     this.getTotal = this.getJsonAccessor(s.totalProperty);
11360                 }
11361                 if(s.successProperty) {
11362                     this.getSuccess = this.getJsonAccessor(s.successProperty);
11363                 }
11364                 this.getRoot = s.root ? this.getJsonAccessor(s.root) : function(p){return p;};
11365                 if (s.id) {
11366                         var g = this.getJsonAccessor(s.id);
11367                         this.getId = function(rec) {
11368                                 var r = g(rec);
11369                                 return (r === undefined || r === "") ? null : r;
11370                         };
11371                 } else {
11372                         this.getId = function(){return null;};
11373                 }
11374             this.ef = [];
11375             for(var i = 0; i < fl; i++){
11376                 f = fi[i];
11377                 var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;
11378                 this.ef[i] = this.getJsonAccessor(map);
11379             }
11380         }
11381
11382         var root = this.getRoot(o), c = root.length, totalRecords = c, success = true;
11383         if(s.totalProperty){
11384             var v = parseInt(this.getTotal(o), 10);
11385             if(!isNaN(v)){
11386                 totalRecords = v;
11387             }
11388         }
11389         if(s.successProperty){
11390             var v = this.getSuccess(o);
11391             if(v === false || v === 'false'){
11392                 success = false;
11393             }
11394         }
11395         var records = [];
11396             for(var i = 0; i < c; i++){
11397                     var n = root[i];
11398                 var values = {};
11399                 var id = this.getId(n);
11400                 for(var j = 0; j < fl; j++){
11401                     f = fi[j];
11402                 var v = this.ef[j](n);
11403                 values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue, n);
11404                 }
11405                 var record = new Record(values, id);
11406                 record.json = n;
11407                 records[i] = record;
11408             }
11409             return {
11410                 success : success,
11411                 records : records,
11412                 totalRecords : totalRecords
11413             };
11414     }
11415 });
11416
11417 Ext.data.XmlReader = function(meta, recordType){
11418     meta = meta || {};
11419     Ext.data.XmlReader.superclass.constructor.call(this, meta, recordType || meta.fields);
11420 };
11421 Ext.extend(Ext.data.XmlReader, Ext.data.DataReader, {
11422     
11423     read : function(response){
11424         var doc = response.responseXML;
11425         if(!doc) {
11426             throw {message: "XmlReader.read: XML Document not available"};
11427         }
11428         return this.readRecords(doc);
11429     },
11430
11431     
11432     readRecords : function(doc){
11433         
11434         this.xmlData = doc;
11435         var root = doc.documentElement || doc;
11436         var q = Ext.DomQuery;
11437         var recordType = this.recordType, fields = recordType.prototype.fields;
11438         var sid = this.meta.id;
11439         var totalRecords = 0, success = true;
11440         if(this.meta.totalRecords){
11441             totalRecords = q.selectNumber(this.meta.totalRecords, root, 0);
11442         }
11443
11444         if(this.meta.success){
11445             var sv = q.selectValue(this.meta.success, root, true);
11446             success = sv !== false && sv !== 'false';
11447         }
11448         var records = [];
11449         var ns = q.select(this.meta.record, root);
11450         for(var i = 0, len = ns.length; i < len; i++) {
11451                 var n = ns[i];
11452                 var values = {};
11453                 var id = sid ? q.selectValue(sid, n) : undefined;
11454                 for(var j = 0, jlen = fields.length; j < jlen; j++){
11455                     var f = fields.items[j];
11456                 var v = q.selectValue(f.mapping || f.name, n, f.defaultValue);
11457                     v = f.convert(v, n);
11458                     values[f.name] = v;
11459                 }
11460                 var record = new recordType(values, id);
11461                 record.node = n;
11462                 records[records.length] = record;
11463             }
11464
11465             return {
11466                 success : success,
11467                 records : records,
11468                 totalRecords : totalRecords || records.length
11469             };
11470     }
11471 });
11472
11473 Ext.data.ArrayReader = Ext.extend(Ext.data.JsonReader, {
11474     
11475     readRecords : function(o){
11476         var sid = this.meta ? this.meta.id : null;
11477         var recordType = this.recordType, fields = recordType.prototype.fields;
11478         var records = [];
11479         var root = o;
11480             for(var i = 0; i < root.length; i++){
11481                     var n = root[i];
11482                 var values = {};
11483                 var id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null);
11484                 for(var j = 0, jlen = fields.length; j < jlen; j++){
11485                 var f = fields.items[j];
11486                 var k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j;
11487                 var v = n[k] !== undefined ? n[k] : f.defaultValue;
11488                 v = f.convert(v, n);
11489                 values[f.name] = v;
11490             }
11491                 var record = new recordType(values, id);
11492                 record.json = n;
11493                 records[records.length] = record;
11494             }
11495             return {
11496                 records : records,
11497                 totalRecords : records.length
11498             };
11499     }
11500 });
11501
11502 Ext.data.Tree = function(root){
11503    this.nodeHash = {};
11504    
11505    this.root = null;
11506    if(root){
11507        this.setRootNode(root);
11508    }
11509    this.addEvents(
11510        
11511        "append",
11512        
11513        "remove",
11514        
11515        "move",
11516        
11517        "insert",
11518        
11519        "beforeappend",
11520        
11521        "beforeremove",
11522        
11523        "beforemove",
11524        
11525        "beforeinsert"
11526    );
11527
11528     Ext.data.Tree.superclass.constructor.call(this);
11529 };
11530
11531 Ext.extend(Ext.data.Tree, Ext.util.Observable, {
11532     
11533     pathSeparator: "/",
11534
11535     
11536     proxyNodeEvent : function(){
11537         return this.fireEvent.apply(this, arguments);
11538     },
11539
11540     
11541     getRootNode : function(){
11542         return this.root;
11543     },
11544
11545     
11546     setRootNode : function(node){
11547         this.root = node;
11548         node.ownerTree = this;
11549         node.isRoot = true;
11550         this.registerNode(node);
11551         return node;
11552     },
11553
11554     
11555     getNodeById : function(id){
11556         return this.nodeHash[id];
11557     },
11558
11559     
11560     registerNode : function(node){
11561         this.nodeHash[node.id] = node;
11562     },
11563
11564     
11565     unregisterNode : function(node){
11566         delete this.nodeHash[node.id];
11567     },
11568
11569     toString : function(){
11570         return "[Tree"+(this.id?" "+this.id:"")+"]";
11571     }
11572 });
11573
11574
11575 Ext.data.Node = function(attributes){
11576     
11577     this.attributes = attributes || {};
11578     this.leaf = this.attributes.leaf;
11579     
11580     this.id = this.attributes.id;
11581     if(!this.id){
11582         this.id = Ext.id(null, "ynode-");
11583         this.attributes.id = this.id;
11584     }
11585     
11586     this.childNodes = [];
11587     if(!this.childNodes.indexOf){ 
11588         this.childNodes.indexOf = function(o){
11589             for(var i = 0, len = this.length; i < len; i++){
11590                 if(this[i] == o) return i;
11591             }
11592             return -1;
11593         };
11594     }
11595     
11596     this.parentNode = null;
11597     
11598     this.firstChild = null;
11599     
11600     this.lastChild = null;
11601     
11602     this.previousSibling = null;
11603     
11604     this.nextSibling = null;
11605
11606     this.addEvents({
11607        
11608        "append" : true,
11609        
11610        "remove" : true,
11611        
11612        "move" : true,
11613        
11614        "insert" : true,
11615        
11616        "beforeappend" : true,
11617        
11618        "beforeremove" : true,
11619        
11620        "beforemove" : true,
11621        
11622        "beforeinsert" : true
11623    });
11624     this.listeners = this.attributes.listeners;
11625     Ext.data.Node.superclass.constructor.call(this);
11626 };
11627
11628 Ext.extend(Ext.data.Node, Ext.util.Observable, {
11629     
11630     fireEvent : function(evtName){
11631         
11632         if(Ext.data.Node.superclass.fireEvent.apply(this, arguments) === false){
11633             return false;
11634         }
11635         
11636         var ot = this.getOwnerTree();
11637         if(ot){
11638             if(ot.proxyNodeEvent.apply(ot, arguments) === false){
11639                 return false;
11640             }
11641         }
11642         return true;
11643     },
11644
11645     
11646     isLeaf : function(){
11647         return this.leaf === true;
11648     },
11649
11650     
11651     setFirstChild : function(node){
11652         this.firstChild = node;
11653     },
11654
11655     
11656     setLastChild : function(node){
11657         this.lastChild = node;
11658     },
11659
11660
11661     
11662     isLast : function(){
11663        return (!this.parentNode ? true : this.parentNode.lastChild == this);
11664     },
11665
11666     
11667     isFirst : function(){
11668        return (!this.parentNode ? true : this.parentNode.firstChild == this);
11669     },
11670
11671     hasChildNodes : function(){
11672         return !this.isLeaf() && this.childNodes.length > 0;
11673     },
11674
11675     
11676     appendChild : function(node){
11677         var multi = false;
11678         if(Ext.isArray(node)){
11679             multi = node;
11680         }else if(arguments.length > 1){
11681             multi = arguments;
11682         }
11683         
11684         if(multi){
11685             for(var i = 0, len = multi.length; i < len; i++) {
11686                 this.appendChild(multi[i]);
11687             }
11688         }else{
11689             if(this.fireEvent("beforeappend", this.ownerTree, this, node) === false){
11690                 return false;
11691             }
11692             var index = this.childNodes.length;
11693             var oldParent = node.parentNode;
11694             
11695             if(oldParent){
11696                 if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index) === false){
11697                     return false;
11698                 }
11699                 oldParent.removeChild(node);
11700             }
11701             index = this.childNodes.length;
11702             if(index == 0){
11703                 this.setFirstChild(node);
11704             }
11705             this.childNodes.push(node);
11706             node.parentNode = this;
11707             var ps = this.childNodes[index-1];
11708             if(ps){
11709                 node.previousSibling = ps;
11710                 ps.nextSibling = node;
11711             }else{
11712                 node.previousSibling = null;
11713             }
11714             node.nextSibling = null;
11715             this.setLastChild(node);
11716             node.setOwnerTree(this.getOwnerTree());
11717             this.fireEvent("append", this.ownerTree, this, node, index);
11718             if(oldParent){
11719                 node.fireEvent("move", this.ownerTree, node, oldParent, this, index);
11720             }
11721             return node;
11722         }
11723     },
11724
11725     
11726     removeChild : function(node){
11727         var index = this.childNodes.indexOf(node);
11728         if(index == -1){
11729             return false;
11730         }
11731         if(this.fireEvent("beforeremove", this.ownerTree, this, node) === false){
11732             return false;
11733         }
11734
11735         
11736         this.childNodes.splice(index, 1);
11737
11738         
11739         if(node.previousSibling){
11740             node.previousSibling.nextSibling = node.nextSibling;
11741         }
11742         if(node.nextSibling){
11743             node.nextSibling.previousSibling = node.previousSibling;
11744         }
11745
11746         
11747         if(this.firstChild == node){
11748             this.setFirstChild(node.nextSibling);
11749         }
11750         if(this.lastChild == node){
11751             this.setLastChild(node.previousSibling);
11752         }
11753
11754         node.setOwnerTree(null);
11755         
11756         node.parentNode = null;
11757         node.previousSibling = null;
11758         node.nextSibling = null;
11759         this.fireEvent("remove", this.ownerTree, this, node);
11760         return node;
11761     },
11762
11763     
11764     insertBefore : function(node, refNode){
11765         if(!refNode){ 
11766             return this.appendChild(node);
11767         }
11768         
11769         if(node == refNode){
11770             return false;
11771         }
11772
11773         if(this.fireEvent("beforeinsert", this.ownerTree, this, node, refNode) === false){
11774             return false;
11775         }
11776         var index = this.childNodes.indexOf(refNode);
11777         var oldParent = node.parentNode;
11778         var refIndex = index;
11779
11780         
11781         if(oldParent == this && this.childNodes.indexOf(node) < index){
11782             refIndex--;
11783         }
11784
11785         
11786         if(oldParent){
11787             if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index, refNode) === false){
11788                 return false;
11789             }
11790             oldParent.removeChild(node);
11791         }
11792         if(refIndex == 0){
11793             this.setFirstChild(node);
11794         }
11795         this.childNodes.splice(refIndex, 0, node);
11796         node.parentNode = this;
11797         var ps = this.childNodes[refIndex-1];
11798         if(ps){
11799             node.previousSibling = ps;
11800             ps.nextSibling = node;
11801         }else{
11802             node.previousSibling = null;
11803         }
11804         node.nextSibling = refNode;
11805         refNode.previousSibling = node;
11806         node.setOwnerTree(this.getOwnerTree());
11807         this.fireEvent("insert", this.ownerTree, this, node, refNode);
11808         if(oldParent){
11809             node.fireEvent("move", this.ownerTree, node, oldParent, this, refIndex, refNode);
11810         }
11811         return node;
11812     },
11813
11814     
11815     remove : function(){
11816         this.parentNode.removeChild(this);
11817         return this;
11818     },
11819
11820     
11821     item : function(index){
11822         return this.childNodes[index];
11823     },
11824
11825     
11826     replaceChild : function(newChild, oldChild){
11827         this.insertBefore(newChild, oldChild);
11828         this.removeChild(oldChild);
11829         return oldChild;
11830     },
11831
11832     
11833     indexOf : function(child){
11834         return this.childNodes.indexOf(child);
11835     },
11836
11837     
11838     getOwnerTree : function(){
11839         
11840         if(!this.ownerTree){
11841             var p = this;
11842             while(p){
11843                 if(p.ownerTree){
11844                     this.ownerTree = p.ownerTree;
11845                     break;
11846                 }
11847                 p = p.parentNode;
11848             }
11849         }
11850         return this.ownerTree;
11851     },
11852
11853     
11854     getDepth : function(){
11855         var depth = 0;
11856         var p = this;
11857         while(p.parentNode){
11858             ++depth;
11859             p = p.parentNode;
11860         }
11861         return depth;
11862     },
11863
11864     
11865     setOwnerTree : function(tree){
11866         
11867         if(tree != this.ownerTree){
11868             if(this.ownerTree){
11869                 this.ownerTree.unregisterNode(this);
11870             }
11871             this.ownerTree = tree;
11872             var cs = this.childNodes;
11873             for(var i = 0, len = cs.length; i < len; i++) {
11874                 cs[i].setOwnerTree(tree);
11875             }
11876             if(tree){
11877                 tree.registerNode(this);
11878             }
11879         }
11880     },
11881
11882     
11883     getPath : function(attr){
11884         attr = attr || "id";
11885         var p = this.parentNode;
11886         var b = [this.attributes[attr]];
11887         while(p){
11888             b.unshift(p.attributes[attr]);
11889             p = p.parentNode;
11890         }
11891         var sep = this.getOwnerTree().pathSeparator;
11892         return sep + b.join(sep);
11893     },
11894
11895     
11896     bubble : function(fn, scope, args){
11897         var p = this;
11898         while(p){
11899             if(fn.apply(scope || p, args || [p]) === false){
11900                 break;
11901             }
11902             p = p.parentNode;
11903         }
11904     },
11905
11906     
11907     cascade : function(fn, scope, args){
11908         if(fn.apply(scope || this, args || [this]) !== false){
11909             var cs = this.childNodes;
11910             for(var i = 0, len = cs.length; i < len; i++) {
11911                 cs[i].cascade(fn, scope, args);
11912             }
11913         }
11914     },
11915
11916     
11917     eachChild : function(fn, scope, args){
11918         var cs = this.childNodes;
11919         for(var i = 0, len = cs.length; i < len; i++) {
11920                 if(fn.apply(scope || this, args || [cs[i]]) === false){
11921                     break;
11922                 }
11923         }
11924     },
11925
11926     
11927     findChild : function(attribute, value){
11928         var cs = this.childNodes;
11929         for(var i = 0, len = cs.length; i < len; i++) {
11930                 if(cs[i].attributes[attribute] == value){
11931                     return cs[i];
11932                 }
11933         }
11934         return null;
11935     },
11936
11937     
11938     findChildBy : function(fn, scope){
11939         var cs = this.childNodes;
11940         for(var i = 0, len = cs.length; i < len; i++) {
11941                 if(fn.call(scope||cs[i], cs[i]) === true){
11942                     return cs[i];
11943                 }
11944         }
11945         return null;
11946     },
11947
11948     
11949     sort : function(fn, scope){
11950         var cs = this.childNodes;
11951         var len = cs.length;
11952         if(len > 0){
11953             var sortFn = scope ? function(){fn.apply(scope, arguments);} : fn;
11954             cs.sort(sortFn);
11955             for(var i = 0; i < len; i++){
11956                 var n = cs[i];
11957                 n.previousSibling = cs[i-1];
11958                 n.nextSibling = cs[i+1];
11959                 if(i == 0){
11960                     this.setFirstChild(n);
11961                 }
11962                 if(i == len-1){
11963                     this.setLastChild(n);
11964                 }
11965             }
11966         }
11967     },
11968
11969     
11970     contains : function(node){
11971         return node.isAncestor(this);
11972     },
11973
11974     
11975     isAncestor : function(node){
11976         var p = this.parentNode;
11977         while(p){
11978             if(p == node){
11979                 return true;
11980             }
11981             p = p.parentNode;
11982         }
11983         return false;
11984     },
11985
11986     toString : function(){
11987         return "[Node"+(this.id?" "+this.id:"")+"]";
11988     }
11989 });
11990
11991 Ext.data.GroupingStore = Ext.extend(Ext.data.Store, {
11992     
11993     
11994     remoteGroup : false,
11995     
11996     groupOnSort:false,
11997
11998     
11999     clearGrouping : function(){
12000         this.groupField = false;
12001         if(this.remoteGroup){
12002             if(this.baseParams){
12003                 delete this.baseParams.groupBy;
12004             }
12005             this.reload();
12006         }else{
12007             this.applySort();
12008             this.fireEvent('datachanged', this);
12009         }
12010     },
12011
12012     
12013     groupBy : function(field, forceRegroup){
12014         if(this.groupField == field && !forceRegroup){
12015             return; 
12016         }
12017         this.groupField = field;
12018         if(this.remoteGroup){
12019             if(!this.baseParams){
12020                 this.baseParams = {};
12021             }
12022             this.baseParams['groupBy'] = field;
12023         }
12024         if(this.groupOnSort){
12025             this.sort(field);
12026             return;
12027         }
12028         if(this.remoteGroup){
12029             this.reload();
12030         }else{
12031             var si = this.sortInfo || {};
12032             if(si.field != field){
12033                 this.applySort();
12034             }else{
12035                 this.sortData(field);
12036             }
12037             this.fireEvent('datachanged', this);
12038         }
12039     },
12040
12041     
12042     applySort : function(){
12043         Ext.data.GroupingStore.superclass.applySort.call(this);
12044         if(!this.groupOnSort && !this.remoteGroup){
12045             var gs = this.getGroupState();
12046             if(gs && gs != this.sortInfo.field){
12047                 this.sortData(this.groupField);
12048             }
12049         }
12050     },
12051
12052     
12053     applyGrouping : function(alwaysFireChange){
12054         if(this.groupField !== false){
12055             this.groupBy(this.groupField, true);
12056             return true;
12057         }else{
12058             if(alwaysFireChange === true){
12059                 this.fireEvent('datachanged', this);
12060             }
12061             return false;
12062         }
12063     },
12064
12065     
12066     getGroupState : function(){
12067         return this.groupOnSort && this.groupField !== false ?
12068                (this.sortInfo ? this.sortInfo.field : undefined) : this.groupField;
12069     }
12070 });
12071
12072 Ext.ComponentMgr = function(){
12073     var all = new Ext.util.MixedCollection();
12074     var types = {};
12075
12076     return {
12077         
12078         register : function(c){
12079             all.add(c);
12080         },
12081
12082         
12083         unregister : function(c){
12084             all.remove(c);
12085         },
12086
12087         
12088         get : function(id){
12089             return all.get(id);
12090         },
12091
12092         
12093         onAvailable : function(id, fn, scope){
12094             all.on("add", function(index, o){
12095                 if(o.id == id){
12096                     fn.call(scope || o, o);
12097                     all.un("add", fn, scope);
12098                 }
12099             });
12100         },
12101
12102         
12103         all : all,
12104
12105         
12106         registerType : function(xtype, cls){
12107             types[xtype] = cls;
12108             cls.xtype = xtype;
12109         },
12110
12111         
12112         create : function(config, defaultType){
12113             return new types[config.xtype || defaultType](config);
12114         }
12115     };
12116 }();
12117
12118
12119
12120 Ext.reg = Ext.ComponentMgr.registerType;
12121
12122 Ext.Component = function(config){
12123     config = config || {};
12124     if(config.initialConfig){
12125         if(config.isAction){                       this.baseAction = config;
12126         }
12127         config = config.initialConfig;     }else if(config.tagName || config.dom || typeof config == "string"){         config = {applyTo: config, id: config.id || config};
12128     }
12129
12130     
12131     this.initialConfig = config;
12132
12133     Ext.apply(this, config);
12134     this.addEvents(
12135         
12136         'disable',
12137         
12138         'enable',
12139         
12140         'beforeshow',
12141         
12142         'show',
12143         
12144         'beforehide',
12145         
12146         'hide',
12147         
12148         'beforerender',
12149         
12150         'render',
12151         
12152         'beforedestroy',
12153         
12154         'destroy',
12155         
12156         'beforestaterestore',
12157         
12158         'staterestore',
12159         
12160         'beforestatesave',
12161         
12162         'statesave'
12163     );
12164     this.getId();
12165     Ext.ComponentMgr.register(this);
12166     Ext.Component.superclass.constructor.call(this);
12167
12168     if(this.baseAction){
12169         this.baseAction.addComponent(this);
12170     }
12171
12172     this.initComponent();
12173
12174     if(this.plugins){
12175         if(Ext.isArray(this.plugins)){
12176             for(var i = 0, len = this.plugins.length; i < len; i++){
12177                 this.plugins[i].init(this);
12178             }
12179         }else{
12180             this.plugins.init(this);
12181         }
12182     }
12183
12184     if(this.stateful !== false){
12185         this.initState(config);
12186     }
12187
12188     if(this.applyTo){
12189         this.applyToMarkup(this.applyTo);
12190         delete this.applyTo;
12191     }else if(this.renderTo){
12192         this.render(this.renderTo);
12193         delete this.renderTo;
12194     }
12195 };
12196
12197 Ext.Component.AUTO_ID = 1000;
12198
12199 Ext.extend(Ext.Component, Ext.util.Observable, {
12200     
12201     
12202     
12203     
12204     
12205     
12206     
12207     
12208     
12209
12210     
12211     
12212     
12213
12214     
12215     disabledClass : "x-item-disabled",
12216         
12217     allowDomMove : true,
12218         
12219     autoShow : false,
12220     
12221     hideMode: 'display',
12222     
12223     hideParent: false,
12224
12225     
12226     
12227     hidden : false,
12228     
12229     disabled : false,
12230     
12231     rendered : false,
12232
12233         ctype : "Ext.Component",
12234
12235         actionMode : "el",
12236
12237         getActionEl : function(){
12238         return this[this.actionMode];
12239     },
12240
12241     
12242     initComponent : Ext.emptyFn,
12243
12244     
12245     render : function(container, position){
12246         if(!this.rendered && this.fireEvent("beforerender", this) !== false){
12247             if(!container && this.el){
12248                 this.el = Ext.get(this.el);
12249                 container = this.el.dom.parentNode;
12250                 this.allowDomMove = false;
12251             }
12252             this.container = Ext.get(container);
12253             if(this.ctCls){
12254                 this.container.addClass(this.ctCls);
12255             }
12256             this.rendered = true;
12257             if(position !== undefined){
12258                 if(typeof position == 'number'){
12259                     position = this.container.dom.childNodes[position];
12260                 }else{
12261                     position = Ext.getDom(position);
12262                 }
12263             }
12264             this.onRender(this.container, position || null);
12265             if(this.autoShow){
12266                 this.el.removeClass(['x-hidden','x-hide-' + this.hideMode]);
12267             }
12268             if(this.cls){
12269                 this.el.addClass(this.cls);
12270                 delete this.cls;
12271             }
12272             if(this.style){
12273                 this.el.applyStyles(this.style);
12274                 delete this.style;
12275             }
12276             this.fireEvent("render", this);
12277             this.afterRender(this.container);
12278             if(this.hidden){
12279                 this.hide();
12280             }
12281             if(this.disabled){
12282                 this.disable();
12283             }
12284
12285             this.initStateEvents();
12286         }
12287         return this;
12288     },
12289
12290         initState : function(config){
12291         if(Ext.state.Manager){
12292             var state = Ext.state.Manager.get(this.stateId || this.id);
12293             if(state){
12294                 if(this.fireEvent('beforestaterestore', this, state) !== false){
12295                     this.applyState(state);
12296                     this.fireEvent('staterestore', this, state);
12297                 }
12298             }
12299         }
12300     },
12301
12302         initStateEvents : function(){
12303         if(this.stateEvents){
12304             for(var i = 0, e; e = this.stateEvents[i]; i++){
12305                 this.on(e, this.saveState, this, {delay:100});
12306             }
12307         }
12308     },
12309
12310         applyState : function(state, config){
12311         if(state){
12312             Ext.apply(this, state);
12313         }
12314     },
12315
12316         getState : function(){
12317         return null;
12318     },
12319
12320         saveState : function(){
12321         if(Ext.state.Manager){
12322             var state = this.getState();
12323             if(this.fireEvent('beforestatesave', this, state) !== false){
12324                 Ext.state.Manager.set(this.stateId || this.id, state);
12325                 this.fireEvent('statesave', this, state);
12326             }
12327         }
12328     },
12329
12330     
12331     applyToMarkup : function(el){
12332         this.allowDomMove = false;
12333         this.el = Ext.get(el);
12334         this.render(this.el.dom.parentNode);
12335     },
12336
12337     
12338     addClass : function(cls){
12339         if(this.el){
12340             this.el.addClass(cls);
12341         }else{
12342             this.cls = this.cls ? this.cls + ' ' + cls : cls;
12343         }
12344     },
12345
12346     
12347     removeClass : function(cls){
12348         if(this.el){
12349             this.el.removeClass(cls);
12350         }else if(this.cls){
12351             this.cls = this.cls.split(' ').remove(cls).join(' ');
12352         }
12353     },
12354
12355             onRender : function(ct, position){
12356         if(this.autoEl){
12357             if(typeof this.autoEl == 'string'){
12358                 this.el = document.createElement(this.autoEl);
12359             }else{
12360                 var div = document.createElement('div');
12361                 Ext.DomHelper.overwrite(div, this.autoEl);
12362                 this.el = div.firstChild;
12363             }
12364             if (!this.el.id) {
12365                 this.el.id = this.getId();
12366             }
12367         }
12368         if(this.el){
12369             this.el = Ext.get(this.el);
12370             if(this.allowDomMove !== false){
12371                 ct.dom.insertBefore(this.el.dom, position);
12372             }
12373         }
12374     },
12375
12376         getAutoCreate : function(){
12377         var cfg = typeof this.autoCreate == "object" ?
12378                       this.autoCreate : Ext.apply({}, this.defaultAutoCreate);
12379         if(this.id && !cfg.id){
12380             cfg.id = this.id;
12381         }
12382         return cfg;
12383     },
12384
12385         afterRender : Ext.emptyFn,
12386
12387     
12388     destroy : function(){
12389         if(this.fireEvent("beforedestroy", this) !== false){
12390             this.beforeDestroy();
12391             if(this.rendered){
12392                 this.el.removeAllListeners();
12393                 this.el.remove();
12394                 if(this.actionMode == "container"){
12395                     this.container.remove();
12396                 }
12397             }
12398             this.onDestroy();
12399             Ext.ComponentMgr.unregister(this);
12400             this.fireEvent("destroy", this);
12401             this.purgeListeners();
12402         }
12403     },
12404
12405             beforeDestroy : Ext.emptyFn,
12406
12407             onDestroy  : Ext.emptyFn,
12408
12409     
12410     getEl : function(){
12411         return this.el;
12412     },
12413
12414     
12415     getId : function(){
12416         return this.id || (this.id = "ext-comp-" + (++Ext.Component.AUTO_ID));
12417     },
12418
12419     
12420     getItemId : function(){
12421         return this.itemId || this.getId();
12422     },
12423
12424     
12425     focus : function(selectText, delay){
12426         if(delay){
12427             this.focus.defer(typeof delay == 'number' ? delay : 10, this, [selectText, false]);
12428             return;
12429         }
12430         if(this.rendered){
12431             this.el.focus();
12432             if(selectText === true){
12433                 this.el.dom.select();
12434             }
12435         }
12436         return this;
12437     },
12438
12439         blur : function(){
12440         if(this.rendered){
12441             this.el.blur();
12442         }
12443         return this;
12444     },
12445
12446     
12447     disable : function(){
12448         if(this.rendered){
12449             this.onDisable();
12450         }
12451         this.disabled = true;
12452         this.fireEvent("disable", this);
12453         return this;
12454     },
12455
12456             onDisable : function(){
12457         this.getActionEl().addClass(this.disabledClass);
12458         this.el.dom.disabled = true;
12459     },
12460
12461     
12462     enable : function(){
12463         if(this.rendered){
12464             this.onEnable();
12465         }
12466         this.disabled = false;
12467         this.fireEvent("enable", this);
12468         return this;
12469     },
12470
12471             onEnable : function(){
12472         this.getActionEl().removeClass(this.disabledClass);
12473         this.el.dom.disabled = false;
12474     },
12475
12476     
12477     setDisabled : function(disabled){
12478         this[disabled ? "disable" : "enable"]();
12479     },
12480
12481     
12482     show: function(){
12483         if(this.fireEvent("beforeshow", this) !== false){
12484             this.hidden = false;
12485             if(this.autoRender){
12486                 this.render(typeof this.autoRender == 'boolean' ? Ext.getBody() : this.autoRender);
12487             }
12488             if(this.rendered){
12489                 this.onShow();
12490             }
12491             this.fireEvent("show", this);
12492         }
12493         return this;
12494     },
12495
12496         onShow : function(){
12497         if(this.hideParent){
12498             this.container.removeClass('x-hide-' + this.hideMode);
12499         }else{
12500             this.getActionEl().removeClass('x-hide-' + this.hideMode);
12501         }
12502
12503     },
12504
12505     
12506     hide: function(){
12507         if(this.fireEvent("beforehide", this) !== false){
12508             this.hidden = true;
12509             if(this.rendered){
12510                 this.onHide();
12511             }
12512             this.fireEvent("hide", this);
12513         }
12514         return this;
12515     },
12516
12517         onHide : function(){
12518         if(this.hideParent){
12519             this.container.addClass('x-hide-' + this.hideMode);
12520         }else{
12521             this.getActionEl().addClass('x-hide-' + this.hideMode);
12522         }
12523     },
12524
12525     
12526     setVisible: function(visible){
12527         if(visible) {
12528             this.show();
12529         }else{
12530             this.hide();
12531         }
12532         return this;
12533     },
12534
12535     
12536     isVisible : function(){
12537         return this.rendered && this.getActionEl().isVisible();
12538     },
12539
12540     
12541     cloneConfig : function(overrides){
12542         overrides = overrides || {};
12543         var id = overrides.id || Ext.id();
12544         var cfg = Ext.applyIf(overrides, this.initialConfig);
12545         cfg.id = id;         return new this.constructor(cfg);
12546     },
12547
12548     
12549     getXType : function(){
12550         return this.constructor.xtype;
12551     },
12552
12553     
12554     isXType : function(xtype, shallow){
12555         return !shallow ?
12556                ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1 :
12557                 this.constructor.xtype == xtype;
12558     },
12559
12560     
12561     getXTypes : function(){
12562         var tc = this.constructor;
12563         if(!tc.xtypes){
12564             var c = [], sc = this;
12565             while(sc && sc.constructor.xtype){
12566                 c.unshift(sc.constructor.xtype);
12567                 sc = sc.constructor.superclass;
12568             }
12569             tc.xtypeChain = c;
12570             tc.xtypes = c.join('/');
12571         }
12572         return tc.xtypes;
12573     },
12574
12575     
12576     findParentBy: function(fn) {
12577         for (var p = this.ownerCt; (p != null) && !fn(p, this); p = p.ownerCt);
12578         return p || null;
12579     },
12580
12581     
12582     findParentByType: function(xtype) {
12583         return typeof xtype == 'function' ?
12584             this.findParentBy(function(p){
12585                 return p.constructor === xtype;
12586             }) :
12587             this.findParentBy(function(p){
12588                 return p.constructor.xtype === xtype;
12589             });
12590     }
12591 });
12592
12593 Ext.reg('component', Ext.Component);
12594
12595
12596 Ext.Action = function(config){
12597     this.initialConfig = config;
12598     this.items = [];
12599 }
12600
12601 Ext.Action.prototype = {
12602     
12603     
12604     
12605     
12606     
12607     
12608
12609     
12610     isAction : true,
12611
12612     
12613     setText : function(text){
12614         this.initialConfig.text = text;
12615         this.callEach('setText', [text]);
12616     },
12617
12618     
12619     getText : function(){
12620         return this.initialConfig.text;
12621     },
12622
12623     
12624     setIconClass : function(cls){
12625         this.initialConfig.iconCls = cls;
12626         this.callEach('setIconClass', [cls]);
12627     },
12628
12629     
12630     getIconClass : function(){
12631         return this.initialConfig.iconCls;
12632     },
12633
12634     
12635     setDisabled : function(v){
12636         this.initialConfig.disabled = v;
12637         this.callEach('setDisabled', [v]);
12638     },
12639
12640     
12641     enable : function(){
12642         this.setDisabled(false);
12643     },
12644
12645     
12646     disable : function(){
12647         this.setDisabled(true);
12648     },
12649
12650     
12651     isDisabled : function(){
12652         return this.initialConfig.disabled;
12653     },
12654
12655     
12656     setHidden : function(v){
12657         this.initialConfig.hidden = v;
12658         this.callEach('setVisible', [!v]);
12659     },
12660
12661     
12662     show : function(){
12663         this.setHidden(false);
12664     },
12665
12666     
12667     hide : function(){
12668         this.setHidden(true);
12669     },
12670
12671     
12672     isHidden : function(){
12673         return this.initialConfig.hidden;
12674     },
12675
12676     
12677     setHandler : function(fn, scope){
12678         this.initialConfig.handler = fn;
12679         this.initialConfig.scope = scope;
12680         this.callEach('setHandler', [fn, scope]);
12681     },
12682
12683     
12684     each : function(fn, scope){
12685         Ext.each(this.items, fn, scope);
12686     },
12687
12688     
12689     callEach : function(fnName, args){
12690         var cs = this.items;
12691         for(var i = 0, len = cs.length; i < len; i++){
12692             cs[i][fnName].apply(cs[i], args);
12693         }
12694     },
12695
12696     
12697     addComponent : function(comp){
12698         this.items.push(comp);
12699         comp.on('destroy', this.removeComponent, this);
12700     },
12701
12702     
12703     removeComponent : function(comp){
12704         this.items.remove(comp);
12705     },
12706
12707     execute : function(){
12708         this.initialConfig.handler.apply(this.initialConfig.scope || window, arguments);
12709     }
12710 };
12711
12712 (function(){ 
12713 Ext.Layer = function(config, existingEl){
12714     config = config || {};
12715     var dh = Ext.DomHelper;
12716     var cp = config.parentEl, pel = cp ? Ext.getDom(cp) : document.body;
12717     if(existingEl){
12718         this.dom = Ext.getDom(existingEl);
12719     }
12720     if(!this.dom){
12721         var o = config.dh || {tag: "div", cls: "x-layer"};
12722         this.dom = dh.append(pel, o);
12723     }
12724     if(config.cls){
12725         this.addClass(config.cls);
12726     }
12727     this.constrain = config.constrain !== false;
12728     this.visibilityMode = Ext.Element.VISIBILITY;
12729     if(config.id){
12730         this.id = this.dom.id = config.id;
12731     }else{
12732         this.id = Ext.id(this.dom);
12733     }
12734     this.zindex = config.zindex || this.getZIndex();
12735     this.position("absolute", this.zindex);
12736     if(config.shadow){
12737         this.shadowOffset = config.shadowOffset || 4;
12738         this.shadow = new Ext.Shadow({
12739             offset : this.shadowOffset,
12740             mode : config.shadow
12741         });
12742     }else{
12743         this.shadowOffset = 0;
12744     }
12745     this.useShim = config.shim !== false && Ext.useShims;
12746     this.useDisplay = config.useDisplay;
12747     this.hide();
12748 };
12749
12750 var supr = Ext.Element.prototype;
12751
12752
12753 var shims = [];
12754
12755 Ext.extend(Ext.Layer, Ext.Element, {
12756
12757     getZIndex : function(){
12758         return this.zindex || parseInt(this.getStyle("z-index"), 10) || 11000;
12759     },
12760
12761     getShim : function(){
12762         if(!this.useShim){
12763             return null;
12764         }
12765         if(this.shim){
12766             return this.shim;
12767         }
12768         var shim = shims.shift();
12769         if(!shim){
12770             shim = this.createShim();
12771             shim.enableDisplayMode('block');
12772             shim.dom.style.display = 'none';
12773             shim.dom.style.visibility = 'visible';
12774         }
12775         var pn = this.dom.parentNode;
12776         if(shim.dom.parentNode != pn){
12777             pn.insertBefore(shim.dom, this.dom);
12778         }
12779         shim.setStyle('z-index', this.getZIndex()-2);
12780         this.shim = shim;
12781         return shim;
12782     },
12783
12784     hideShim : function(){
12785         if(this.shim){
12786             this.shim.setDisplayed(false);
12787             shims.push(this.shim);
12788             delete this.shim;
12789         }
12790     },
12791
12792     disableShadow : function(){
12793         if(this.shadow){
12794             this.shadowDisabled = true;
12795             this.shadow.hide();
12796             this.lastShadowOffset = this.shadowOffset;
12797             this.shadowOffset = 0;
12798         }
12799     },
12800
12801     enableShadow : function(show){
12802         if(this.shadow){
12803             this.shadowDisabled = false;
12804             this.shadowOffset = this.lastShadowOffset;
12805             delete this.lastShadowOffset;
12806             if(show){
12807                 this.sync(true);
12808             }
12809         }
12810     },
12811
12812     
12813     
12814     
12815     sync : function(doShow){
12816         var sw = this.shadow;
12817         if(!this.updating && this.isVisible() && (sw || this.useShim)){
12818             var sh = this.getShim();
12819
12820             var w = this.getWidth(),
12821                 h = this.getHeight();
12822
12823             var l = this.getLeft(true),
12824                 t = this.getTop(true);
12825
12826             if(sw && !this.shadowDisabled){
12827                 if(doShow && !sw.isVisible()){
12828                     sw.show(this);
12829                 }else{
12830                     sw.realign(l, t, w, h);
12831                 }
12832                 if(sh){
12833                     if(doShow){
12834                        sh.show();
12835                     }
12836                     
12837                     var a = sw.adjusts, s = sh.dom.style;
12838                     s.left = (Math.min(l, l+a.l))+"px";
12839                     s.top = (Math.min(t, t+a.t))+"px";
12840                     s.width = (w+a.w)+"px";
12841                     s.height = (h+a.h)+"px";
12842                 }
12843             }else if(sh){
12844                 if(doShow){
12845                    sh.show();
12846                 }
12847                 sh.setSize(w, h);
12848                 sh.setLeftTop(l, t);
12849             }
12850             
12851         }
12852     },
12853
12854     
12855     destroy : function(){
12856         this.hideShim();
12857         if(this.shadow){
12858             this.shadow.hide();
12859         }
12860         this.removeAllListeners();
12861         Ext.removeNode(this.dom);
12862         Ext.Element.uncache(this.id);
12863     },
12864
12865     remove : function(){
12866         this.destroy();
12867     },
12868
12869     
12870     beginUpdate : function(){
12871         this.updating = true;
12872     },
12873
12874     
12875     endUpdate : function(){
12876         this.updating = false;
12877         this.sync(true);
12878     },
12879
12880     
12881     hideUnders : function(negOffset){
12882         if(this.shadow){
12883             this.shadow.hide();
12884         }
12885         this.hideShim();
12886     },
12887
12888     
12889     constrainXY : function(){
12890         if(this.constrain){
12891             var vw = Ext.lib.Dom.getViewWidth(),
12892                 vh = Ext.lib.Dom.getViewHeight();
12893             var s = Ext.getDoc().getScroll();
12894
12895             var xy = this.getXY();
12896             var x = xy[0], y = xy[1];   
12897             var w = this.dom.offsetWidth+this.shadowOffset, h = this.dom.offsetHeight+this.shadowOffset;
12898             
12899             var moved = false;
12900             
12901             if((x + w) > vw+s.left){
12902                 x = vw - w - this.shadowOffset;
12903                 moved = true;
12904             }
12905             if((y + h) > vh+s.top){
12906                 y = vh - h - this.shadowOffset;
12907                 moved = true;
12908             }
12909             
12910             if(x < s.left){
12911                 x = s.left;
12912                 moved = true;
12913             }
12914             if(y < s.top){
12915                 y = s.top;
12916                 moved = true;
12917             }
12918             if(moved){
12919                 if(this.avoidY){
12920                     var ay = this.avoidY;
12921                     if(y <= ay && (y+h) >= ay){
12922                         y = ay-h-5;   
12923                     }
12924                 }
12925                 xy = [x, y];
12926                 this.storeXY(xy);
12927                 supr.setXY.call(this, xy);
12928                 this.sync();
12929             }
12930         }
12931     },
12932
12933     isVisible : function(){
12934         return this.visible;    
12935     },
12936
12937     
12938     showAction : function(){
12939         this.visible = true; 
12940         if(this.useDisplay === true){
12941             this.setDisplayed("");
12942         }else if(this.lastXY){
12943             supr.setXY.call(this, this.lastXY);
12944         }else if(this.lastLT){
12945             supr.setLeftTop.call(this, this.lastLT[0], this.lastLT[1]);
12946         }
12947     },
12948
12949     
12950     hideAction : function(){
12951         this.visible = false;
12952         if(this.useDisplay === true){
12953             this.setDisplayed(false);
12954         }else{
12955             this.setLeftTop(-10000,-10000);
12956         }
12957     },
12958
12959     
12960     setVisible : function(v, a, d, c, e){
12961         if(v){
12962             this.showAction();
12963         }
12964         if(a && v){
12965             var cb = function(){
12966                 this.sync(true);
12967                 if(c){
12968                     c();
12969                 }
12970             }.createDelegate(this);
12971             supr.setVisible.call(this, true, true, d, cb, e);
12972         }else{
12973             if(!v){
12974                 this.hideUnders(true);
12975             }
12976             var cb = c;
12977             if(a){
12978                 cb = function(){
12979                     this.hideAction();
12980                     if(c){
12981                         c();
12982                     }
12983                 }.createDelegate(this);
12984             }
12985             supr.setVisible.call(this, v, a, d, cb, e);
12986             if(v){
12987                 this.sync(true);
12988             }else if(!a){
12989                 this.hideAction();
12990             }
12991         }
12992     },
12993
12994     storeXY : function(xy){
12995         delete this.lastLT;
12996         this.lastXY = xy;
12997     },
12998
12999     storeLeftTop : function(left, top){
13000         delete this.lastXY;
13001         this.lastLT = [left, top];
13002     },
13003
13004     
13005     beforeFx : function(){
13006         this.beforeAction();
13007         return Ext.Layer.superclass.beforeFx.apply(this, arguments);
13008     },
13009
13010     
13011     afterFx : function(){
13012         Ext.Layer.superclass.afterFx.apply(this, arguments);
13013         this.sync(this.isVisible());
13014     },
13015
13016     
13017     beforeAction : function(){
13018         if(!this.updating && this.shadow){
13019             this.shadow.hide();
13020         }
13021     },
13022
13023     
13024     setLeft : function(left){
13025         this.storeLeftTop(left, this.getTop(true));
13026         supr.setLeft.apply(this, arguments);
13027         this.sync();
13028     },
13029
13030     setTop : function(top){
13031         this.storeLeftTop(this.getLeft(true), top);
13032         supr.setTop.apply(this, arguments);
13033         this.sync();
13034     },
13035
13036     setLeftTop : function(left, top){
13037         this.storeLeftTop(left, top);
13038         supr.setLeftTop.apply(this, arguments);
13039         this.sync();
13040     },
13041
13042     setXY : function(xy, a, d, c, e){
13043         this.fixDisplay();
13044         this.beforeAction();
13045         this.storeXY(xy);
13046         var cb = this.createCB(c);
13047         supr.setXY.call(this, xy, a, d, cb, e);
13048         if(!a){
13049             cb();
13050         }
13051     },
13052
13053     
13054     createCB : function(c){
13055         var el = this;
13056         return function(){
13057             el.constrainXY();
13058             el.sync(true);
13059             if(c){
13060                 c();
13061             }
13062         };
13063     },
13064
13065     
13066     setX : function(x, a, d, c, e){
13067         this.setXY([x, this.getY()], a, d, c, e);
13068     },
13069
13070     
13071     setY : function(y, a, d, c, e){
13072         this.setXY([this.getX(), y], a, d, c, e);
13073     },
13074
13075     
13076     setSize : function(w, h, a, d, c, e){
13077         this.beforeAction();
13078         var cb = this.createCB(c);
13079         supr.setSize.call(this, w, h, a, d, cb, e);
13080         if(!a){
13081             cb();
13082         }
13083     },
13084
13085     
13086     setWidth : function(w, a, d, c, e){
13087         this.beforeAction();
13088         var cb = this.createCB(c);
13089         supr.setWidth.call(this, w, a, d, cb, e);
13090         if(!a){
13091             cb();
13092         }
13093     },
13094
13095     
13096     setHeight : function(h, a, d, c, e){
13097         this.beforeAction();
13098         var cb = this.createCB(c);
13099         supr.setHeight.call(this, h, a, d, cb, e);
13100         if(!a){
13101             cb();
13102         }
13103     },
13104
13105     
13106     setBounds : function(x, y, w, h, a, d, c, e){
13107         this.beforeAction();
13108         var cb = this.createCB(c);
13109         if(!a){
13110             this.storeXY([x, y]);
13111             supr.setXY.call(this, [x, y]);
13112             supr.setSize.call(this, w, h, a, d, cb, e);
13113             cb();
13114         }else{
13115             supr.setBounds.call(this, x, y, w, h, a, d, cb, e);
13116         }
13117         return this;
13118     },
13119     
13120     
13121     setZIndex : function(zindex){
13122         this.zindex = zindex;
13123         this.setStyle("z-index", zindex + 2);
13124         if(this.shadow){
13125             this.shadow.setZIndex(zindex + 1);
13126         }
13127         if(this.shim){
13128             this.shim.setStyle("z-index", zindex);
13129         }
13130     }
13131 });
13132 })();
13133
13134 Ext.Shadow = function(config){
13135     Ext.apply(this, config);
13136     if(typeof this.mode != "string"){
13137         this.mode = this.defaultMode;
13138     }
13139     var o = this.offset, a = {h: 0};
13140     var rad = Math.floor(this.offset/2);
13141     switch(this.mode.toLowerCase()){         case "drop":
13142             a.w = 0;
13143             a.l = a.t = o;
13144             a.t -= 1;
13145             if(Ext.isIE){
13146                 a.l -= this.offset + rad;
13147                 a.t -= this.offset + rad;
13148                 a.w -= rad;
13149                 a.h -= rad;
13150                 a.t += 1;
13151             }
13152         break;
13153         case "sides":
13154             a.w = (o*2);
13155             a.l = -o;
13156             a.t = o-1;
13157             if(Ext.isIE){
13158                 a.l -= (this.offset - rad);
13159                 a.t -= this.offset + rad;
13160                 a.l += 1;
13161                 a.w -= (this.offset - rad)*2;
13162                 a.w -= rad + 1;
13163                 a.h -= 1;
13164             }
13165         break;
13166         case "frame":
13167             a.w = a.h = (o*2);
13168             a.l = a.t = -o;
13169             a.t += 1;
13170             a.h -= 2;
13171             if(Ext.isIE){
13172                 a.l -= (this.offset - rad);
13173                 a.t -= (this.offset - rad);
13174                 a.l += 1;
13175                 a.w -= (this.offset + rad + 1);
13176                 a.h -= (this.offset + rad);
13177                 a.h += 1;
13178             }
13179         break;
13180     };
13181
13182     this.adjusts = a;
13183 };
13184
13185 Ext.Shadow.prototype = {
13186     
13187     
13188     offset: 4,
13189
13190         defaultMode: "drop",
13191
13192     
13193     show : function(target){
13194         target = Ext.get(target);
13195         if(!this.el){
13196             this.el = Ext.Shadow.Pool.pull();
13197             if(this.el.dom.nextSibling != target.dom){
13198                 this.el.insertBefore(target);
13199             }
13200         }
13201         this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10)-1);
13202         if(Ext.isIE){
13203             this.el.dom.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius="+(this.offset)+")";
13204         }
13205         this.realign(
13206             target.getLeft(true),
13207             target.getTop(true),
13208             target.getWidth(),
13209             target.getHeight()
13210         );
13211         this.el.dom.style.display = "block";
13212     },
13213
13214     
13215     isVisible : function(){
13216         return this.el ? true : false;  
13217     },
13218
13219     
13220     realign : function(l, t, w, h){
13221         if(!this.el){
13222             return;
13223         }
13224         var a = this.adjusts, d = this.el.dom, s = d.style;
13225         var iea = 0;
13226         s.left = (l+a.l)+"px";
13227         s.top = (t+a.t)+"px";
13228         var sw = (w+a.w), sh = (h+a.h), sws = sw +"px", shs = sh + "px";
13229         if(s.width != sws || s.height != shs){
13230             s.width = sws;
13231             s.height = shs;
13232             if(!Ext.isIE){
13233                 var cn = d.childNodes;
13234                 var sww = Math.max(0, (sw-12))+"px";
13235                 cn[0].childNodes[1].style.width = sww;
13236                 cn[1].childNodes[1].style.width = sww;
13237                 cn[2].childNodes[1].style.width = sww;
13238                 cn[1].style.height = Math.max(0, (sh-12))+"px";
13239             }
13240         }
13241     },
13242
13243     
13244     hide : function(){
13245         if(this.el){
13246             this.el.dom.style.display = "none";
13247             Ext.Shadow.Pool.push(this.el);
13248             delete this.el;
13249         }
13250     },
13251
13252     
13253     setZIndex : function(z){
13254         this.zIndex = z;
13255         if(this.el){
13256             this.el.setStyle("z-index", z);
13257         }
13258     }
13259 };
13260
13261 Ext.Shadow.Pool = function(){
13262     var p = [];
13263     var markup = Ext.isIE ?
13264                  '<div class="x-ie-shadow"></div>' :
13265                  '<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>';
13266     return {
13267         pull : function(){
13268             var sh = p.shift();
13269             if(!sh){
13270                 sh = Ext.get(Ext.DomHelper.insertHtml("beforeBegin", document.body.firstChild, markup));
13271                 sh.autoBoxAdjust = false;
13272             }
13273             return sh;
13274         },
13275
13276         push : function(sh){
13277             p.push(sh);
13278         }
13279     };
13280 }();
13281
13282 Ext.BoxComponent = Ext.extend(Ext.Component, {
13283     
13284     
13285     
13286     
13287     
13288     
13289     
13290     
13291     
13292
13293     initComponent : function(){
13294         Ext.BoxComponent.superclass.initComponent.call(this);
13295         this.addEvents(
13296             
13297             'resize',
13298             
13299             'move'
13300         );
13301     },
13302
13303         boxReady : false,
13304         deferHeight: false,
13305
13306     
13307     setSize : function(w, h){
13308                 if(typeof w == 'object'){
13309             h = w.height;
13310             w = w.width;
13311         }
13312                 if(!this.boxReady){
13313             this.width = w;
13314             this.height = h;
13315             return this;
13316         }
13317
13318                 if(this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
13319             return this;
13320         }
13321         this.lastSize = {width: w, height: h};
13322         var adj = this.adjustSize(w, h);
13323         var aw = adj.width, ah = adj.height;
13324         if(aw !== undefined || ah !== undefined){             var rz = this.getResizeEl();
13325             if(!this.deferHeight && aw !== undefined && ah !== undefined){
13326                 rz.setSize(aw, ah);
13327             }else if(!this.deferHeight && ah !== undefined){
13328                 rz.setHeight(ah);
13329             }else if(aw !== undefined){
13330                 rz.setWidth(aw);
13331             }
13332             this.onResize(aw, ah, w, h);
13333             this.fireEvent('resize', this, aw, ah, w, h);
13334         }
13335         return this;
13336     },
13337
13338     
13339     setWidth : function(width){
13340         return this.setSize(width);
13341     },
13342
13343     
13344     setHeight : function(height){
13345         return this.setSize(undefined, height);
13346     },
13347
13348     
13349     getSize : function(){
13350         return this.el.getSize();
13351     },
13352
13353     
13354     getPosition : function(local){
13355         if(local === true){
13356             return [this.el.getLeft(true), this.el.getTop(true)];
13357         }
13358         return this.xy || this.el.getXY();
13359     },
13360
13361     
13362     getBox : function(local){
13363         var s = this.el.getSize();
13364         if(local === true){
13365             s.x = this.el.getLeft(true);
13366             s.y = this.el.getTop(true);
13367         }else{
13368             var xy = this.xy || this.el.getXY();
13369             s.x = xy[0];
13370             s.y = xy[1];
13371         }
13372         return s;
13373     },
13374
13375     
13376     updateBox : function(box){
13377         this.setSize(box.width, box.height);
13378         this.setPagePosition(box.x, box.y);
13379         return this;
13380     },
13381
13382         getResizeEl : function(){
13383         return this.resizeEl || this.el;
13384     },
13385
13386         getPositionEl : function(){
13387         return this.positionEl || this.el;
13388     },
13389
13390     
13391     setPosition : function(x, y){
13392         if(x && typeof x[1] == 'number'){
13393             y = x[1];
13394             x = x[0];
13395         }
13396         this.x = x;
13397         this.y = y;
13398         if(!this.boxReady){
13399             return this;
13400         }
13401         var adj = this.adjustPosition(x, y);
13402         var ax = adj.x, ay = adj.y;
13403
13404         var el = this.getPositionEl();
13405         if(ax !== undefined || ay !== undefined){
13406             if(ax !== undefined && ay !== undefined){
13407                 el.setLeftTop(ax, ay);
13408             }else if(ax !== undefined){
13409                 el.setLeft(ax);
13410             }else if(ay !== undefined){
13411                 el.setTop(ay);
13412             }
13413             this.onPosition(ax, ay);
13414             this.fireEvent('move', this, ax, ay);
13415         }
13416         return this;
13417     },
13418
13419     
13420     setPagePosition : function(x, y){
13421         if(x && typeof x[1] == 'number'){
13422             y = x[1];
13423             x = x[0];
13424         }
13425         this.pageX = x;
13426         this.pageY = y;
13427         if(!this.boxReady){
13428             return;
13429         }
13430         if(x === undefined || y === undefined){             return;
13431         }
13432         var p = this.el.translatePoints(x, y);
13433         this.setPosition(p.left, p.top);
13434         return this;
13435     },
13436
13437         onRender : function(ct, position){
13438         Ext.BoxComponent.superclass.onRender.call(this, ct, position);
13439         if(this.resizeEl){
13440             this.resizeEl = Ext.get(this.resizeEl);
13441         }
13442         if(this.positionEl){
13443             this.positionEl = Ext.get(this.positionEl);
13444         }
13445     },
13446
13447         afterRender : function(){
13448         Ext.BoxComponent.superclass.afterRender.call(this);
13449         this.boxReady = true;
13450         this.setSize(this.width, this.height);
13451         if(this.x || this.y){
13452             this.setPosition(this.x, this.y);
13453         }else if(this.pageX || this.pageY){
13454             this.setPagePosition(this.pageX, this.pageY);
13455         }
13456     },
13457
13458     
13459     syncSize : function(){
13460         delete this.lastSize;
13461         this.setSize(this.autoWidth ? undefined : this.el.getWidth(), this.autoHeight ? undefined : this.el.getHeight());
13462         return this;
13463     },
13464
13465     
13466     onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
13467
13468     },
13469
13470     
13471     onPosition : function(x, y){
13472
13473     },
13474
13475         adjustSize : function(w, h){
13476         if(this.autoWidth){
13477             w = 'auto';
13478         }
13479         if(this.autoHeight){
13480             h = 'auto';
13481         }
13482         return {width : w, height: h};
13483     },
13484
13485         adjustPosition : function(x, y){
13486         return {x : x, y: y};
13487     }
13488 });
13489 Ext.reg('box', Ext.BoxComponent);
13490
13491 Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy){
13492     
13493     
13494     this.el = Ext.get(dragElement, true);
13495     this.el.dom.unselectable = "on";
13496     
13497     this.resizingEl = Ext.get(resizingElement, true);
13498
13499     
13500     this.orientation = orientation || Ext.SplitBar.HORIZONTAL;
13501     
13502     
13503     this.minSize = 0;
13504     
13505     
13506     this.maxSize = 2000;
13507     
13508     
13509     this.animate = false;
13510     
13511     
13512     this.useShim = false;
13513     
13514     
13515     this.shim = null;
13516     
13517     if(!existingProxy){
13518         
13519         this.proxy = Ext.SplitBar.createProxy(this.orientation);
13520     }else{
13521         this.proxy = Ext.get(existingProxy).dom;
13522     }
13523     
13524     this.dd = new Ext.dd.DDProxy(this.el.dom.id, "XSplitBars", {dragElId : this.proxy.id});
13525     
13526     
13527     this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);
13528     
13529     
13530     this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);
13531     
13532     
13533     this.dragSpecs = {};
13534     
13535     
13536     this.adapter = new Ext.SplitBar.BasicLayoutAdapter();
13537     this.adapter.init(this);
13538     
13539     if(this.orientation == Ext.SplitBar.HORIZONTAL){
13540         
13541         this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? Ext.SplitBar.LEFT : Ext.SplitBar.RIGHT);
13542         this.el.addClass("x-splitbar-h");
13543     }else{
13544         
13545         this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? Ext.SplitBar.TOP : Ext.SplitBar.BOTTOM);
13546         this.el.addClass("x-splitbar-v");
13547     }
13548     
13549     this.addEvents(
13550         
13551         "resize",
13552         
13553         "moved",
13554         
13555         "beforeresize",
13556
13557         "beforeapply"
13558     );
13559
13560     Ext.SplitBar.superclass.constructor.call(this);
13561 };
13562
13563 Ext.extend(Ext.SplitBar, Ext.util.Observable, {
13564     onStartProxyDrag : function(x, y){
13565         this.fireEvent("beforeresize", this);
13566         this.overlay =  Ext.DomHelper.append(document.body,  {cls: "x-drag-overlay", html: "&#160;"}, true);
13567         this.overlay.unselectable();
13568         this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
13569         this.overlay.show();
13570         Ext.get(this.proxy).setDisplayed("block");
13571         var size = this.adapter.getElementSize(this);
13572         this.activeMinSize = this.getMinimumSize();;
13573         this.activeMaxSize = this.getMaximumSize();;
13574         var c1 = size - this.activeMinSize;
13575         var c2 = Math.max(this.activeMaxSize - size, 0);
13576         if(this.orientation == Ext.SplitBar.HORIZONTAL){
13577             this.dd.resetConstraints();
13578             this.dd.setXConstraint(
13579                 this.placement == Ext.SplitBar.LEFT ? c1 : c2, 
13580                 this.placement == Ext.SplitBar.LEFT ? c2 : c1
13581             );
13582             this.dd.setYConstraint(0, 0);
13583         }else{
13584             this.dd.resetConstraints();
13585             this.dd.setXConstraint(0, 0);
13586             this.dd.setYConstraint(
13587                 this.placement == Ext.SplitBar.TOP ? c1 : c2, 
13588                 this.placement == Ext.SplitBar.TOP ? c2 : c1
13589             );
13590          }
13591         this.dragSpecs.startSize = size;
13592         this.dragSpecs.startPoint = [x, y];
13593         Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);
13594     },
13595     
13596     
13597     onEndProxyDrag : function(e){
13598         Ext.get(this.proxy).setDisplayed(false);
13599         var endPoint = Ext.lib.Event.getXY(e);
13600         if(this.overlay){
13601             this.overlay.remove();
13602             delete this.overlay;
13603         }
13604         var newSize;
13605         if(this.orientation == Ext.SplitBar.HORIZONTAL){
13606             newSize = this.dragSpecs.startSize + 
13607                 (this.placement == Ext.SplitBar.LEFT ?
13608                     endPoint[0] - this.dragSpecs.startPoint[0] :
13609                     this.dragSpecs.startPoint[0] - endPoint[0]
13610                 );
13611         }else{
13612             newSize = this.dragSpecs.startSize + 
13613                 (this.placement == Ext.SplitBar.TOP ?
13614                     endPoint[1] - this.dragSpecs.startPoint[1] :
13615                     this.dragSpecs.startPoint[1] - endPoint[1]
13616                 );
13617         }
13618         newSize = Math.min(Math.max(newSize, this.activeMinSize), this.activeMaxSize);
13619         if(newSize != this.dragSpecs.startSize){
13620             if(this.fireEvent('beforeapply', this, newSize) !== false){
13621                 this.adapter.setElementSize(this, newSize);
13622                 this.fireEvent("moved", this, newSize);
13623                 this.fireEvent("resize", this, newSize);
13624             }
13625         }
13626     },
13627     
13628     
13629     getAdapter : function(){
13630         return this.adapter;
13631     },
13632     
13633     
13634     setAdapter : function(adapter){
13635         this.adapter = adapter;
13636         this.adapter.init(this);
13637     },
13638     
13639     
13640     getMinimumSize : function(){
13641         return this.minSize;
13642     },
13643     
13644     
13645     setMinimumSize : function(minSize){
13646         this.minSize = minSize;
13647     },
13648     
13649     
13650     getMaximumSize : function(){
13651         return this.maxSize;
13652     },
13653     
13654     
13655     setMaximumSize : function(maxSize){
13656         this.maxSize = maxSize;
13657     },
13658     
13659     
13660     setCurrentSize : function(size){
13661         var oldAnimate = this.animate;
13662         this.animate = false;
13663         this.adapter.setElementSize(this, size);
13664         this.animate = oldAnimate;
13665     },
13666     
13667     
13668     destroy : function(removeEl){
13669         if(this.shim){
13670             this.shim.remove();
13671         }
13672         this.dd.unreg();
13673         Ext.removeNode(this.proxy);
13674         if(removeEl){
13675             this.el.remove();
13676         }
13677     }
13678 });
13679
13680
13681 Ext.SplitBar.createProxy = function(dir){
13682     var proxy = new Ext.Element(document.createElement("div"));
13683     proxy.unselectable();
13684     var cls = 'x-splitbar-proxy';
13685     proxy.addClass(cls + ' ' + (dir == Ext.SplitBar.HORIZONTAL ? cls +'-h' : cls + '-v'));
13686     document.body.appendChild(proxy.dom);
13687     return proxy.dom;
13688 };
13689
13690
13691 Ext.SplitBar.BasicLayoutAdapter = function(){
13692 };
13693
13694 Ext.SplitBar.BasicLayoutAdapter.prototype = {
13695     
13696     init : function(s){
13697     
13698     },
13699     
13700      getElementSize : function(s){
13701         if(s.orientation == Ext.SplitBar.HORIZONTAL){
13702             return s.resizingEl.getWidth();
13703         }else{
13704             return s.resizingEl.getHeight();
13705         }
13706     },
13707     
13708     
13709     setElementSize : function(s, newSize, onComplete){
13710         if(s.orientation == Ext.SplitBar.HORIZONTAL){
13711             if(!s.animate){
13712                 s.resizingEl.setWidth(newSize);
13713                 if(onComplete){
13714                     onComplete(s, newSize);
13715                 }
13716             }else{
13717                 s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');
13718             }
13719         }else{
13720             
13721             if(!s.animate){
13722                 s.resizingEl.setHeight(newSize);
13723                 if(onComplete){
13724                     onComplete(s, newSize);
13725                 }
13726             }else{
13727                 s.resizingEl.setHeight(newSize, true, .1, onComplete, 'easeOut');
13728             }
13729         }
13730     }
13731 };
13732
13733
13734 Ext.SplitBar.AbsoluteLayoutAdapter = function(container){
13735     this.basic = new Ext.SplitBar.BasicLayoutAdapter();
13736     this.container = Ext.get(container);
13737 };
13738
13739 Ext.SplitBar.AbsoluteLayoutAdapter.prototype = {
13740     init : function(s){
13741         this.basic.init(s);
13742     },
13743     
13744     getElementSize : function(s){
13745         return this.basic.getElementSize(s);
13746     },
13747     
13748     setElementSize : function(s, newSize, onComplete){
13749         this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));
13750     },
13751     
13752     moveSplitter : function(s){
13753         var yes = Ext.SplitBar;
13754         switch(s.placement){
13755             case yes.LEFT:
13756                 s.el.setX(s.resizingEl.getRight());
13757                 break;
13758             case yes.RIGHT:
13759                 s.el.setStyle("right", (this.container.getWidth() - s.resizingEl.getLeft()) + "px");
13760                 break;
13761             case yes.TOP:
13762                 s.el.setY(s.resizingEl.getBottom());
13763                 break;
13764             case yes.BOTTOM:
13765                 s.el.setY(s.resizingEl.getTop() - s.el.getHeight());
13766                 break;
13767         }
13768     }
13769 };
13770
13771
13772 Ext.SplitBar.VERTICAL = 1;
13773
13774
13775 Ext.SplitBar.HORIZONTAL = 2;
13776
13777
13778 Ext.SplitBar.LEFT = 1;
13779
13780
13781 Ext.SplitBar.RIGHT = 2;
13782
13783
13784 Ext.SplitBar.TOP = 3;
13785
13786
13787 Ext.SplitBar.BOTTOM = 4;
13788
13789
13790 Ext.Container = Ext.extend(Ext.BoxComponent, {
13791     
13792     
13793     
13794     
13795     
13796     
13797     
13798
13799     
13800     autoDestroy: true,
13801     
13802     
13803     defaultType: 'panel',
13804
13805         initComponent : function(){
13806         Ext.Container.superclass.initComponent.call(this);
13807
13808         this.addEvents(
13809             
13810             'afterlayout',
13811             
13812             'beforeadd',
13813             
13814             'beforeremove',
13815             
13816             'add',
13817             
13818             'remove'
13819         );
13820
13821         
13822         var items = this.items;
13823         if(items){
13824             delete this.items;
13825             if(Ext.isArray(items)){
13826                 this.add.apply(this, items);
13827             }else{
13828                 this.add(items);
13829             }
13830         }
13831     },
13832
13833         initItems : function(){
13834         if(!this.items){
13835             this.items = new Ext.util.MixedCollection(false, this.getComponentId);
13836             this.getLayout();         }
13837     },
13838
13839         setLayout : function(layout){
13840         if(this.layout && this.layout != layout){
13841             this.layout.setContainer(null);
13842         }
13843         this.initItems();
13844         this.layout = layout;
13845         layout.setContainer(this);
13846     },
13847
13848         render : function(){
13849         Ext.Container.superclass.render.apply(this, arguments);
13850         if(this.layout){
13851             if(typeof this.layout == 'string'){
13852                 this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig);
13853             }
13854             this.setLayout(this.layout);
13855
13856             if(this.activeItem !== undefined){
13857                 var item = this.activeItem;
13858                 delete this.activeItem;
13859                 this.layout.setActiveItem(item);
13860                 return;
13861             }
13862         }
13863         if(!this.ownerCt){
13864             this.doLayout();
13865         }
13866         if(this.monitorResize === true){
13867             Ext.EventManager.onWindowResize(this.doLayout, this, [false]);
13868         }
13869     },
13870
13871         getLayoutTarget : function(){
13872         return this.el;
13873     },
13874
13875         getComponentId : function(comp){
13876         return comp.itemId || comp.id;
13877     },
13878
13879     
13880     add : function(comp){
13881         if(!this.items){
13882             this.initItems();
13883         }
13884         var a = arguments, len = a.length;
13885         if(len > 1){
13886             for(var i = 0; i < len; i++) {
13887                 this.add(a[i]);
13888             }
13889             return;
13890         }
13891         var c = this.lookupComponent(this.applyDefaults(comp));
13892         var pos = this.items.length;
13893         if(this.fireEvent('beforeadd', this, c, pos) !== false && this.onBeforeAdd(c) !== false){
13894             this.items.add(c);
13895             c.ownerCt = this;
13896             this.fireEvent('add', this, c, pos);
13897         }
13898         return c;
13899     },
13900
13901     
13902     insert : function(index, comp){
13903         if(!this.items){
13904             this.initItems();
13905         }
13906         var a = arguments, len = a.length;
13907         if(len > 2){
13908             for(var i = len-1; i >= 1; --i) {
13909                 this.insert(index, a[i]);
13910             }
13911             return;
13912         }
13913         var c = this.lookupComponent(this.applyDefaults(comp));
13914
13915         if(c.ownerCt == this && this.items.indexOf(c) < index){
13916             --index;
13917         }
13918
13919         if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
13920             this.items.insert(index, c);
13921             c.ownerCt = this;
13922             this.fireEvent('add', this, c, index);
13923         }
13924         return c;
13925     },
13926
13927         applyDefaults : function(c){
13928         if(this.defaults){
13929             if(typeof c == 'string'){
13930                 c = Ext.ComponentMgr.get(c);
13931                 Ext.apply(c, this.defaults);
13932             }else if(!c.events){
13933                 Ext.applyIf(c, this.defaults);
13934             }else{
13935                 Ext.apply(c, this.defaults);
13936             }
13937         }
13938         return c;
13939     },
13940
13941         onBeforeAdd : function(item){
13942         if(item.ownerCt){
13943             item.ownerCt.remove(item, false);
13944         }
13945         if(this.hideBorders === true){
13946             item.border = (item.border === true);
13947         }
13948     },
13949
13950     
13951     remove : function(comp, autoDestroy){
13952         var c = this.getComponent(comp);
13953         if(c && this.fireEvent('beforeremove', this, c) !== false){
13954             this.items.remove(c);
13955             delete c.ownerCt;
13956             if(autoDestroy === true || (autoDestroy !== false && this.autoDestroy)){
13957                 c.destroy();
13958             }
13959             if(this.layout && this.layout.activeItem == c){
13960                 delete this.layout.activeItem;
13961             }
13962             this.fireEvent('remove', this, c);
13963         }
13964         return c;
13965     },
13966
13967     
13968     getComponent : function(comp){
13969         if(typeof comp == 'object'){
13970             return comp;
13971         }
13972         return this.items.get(comp);
13973     },
13974
13975         lookupComponent : function(comp){
13976         if(typeof comp == 'string'){
13977             return Ext.ComponentMgr.get(comp);
13978         }else if(!comp.events){
13979             return this.createComponent(comp);
13980         }
13981         return comp;
13982     },
13983
13984         createComponent : function(config){
13985         return Ext.ComponentMgr.create(config, this.defaultType);
13986     },
13987
13988     
13989     doLayout : function(shallow){
13990         if(this.rendered && this.layout){
13991             this.layout.layout();
13992         }
13993         if(shallow !== false && this.items){
13994             var cs = this.items.items;
13995             for(var i = 0, len = cs.length; i < len; i++) {
13996                 var c  = cs[i];
13997                 if(c.doLayout){
13998                     c.doLayout();
13999                 }
14000             }
14001         }
14002     },
14003
14004     
14005     getLayout : function(){
14006         if(!this.layout){
14007             var layout = new Ext.layout.ContainerLayout(this.layoutConfig);
14008             this.setLayout(layout);
14009         }
14010         return this.layout;
14011     },
14012
14013         onDestroy : function(){
14014         if(this.items){
14015             var cs = this.items.items;
14016             for(var i = 0, len = cs.length; i < len; i++) {
14017                 Ext.destroy(cs[i]);
14018             }
14019         }
14020         if(this.monitorResize){
14021             Ext.EventManager.removeResizeListener(this.doLayout, this);
14022         }
14023         Ext.Container.superclass.onDestroy.call(this);
14024     },
14025
14026     
14027     bubble : function(fn, scope, args){
14028         var p = this;
14029         while(p){
14030             if(fn.apply(scope || p, args || [p]) === false){
14031                 break;
14032             }
14033             p = p.ownerCt;
14034         }
14035     },
14036
14037     
14038     cascade : function(fn, scope, args){
14039         if(fn.apply(scope || this, args || [this]) !== false){
14040             if(this.items){
14041                 var cs = this.items.items;
14042                 for(var i = 0, len = cs.length; i < len; i++){
14043                     if(cs[i].cascade){
14044                         cs[i].cascade(fn, scope, args);
14045                     }else{
14046                         fn.apply(scope || this, args || [cs[i]]);
14047                     }
14048                 }
14049             }
14050         }
14051     },
14052
14053     
14054     findById : function(id){
14055         var m, ct = this;
14056         this.cascade(function(c){
14057             if(ct != c && c.id === id){
14058                 m = c;
14059                 return false;
14060             }
14061         });
14062         return m || null;
14063     },
14064
14065     
14066     findByType : function(xtype){
14067         return typeof xtype == 'function' ?
14068             this.findBy(function(c){
14069                 return c.constructor === xtype;
14070             }) :
14071             this.findBy(function(c){
14072                 return c.constructor.xtype === xtype;
14073             });
14074     },
14075
14076     
14077     find : function(prop, value){
14078         return this.findBy(function(c){
14079             return c[prop] === value;
14080         });
14081     },
14082
14083     
14084     findBy : function(fn, scope){
14085         var m = [], ct = this;
14086         this.cascade(function(c){
14087             if(ct != c && fn.call(scope || c, c, ct) === true){
14088                 m.push(c);
14089             }
14090         });
14091         return m;
14092     }
14093 });
14094
14095 Ext.Container.LAYOUTS = {};
14096 Ext.reg('container', Ext.Container);
14097
14098 Ext.layout.ContainerLayout = function(config){
14099     Ext.apply(this, config);
14100 };
14101
14102 Ext.layout.ContainerLayout.prototype = {
14103     
14104     
14105
14106     
14107
14108         monitorResize:false,
14109         activeItem : null,
14110
14111         layout : function(){
14112         var target = this.container.getLayoutTarget();
14113         this.onLayout(this.container, target);
14114         this.container.fireEvent('afterlayout', this.container, this);
14115     },
14116
14117         onLayout : function(ct, target){
14118         this.renderAll(ct, target);
14119     },
14120
14121         isValidParent : function(c, target){
14122                 var el = c.getPositionEl ? c.getPositionEl() : c.getEl();
14123                 return el.dom.parentNode == target.dom;
14124     },
14125
14126         renderAll : function(ct, target){
14127         var items = ct.items.items;
14128         for(var i = 0, len = items.length; i < len; i++) {
14129             var c = items[i];
14130             if(c && (!c.rendered || !this.isValidParent(c, target))){
14131                 this.renderItem(c, i, target);
14132             }
14133         }
14134     },
14135
14136         renderItem : function(c, position, target){
14137         if(c && !c.rendered){
14138             c.render(target, position);
14139             if(this.extraCls){
14140                 var t = c.getPositionEl ? c.getPositionEl() : c;
14141                 t.addClass(this.extraCls);
14142             }
14143             if (this.renderHidden && c != this.activeItem) {
14144                 c.hide();
14145             }
14146         }else if(c && !this.isValidParent(c, target)){
14147             if(this.extraCls){
14148                 c.addClass(this.extraCls);
14149             }
14150             if(typeof position == 'number'){
14151                 position = target.dom.childNodes[position];
14152             }
14153             target.dom.insertBefore(c.getEl().dom, position || null);
14154             if (this.renderHidden && c != this.activeItem) {
14155                 c.hide();
14156             }
14157         }
14158     },
14159
14160         onResize: function(){
14161         if(this.container.collapsed){
14162             return;
14163         }
14164         var b = this.container.bufferResize;
14165         if(b){
14166             if(!this.resizeTask){
14167                 this.resizeTask = new Ext.util.DelayedTask(this.layout, this);
14168                 this.resizeBuffer = typeof b == 'number' ? b : 100;
14169             }
14170             this.resizeTask.delay(this.resizeBuffer);
14171         }else{
14172             this.layout();
14173         }
14174     },
14175
14176         setContainer : function(ct){
14177         if(this.monitorResize && ct != this.container){
14178             if(this.container){
14179                 this.container.un('resize', this.onResize, this);
14180             }
14181             if(ct){
14182                 ct.on('resize', this.onResize, this);
14183             }
14184         }
14185         this.container = ct;
14186     },
14187
14188         parseMargins : function(v){
14189         var ms = v.split(' ');
14190         var len = ms.length;
14191         if(len == 1){
14192             ms[1] = ms[0];
14193             ms[2] = ms[0];
14194             ms[3] = ms[0];
14195         }
14196         if(len == 2){
14197             ms[2] = ms[0];
14198             ms[3] = ms[1];
14199         }
14200         return {
14201             top:parseInt(ms[0], 10) || 0,
14202             right:parseInt(ms[1], 10) || 0,
14203             bottom:parseInt(ms[2], 10) || 0,
14204             left:parseInt(ms[3], 10) || 0
14205         };
14206     }
14207 };
14208 Ext.Container.LAYOUTS['auto'] = Ext.layout.ContainerLayout;
14209
14210 Ext.layout.FitLayout = Ext.extend(Ext.layout.ContainerLayout, {
14211     
14212     monitorResize:true,
14213
14214     
14215     onLayout : function(ct, target){
14216         Ext.layout.FitLayout.superclass.onLayout.call(this, ct, target);
14217         if(!this.container.collapsed){
14218             this.setItemSize(this.activeItem || ct.items.itemAt(0), target.getStyleSize());
14219         }
14220     },
14221
14222     
14223     setItemSize : function(item, size){
14224         if(item && size.height > 0){ 
14225             item.setSize(size);
14226         }
14227     }
14228 });
14229 Ext.Container.LAYOUTS['fit'] = Ext.layout.FitLayout;
14230
14231 Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {
14232     
14233     deferredRender : false,
14234
14235     
14236     renderHidden : true,
14237
14238     
14239     setActiveItem : function(item){
14240         item = this.container.getComponent(item);
14241         if(this.activeItem != item){
14242             if(this.activeItem){
14243                 this.activeItem.hide();
14244             }
14245             this.activeItem = item;
14246             item.show();
14247             this.layout();
14248         }
14249     },
14250
14251     
14252     renderAll : function(ct, target){
14253         if(this.deferredRender){
14254             this.renderItem(this.activeItem, undefined, target);
14255         }else{
14256             Ext.layout.CardLayout.superclass.renderAll.call(this, ct, target);
14257         }
14258     }
14259 });
14260 Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;
14261
14262 Ext.layout.AnchorLayout = Ext.extend(Ext.layout.ContainerLayout, {
14263     
14264     monitorResize:true,
14265
14266     
14267     getAnchorViewSize : function(ct, target){
14268         return target.dom == document.body ?
14269                    target.getViewSize() : target.getStyleSize();
14270     },
14271
14272     
14273     onLayout : function(ct, target){
14274         Ext.layout.AnchorLayout.superclass.onLayout.call(this, ct, target);
14275
14276         var size = this.getAnchorViewSize(ct, target);
14277
14278         var w = size.width, h = size.height;
14279
14280         if(w < 20 || h < 20){
14281             return;
14282         }
14283
14284         
14285         var aw, ah;
14286         if(ct.anchorSize){
14287             if(typeof ct.anchorSize == 'number'){
14288                 aw = ct.anchorSize;
14289             }else{
14290                 aw = ct.anchorSize.width;
14291                 ah = ct.anchorSize.height;
14292             }
14293         }else{
14294             aw = ct.initialConfig.width;
14295             ah = ct.initialConfig.height;
14296         }
14297
14298         var cs = ct.items.items, len = cs.length, i, c, a, cw, ch;
14299         for(i = 0; i < len; i++){
14300             c = cs[i];
14301             if(c.anchor){
14302                 a = c.anchorSpec;
14303                 if(!a){ 
14304                     var vs = c.anchor.split(' ');
14305                     c.anchorSpec = a = {
14306                         right: this.parseAnchor(vs[0], c.initialConfig.width, aw),
14307                         bottom: this.parseAnchor(vs[1], c.initialConfig.height, ah)
14308                     };
14309                 }
14310                 cw = a.right ? this.adjustWidthAnchor(a.right(w), c) : undefined;
14311                 ch = a.bottom ? this.adjustHeightAnchor(a.bottom(h), c) : undefined;
14312
14313                 if(cw || ch){
14314                     c.setSize(cw || undefined, ch || undefined);
14315                 }
14316             }
14317         }
14318     },
14319
14320     
14321     parseAnchor : function(a, start, cstart){
14322         if(a && a != 'none'){
14323             var last;
14324             if(/^(r|right|b|bottom)$/i.test(a)){   
14325                 var diff = cstart - start;
14326                 return function(v){
14327                     if(v !== last){
14328                         last = v;
14329                         return v - diff;
14330                     }
14331                 }
14332             }else if(a.indexOf('%') != -1){
14333                 var ratio = parseFloat(a.replace('%', ''))*.01;   
14334                 return function(v){
14335                     if(v !== last){
14336                         last = v;
14337                         return Math.floor(v*ratio);
14338                     }
14339                 }
14340             }else{
14341                 a = parseInt(a, 10);
14342                 if(!isNaN(a)){                            
14343                     return function(v){
14344                         if(v !== last){
14345                             last = v;
14346                             return v + a;
14347                         }
14348                     }
14349                 }
14350             }
14351         }
14352         return false;
14353     },
14354
14355     
14356     adjustWidthAnchor : function(value, comp){
14357         return value;
14358     },
14359
14360     
14361     adjustHeightAnchor : function(value, comp){
14362         return value;
14363     }
14364     
14365     
14366 });
14367 Ext.Container.LAYOUTS['anchor'] = Ext.layout.AnchorLayout;
14368
14369 Ext.layout.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {
14370     
14371     monitorResize:true,
14372     
14373     extraCls: 'x-column',
14374
14375     scrollOffset : 0,
14376
14377     
14378     isValidParent : function(c, target){
14379         return c.getEl().dom.parentNode == this.innerCt.dom;
14380     },
14381
14382     
14383     onLayout : function(ct, target){
14384         var cs = ct.items.items, len = cs.length, c, i;
14385
14386         if(!this.innerCt){
14387             target.addClass('x-column-layout-ct');
14388
14389             
14390             
14391             this.innerCt = target.createChild({cls:'x-column-inner'});
14392             this.innerCt.createChild({cls:'x-clear'});
14393         }
14394         this.renderAll(ct, this.innerCt);
14395
14396         var size = target.getViewSize();
14397
14398         if(size.width < 1 && size.height < 1){ 
14399             return;
14400         }
14401
14402         var w = size.width - target.getPadding('lr') - this.scrollOffset,
14403             h = size.height - target.getPadding('tb'),
14404             pw = w;
14405
14406         this.innerCt.setWidth(w);
14407         
14408         
14409         
14410
14411         for(i = 0; i < len; i++){
14412             c = cs[i];
14413             if(!c.columnWidth){
14414                 pw -= (c.getSize().width + c.getEl().getMargins('lr'));
14415             }
14416         }
14417
14418         pw = pw < 0 ? 0 : pw;
14419
14420         for(i = 0; i < len; i++){
14421             c = cs[i];
14422             if(c.columnWidth){
14423                 c.setSize(Math.floor(c.columnWidth*pw) - c.getEl().getMargins('lr'));
14424             }
14425         }
14426     }
14427     
14428     
14429 });
14430
14431 Ext.Container.LAYOUTS['column'] = Ext.layout.ColumnLayout;
14432
14433 Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {
14434         monitorResize:true,
14435         rendered : false,
14436
14437         onLayout : function(ct, target){
14438         var collapsed;
14439         if(!this.rendered){
14440             target.position();
14441             target.addClass('x-border-layout-ct');
14442             var items = ct.items.items;
14443             collapsed = [];
14444             for(var i = 0, len = items.length; i < len; i++) {
14445                 var c = items[i];
14446                 var pos = c.region;
14447                 if(c.collapsed){
14448                     collapsed.push(c);
14449                 }
14450                 c.collapsed = false;
14451                 if(!c.rendered){
14452                     c.cls = c.cls ? c.cls +' x-border-panel' : 'x-border-panel';
14453                     c.render(target, i);
14454                 }
14455                 this[pos] = pos != 'center' && c.split ?
14456                     new Ext.layout.BorderLayout.SplitRegion(this, c.initialConfig, pos) :
14457                     new Ext.layout.BorderLayout.Region(this, c.initialConfig, pos);
14458                 this[pos].render(target, c);
14459             }
14460             this.rendered = true;
14461         }
14462
14463         var size = target.getViewSize();
14464         if(size.width < 20 || size.height < 20){             if(collapsed){
14465                 this.restoreCollapsed = collapsed;
14466             }
14467             return;
14468         }else if(this.restoreCollapsed){
14469             collapsed = this.restoreCollapsed;
14470             delete this.restoreCollapsed;
14471         }
14472
14473         var w = size.width, h = size.height;
14474         var centerW = w, centerH = h, centerY = 0, centerX = 0;
14475
14476         var n = this.north, s = this.south, west = this.west, e = this.east, c = this.center;
14477         if(!c){
14478             throw 'No center region defined in BorderLayout ' + ct.id;
14479         }
14480
14481         if(n && n.isVisible()){
14482             var b = n.getSize();
14483             var m = n.getMargins();
14484             b.width = w - (m.left+m.right);
14485             b.x = m.left;
14486             b.y = m.top;
14487             centerY = b.height + b.y + m.bottom;
14488             centerH -= centerY;
14489             n.applyLayout(b);
14490         }
14491         if(s && s.isVisible()){
14492             var b = s.getSize();
14493             var m = s.getMargins();
14494             b.width = w - (m.left+m.right);
14495             b.x = m.left;
14496             var totalHeight = (b.height + m.top + m.bottom);
14497             b.y = h - totalHeight + m.top;
14498             centerH -= totalHeight;
14499             s.applyLayout(b);
14500         }
14501         if(west && west.isVisible()){
14502             var b = west.getSize();
14503             var m = west.getMargins();
14504             b.height = centerH - (m.top+m.bottom);
14505             b.x = m.left;
14506             b.y = centerY + m.top;
14507             var totalWidth = (b.width + m.left + m.right);
14508             centerX += totalWidth;
14509             centerW -= totalWidth;
14510             west.applyLayout(b);
14511         }
14512         if(e && e.isVisible()){
14513             var b = e.getSize();
14514             var m = e.getMargins();
14515             b.height = centerH - (m.top+m.bottom);
14516             var totalWidth = (b.width + m.left + m.right);
14517             b.x = w - totalWidth + m.left;
14518             b.y = centerY + m.top;
14519             centerW -= totalWidth;
14520             e.applyLayout(b);
14521         }
14522
14523         var m = c.getMargins();
14524         var centerBox = {
14525             x: centerX + m.left,
14526             y: centerY + m.top,
14527             width: centerW - (m.left+m.right),
14528             height: centerH - (m.top+m.bottom)
14529         };
14530         c.applyLayout(centerBox);
14531
14532         if(collapsed){
14533             for(var i = 0, len = collapsed.length; i < len; i++){
14534                 collapsed[i].collapse(false);
14535             }
14536         }
14537
14538         if(Ext.isIE && Ext.isStrict){             target.repaint();
14539         }
14540     }
14541     
14542     
14543 });
14544
14545
14546 Ext.layout.BorderLayout.Region = function(layout, config, pos){
14547     Ext.apply(this, config);
14548     this.layout = layout;
14549     this.position = pos;
14550     this.state = {};
14551     if(typeof this.margins == 'string'){
14552         this.margins = this.layout.parseMargins(this.margins);
14553     }
14554     this.margins = Ext.applyIf(this.margins || {}, this.defaultMargins);
14555     if(this.collapsible){
14556         if(typeof this.cmargins == 'string'){
14557             this.cmargins = this.layout.parseMargins(this.cmargins);
14558         }
14559         if(this.collapseMode == 'mini' && !this.cmargins){
14560             this.cmargins = {left:0,top:0,right:0,bottom:0};
14561         }else{
14562             this.cmargins = Ext.applyIf(this.cmargins || {},
14563                 pos == 'north' || pos == 'south' ? this.defaultNSCMargins : this.defaultEWCMargins);
14564         }
14565     }
14566 };
14567
14568 Ext.layout.BorderLayout.Region.prototype = {
14569     
14570     
14571     
14572     
14573     
14574     
14575     collapsible : false,
14576     
14577     split:false,
14578     
14579     floatable: true,
14580     
14581     minWidth:50,
14582     
14583     minHeight:50,
14584
14585         defaultMargins : {left:0,top:0,right:0,bottom:0},
14586         defaultNSCMargins : {left:5,top:5,right:5,bottom:5},
14587         defaultEWCMargins : {left:5,top:0,right:5,bottom:0},
14588
14589     
14590     isCollapsed : false,
14591
14592     
14593     
14594     
14595
14596         render : function(ct, p){
14597         this.panel = p;
14598         p.el.enableDisplayMode();
14599         this.targetEl = ct;
14600         this.el = p.el;
14601
14602         var gs = p.getState, ps = this.position;
14603         p.getState = function(){
14604             return Ext.apply(gs.call(p) || {}, this.state);
14605         }.createDelegate(this);
14606
14607         if(ps != 'center'){
14608             p.allowQueuedExpand = false;
14609             p.on({
14610                 beforecollapse: this.beforeCollapse,
14611                 collapse: this.onCollapse,
14612                 beforeexpand: this.beforeExpand,
14613                 expand: this.onExpand,
14614                 hide: this.onHide,
14615                 show: this.onShow,
14616                 scope: this
14617             });
14618             if(this.collapsible){
14619                 p.collapseEl = 'el';
14620                 p.slideAnchor = this.getSlideAnchor();
14621             }
14622             if(p.tools && p.tools.toggle){
14623                 p.tools.toggle.addClass('x-tool-collapse-'+ps);
14624                 p.tools.toggle.addClassOnOver('x-tool-collapse-'+ps+'-over');
14625             }
14626         }
14627     },
14628
14629         getCollapsedEl : function(){
14630         if(!this.collapsedEl){
14631             if(!this.toolTemplate){
14632                 var tt = new Ext.Template(
14633                      '<div class="x-tool x-tool-{id}">&#160;</div>'
14634                 );
14635                 tt.disableFormats = true;
14636                 tt.compile();
14637                 Ext.layout.BorderLayout.Region.prototype.toolTemplate = tt;
14638             }
14639             this.collapsedEl = this.targetEl.createChild({
14640                 cls: "x-layout-collapsed x-layout-collapsed-"+this.position,
14641                 id: this.panel.id + '-xcollapsed'
14642             });
14643             this.collapsedEl.enableDisplayMode('block');
14644
14645             if(this.collapseMode == 'mini'){
14646                 this.collapsedEl.addClass('x-layout-cmini-'+this.position);
14647                 this.miniCollapsedEl = this.collapsedEl.createChild({
14648                     cls: "x-layout-mini x-layout-mini-"+this.position, html: "&#160;"
14649                 });
14650                 this.miniCollapsedEl.addClassOnOver('x-layout-mini-over');
14651                 this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
14652                 this.collapsedEl.on('click', this.onExpandClick, this, {stopEvent:true});
14653             }else {
14654                 var t = this.toolTemplate.append(
14655                         this.collapsedEl.dom,
14656                         {id:'expand-'+this.position}, true);
14657                 t.addClassOnOver('x-tool-expand-'+this.position+'-over');
14658                 t.on('click', this.onExpandClick, this, {stopEvent:true});
14659                 
14660                 if(this.floatable !== false){
14661                    this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
14662                    this.collapsedEl.on("click", this.collapseClick, this);
14663                 }
14664             }
14665         }
14666         return this.collapsedEl;
14667     },
14668
14669         onExpandClick : function(e){
14670         if(this.isSlid){
14671             this.afterSlideIn();
14672             this.panel.expand(false);
14673         }else{
14674             this.panel.expand();
14675         }
14676     },
14677
14678         onCollapseClick : function(e){
14679         this.panel.collapse();
14680     },
14681
14682         beforeCollapse : function(p, animate){
14683         this.lastAnim = animate;
14684         if(this.splitEl){
14685             this.splitEl.hide();
14686         }
14687         this.getCollapsedEl().show();
14688         this.panel.el.setStyle('z-index', 100);
14689         this.isCollapsed = true;
14690         this.layout.layout();
14691     },
14692
14693         onCollapse : function(animate){
14694         this.panel.el.setStyle('z-index', 1);
14695         if(this.lastAnim === false || this.panel.animCollapse === false){
14696             this.getCollapsedEl().dom.style.visibility = 'visible';
14697         }else{
14698             this.getCollapsedEl().slideIn(this.panel.slideAnchor, {duration:.2});
14699         }
14700         this.state.collapsed = true;
14701         this.panel.saveState();
14702     },
14703
14704         beforeExpand : function(animate){
14705         var c = this.getCollapsedEl();
14706         this.el.show();
14707         if(this.position == 'east' || this.position == 'west'){
14708             this.panel.setSize(undefined, c.getHeight());
14709         }else{
14710             this.panel.setSize(c.getWidth(), undefined);
14711         }
14712         c.hide();
14713         c.dom.style.visibility = 'hidden';
14714         this.panel.el.setStyle('z-index', 100);
14715     },
14716
14717         onExpand : function(){
14718         this.isCollapsed = false;
14719         if(this.splitEl){
14720             this.splitEl.show();
14721         }
14722         this.layout.layout();
14723         this.panel.el.setStyle('z-index', 1);
14724         this.state.collapsed = false;
14725         this.panel.saveState();
14726     },
14727
14728         collapseClick : function(e){
14729         if(this.isSlid){
14730            e.stopPropagation();
14731            this.slideIn();
14732         }else{
14733            e.stopPropagation();
14734            this.slideOut();
14735         }
14736     },
14737
14738         onHide : function(){
14739         if(this.isCollapsed){
14740             this.getCollapsedEl().hide();
14741         }else if(this.splitEl){
14742             this.splitEl.hide();
14743         }
14744     },
14745
14746         onShow : function(){
14747         if(this.isCollapsed){
14748             this.getCollapsedEl().show();
14749         }else if(this.splitEl){
14750             this.splitEl.show();
14751         }
14752     },
14753
14754     
14755     isVisible : function(){
14756         return !this.panel.hidden;
14757     },
14758
14759     
14760     getMargins : function(){
14761         return this.isCollapsed && this.cmargins ? this.cmargins : this.margins;
14762     },
14763
14764     
14765     getSize : function(){
14766         return this.isCollapsed ? this.getCollapsedEl().getSize() : this.panel.getSize();
14767     },
14768
14769     
14770     setPanel : function(panel){
14771         this.panel = panel;
14772     },
14773
14774     
14775     getMinWidth: function(){
14776         return this.minWidth;
14777     },
14778
14779     
14780     getMinHeight: function(){
14781         return this.minHeight;
14782     },
14783
14784         applyLayoutCollapsed : function(box){
14785         var ce = this.getCollapsedEl();
14786         ce.setLeftTop(box.x, box.y);
14787         ce.setSize(box.width, box.height);
14788     },
14789
14790         applyLayout : function(box){
14791         if(this.isCollapsed){
14792             this.applyLayoutCollapsed(box);
14793         }else{
14794             this.panel.setPosition(box.x, box.y);
14795             this.panel.setSize(box.width, box.height);
14796         }
14797     },
14798
14799         beforeSlide: function(){
14800         this.panel.beforeEffect();
14801     },
14802
14803         afterSlide : function(){
14804         this.panel.afterEffect();
14805     },
14806
14807         initAutoHide : function(){
14808         if(this.autoHide !== false){
14809             if(!this.autoHideHd){
14810                 var st = new Ext.util.DelayedTask(this.slideIn, this);
14811                 this.autoHideHd = {
14812                     "mouseout": function(e){
14813                         if(!e.within(this.el, true)){
14814                             st.delay(500);
14815                         }
14816                     },
14817                     "mouseover" : function(e){
14818                         st.cancel();
14819                     },
14820                     scope : this
14821                 };
14822             }
14823             this.el.on(this.autoHideHd);
14824         }
14825     },
14826
14827         clearAutoHide : function(){
14828         if(this.autoHide !== false){
14829             this.el.un("mouseout", this.autoHideHd.mouseout);
14830             this.el.un("mouseover", this.autoHideHd.mouseover);
14831         }
14832     },
14833
14834         clearMonitor : function(){
14835         Ext.getDoc().un("click", this.slideInIf, this);
14836     },
14837
14838             slideOut : function(){
14839         if(this.isSlid || this.el.hasActiveFx()){
14840             return;
14841         }
14842         this.isSlid = true;
14843         var ts = this.panel.tools;
14844         if(ts && ts.toggle){
14845             ts.toggle.hide();
14846         }
14847         this.el.show();
14848         if(this.position == 'east' || this.position == 'west'){
14849             this.panel.setSize(undefined, this.collapsedEl.getHeight());
14850         }else{
14851             this.panel.setSize(this.collapsedEl.getWidth(), undefined);
14852         }
14853         this.restoreLT = [this.el.dom.style.left, this.el.dom.style.top];
14854         this.el.alignTo(this.collapsedEl, this.getCollapseAnchor());
14855         this.el.setStyle("z-index", 102);
14856         if(this.animFloat !== false){
14857             this.beforeSlide();
14858             this.el.slideIn(this.getSlideAnchor(), {
14859                 callback: function(){
14860                     this.afterSlide();
14861                     this.initAutoHide();
14862                     Ext.getDoc().on("click", this.slideInIf, this);
14863                 },
14864                 scope: this,
14865                 block: true
14866             });
14867         }else{
14868             this.initAutoHide();
14869              Ext.getDoc().on("click", this.slideInIf, this);
14870         }
14871     },
14872
14873         afterSlideIn : function(){
14874         this.clearAutoHide();
14875         this.isSlid = false;
14876         this.clearMonitor();
14877         this.el.setStyle("z-index", "");
14878         this.el.dom.style.left = this.restoreLT[0];
14879         this.el.dom.style.top = this.restoreLT[1];
14880
14881         var ts = this.panel.tools;
14882         if(ts && ts.toggle){
14883             ts.toggle.show();
14884         }
14885     },
14886
14887         slideIn : function(cb){
14888         if(!this.isSlid || this.el.hasActiveFx()){
14889             Ext.callback(cb);
14890             return;
14891         }
14892         this.isSlid = false;
14893         if(this.animFloat !== false){
14894             this.beforeSlide();
14895             this.el.slideOut(this.getSlideAnchor(), {
14896                 callback: function(){
14897                     this.el.hide();
14898                     this.afterSlide();
14899                     this.afterSlideIn();
14900                     Ext.callback(cb);
14901                 },
14902                 scope: this,
14903                 block: true
14904             });
14905         }else{
14906             this.el.hide();
14907             this.afterSlideIn();
14908         }
14909     },
14910
14911         slideInIf : function(e){
14912         if(!e.within(this.el)){
14913             this.slideIn();
14914         }
14915     },
14916
14917         anchors : {
14918         "west" : "left",
14919         "east" : "right",
14920         "north" : "top",
14921         "south" : "bottom"
14922     },
14923
14924         sanchors : {
14925         "west" : "l",
14926         "east" : "r",
14927         "north" : "t",
14928         "south" : "b"
14929     },
14930
14931         canchors : {
14932         "west" : "tl-tr",
14933         "east" : "tr-tl",
14934         "north" : "tl-bl",
14935         "south" : "bl-tl"
14936     },
14937
14938         getAnchor : function(){
14939         return this.anchors[this.position];
14940     },
14941
14942         getCollapseAnchor : function(){
14943         return this.canchors[this.position];
14944     },
14945
14946         getSlideAnchor : function(){
14947         return this.sanchors[this.position];
14948     },
14949
14950         getAlignAdj : function(){
14951         var cm = this.cmargins;
14952         switch(this.position){
14953             case "west":
14954                 return [0, 0];
14955             break;
14956             case "east":
14957                 return [0, 0];
14958             break;
14959             case "north":
14960                 return [0, 0];
14961             break;
14962             case "south":
14963                 return [0, 0];
14964             break;
14965         }
14966     },
14967
14968         getExpandAdj : function(){
14969         var c = this.collapsedEl, cm = this.cmargins;
14970         switch(this.position){
14971             case "west":
14972                 return [-(cm.right+c.getWidth()+cm.left), 0];
14973             break;
14974             case "east":
14975                 return [cm.right+c.getWidth()+cm.left, 0];
14976             break;
14977             case "north":
14978                 return [0, -(cm.top+cm.bottom+c.getHeight())];
14979             break;
14980             case "south":
14981                 return [0, cm.top+cm.bottom+c.getHeight()];
14982             break;
14983         }
14984     }
14985 };
14986
14987
14988 Ext.layout.BorderLayout.SplitRegion = function(layout, config, pos){
14989     Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this, layout, config, pos);
14990         this.applyLayout = this.applyFns[pos];
14991 };
14992
14993 Ext.extend(Ext.layout.BorderLayout.SplitRegion, Ext.layout.BorderLayout.Region, {
14994     
14995     splitTip : "Drag to resize.",
14996     
14997     collapsibleSplitTip : "Drag to resize. Double click to hide.",
14998     
14999     useSplitTips : false,
15000
15001         splitSettings : {
15002         north : {
15003             orientation: Ext.SplitBar.VERTICAL,
15004             placement: Ext.SplitBar.TOP,
15005             maxFn : 'getVMaxSize',
15006             minProp: 'minHeight',
15007             maxProp: 'maxHeight'
15008         },
15009         south : {
15010             orientation: Ext.SplitBar.VERTICAL,
15011             placement: Ext.SplitBar.BOTTOM,
15012             maxFn : 'getVMaxSize',
15013             minProp: 'minHeight',
15014             maxProp: 'maxHeight'
15015         },
15016         east : {
15017             orientation: Ext.SplitBar.HORIZONTAL,
15018             placement: Ext.SplitBar.RIGHT,
15019             maxFn : 'getHMaxSize',
15020             minProp: 'minWidth',
15021             maxProp: 'maxWidth'
15022         },
15023         west : {
15024             orientation: Ext.SplitBar.HORIZONTAL,
15025             placement: Ext.SplitBar.LEFT,
15026             maxFn : 'getHMaxSize',
15027             minProp: 'minWidth',
15028             maxProp: 'maxWidth'
15029         }
15030     },
15031
15032         applyFns : {
15033         west : function(box){
15034             if(this.isCollapsed){
15035                 return this.applyLayoutCollapsed(box);
15036             }
15037             var sd = this.splitEl.dom, s = sd.style;
15038             this.panel.setPosition(box.x, box.y);
15039             var sw = sd.offsetWidth;
15040             s.left = (box.x+box.width-sw)+'px';
15041             s.top = (box.y)+'px';
15042             s.height = Math.max(0, box.height)+'px';
15043             this.panel.setSize(box.width-sw, box.height);
15044         },
15045         east : function(box){
15046             if(this.isCollapsed){
15047                 return this.applyLayoutCollapsed(box);
15048             }
15049             var sd = this.splitEl.dom, s = sd.style;
15050             var sw = sd.offsetWidth;
15051             this.panel.setPosition(box.x+sw, box.y);
15052             s.left = (box.x)+'px';
15053             s.top = (box.y)+'px';
15054             s.height = Math.max(0, box.height)+'px';
15055             this.panel.setSize(box.width-sw, box.height);
15056         },
15057         north : function(box){
15058             if(this.isCollapsed){
15059                 return this.applyLayoutCollapsed(box);
15060             }
15061             var sd = this.splitEl.dom, s = sd.style;
15062             var sh = sd.offsetHeight;
15063             this.panel.setPosition(box.x, box.y);
15064             s.left = (box.x)+'px';
15065             s.top = (box.y+box.height-sh)+'px';
15066             s.width = Math.max(0, box.width)+'px';
15067             this.panel.setSize(box.width, box.height-sh);
15068         },
15069         south : function(box){
15070             if(this.isCollapsed){
15071                 return this.applyLayoutCollapsed(box);
15072             }
15073             var sd = this.splitEl.dom, s = sd.style;
15074             var sh = sd.offsetHeight;
15075             this.panel.setPosition(box.x, box.y+sh);
15076             s.left = (box.x)+'px';
15077             s.top = (box.y)+'px';
15078             s.width = Math.max(0, box.width)+'px';
15079             this.panel.setSize(box.width, box.height-sh);
15080         }
15081     },
15082
15083         render : function(ct, p){
15084         Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this, ct, p);
15085
15086         var ps = this.position;
15087
15088         this.splitEl = ct.createChild({
15089             cls: "x-layout-split x-layout-split-"+ps, html: "&#160;",
15090             id: this.panel.id + '-xsplit'
15091         });
15092
15093         if(this.collapseMode == 'mini'){
15094             this.miniSplitEl = this.splitEl.createChild({
15095                 cls: "x-layout-mini x-layout-mini-"+ps, html: "&#160;"
15096             });
15097             this.miniSplitEl.addClassOnOver('x-layout-mini-over');
15098             this.miniSplitEl.on('click', this.onCollapseClick, this, {stopEvent:true});
15099         }
15100
15101         var s = this.splitSettings[ps];
15102
15103         this.split = new Ext.SplitBar(this.splitEl.dom, p.el, s.orientation);
15104         this.split.placement = s.placement;
15105         this.split.getMaximumSize = this[s.maxFn].createDelegate(this);
15106         this.split.minSize = this.minSize || this[s.minProp];
15107         this.split.on("beforeapply", this.onSplitMove, this);
15108         this.split.useShim = this.useShim === true;
15109         this.maxSize = this.maxSize || this[s.maxProp];
15110
15111         if(p.hidden){
15112             this.splitEl.hide();
15113         }
15114
15115         if(this.useSplitTips){
15116             this.splitEl.dom.title = this.collapsible ? this.collapsibleSplitTip : this.splitTip;
15117         }
15118         if(this.collapsible){
15119             this.splitEl.on("dblclick", this.onCollapseClick,  this);
15120         }
15121     },
15122
15123         getSize : function(){
15124         if(this.isCollapsed){
15125             return this.collapsedEl.getSize();
15126         }
15127         var s = this.panel.getSize();
15128         if(this.position == 'north' || this.position == 'south'){
15129             s.height += this.splitEl.dom.offsetHeight;
15130         }else{
15131             s.width += this.splitEl.dom.offsetWidth;
15132         }
15133         return s;
15134     },
15135
15136         getHMaxSize : function(){
15137          var cmax = this.maxSize || 10000;
15138          var center = this.layout.center;
15139          return Math.min(cmax, (this.el.getWidth()+center.el.getWidth())-center.getMinWidth());
15140     },
15141
15142         getVMaxSize : function(){
15143         var cmax = this.maxSize || 10000;
15144         var center = this.layout.center;
15145         return Math.min(cmax, (this.el.getHeight()+center.el.getHeight())-center.getMinHeight());
15146     },
15147
15148         onSplitMove : function(split, newSize){
15149         var s = this.panel.getSize();
15150         this.lastSplitSize = newSize;
15151         if(this.position == 'north' || this.position == 'south'){
15152             this.panel.setSize(s.width, newSize);
15153             this.state.height = newSize;
15154         }else{
15155             this.panel.setSize(newSize, s.height);
15156             this.state.width = newSize;
15157         }
15158         this.layout.layout();
15159         this.panel.saveState();
15160         return false;
15161     },
15162
15163     
15164     getSplitBar : function(){
15165         return this.split;
15166     }
15167 });
15168
15169 Ext.Container.LAYOUTS['border'] = Ext.layout.BorderLayout;
15170
15171 Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {
15172     
15173     
15174     
15175     labelSeparator : ':',
15176
15177         getAnchorViewSize : function(ct, target){
15178         return ct.body.getStyleSize();
15179     },
15180
15181         setContainer : function(ct){
15182         Ext.layout.FormLayout.superclass.setContainer.call(this, ct);
15183
15184         if(ct.labelAlign){
15185             ct.addClass('x-form-label-'+ct.labelAlign);
15186         }
15187
15188         if(ct.hideLabels){
15189             this.labelStyle = "display:none";
15190             this.elementStyle = "padding-left:0;";
15191             this.labelAdjust = 0;
15192         }else{
15193             this.labelSeparator = ct.labelSeparator || this.labelSeparator;
15194             ct.labelWidth = ct.labelWidth || 100;
15195             if(typeof ct.labelWidth == 'number'){
15196                 var pad = (typeof ct.labelPad == 'number' ? ct.labelPad : 5);
15197                 this.labelAdjust = ct.labelWidth+pad;
15198                 this.labelStyle = "width:"+ct.labelWidth+"px;";
15199                 this.elementStyle = "padding-left:"+(ct.labelWidth+pad)+'px';
15200             }
15201             if(ct.labelAlign == 'top'){
15202                 this.labelStyle = "width:auto;";
15203                 this.labelAdjust = 0;
15204                 this.elementStyle = "padding-left:0;";
15205             }
15206         }
15207
15208         if(!this.fieldTpl){
15209                         var t = new Ext.Template(
15210                 '<div class="x-form-item {5}" tabIndex="-1">',
15211                     '<label for="{0}" style="{2}" class="x-form-item-label">{1}{4}</label>',
15212                     '<div class="x-form-element" id="x-form-el-{0}" style="{3}">',
15213                     '</div><div class="{6}"></div>',
15214                 '</div>'
15215             );
15216             t.disableFormats = true;
15217             t.compile();
15218             Ext.layout.FormLayout.prototype.fieldTpl = t;
15219         }
15220     },
15221
15222         renderItem : function(c, position, target){
15223         if(c && !c.rendered && c.isFormField && c.inputType != 'hidden'){
15224             var args = [
15225                    c.id, c.fieldLabel,
15226                    c.labelStyle||this.labelStyle||'',
15227                    this.elementStyle||'',
15228                    typeof c.labelSeparator == 'undefined' ? this.labelSeparator : c.labelSeparator,
15229                    (c.itemCls||this.container.itemCls||'') + (c.hideLabel ? ' x-hide-label' : ''),
15230                    c.clearCls || 'x-form-clear-left' 
15231             ];
15232             if(typeof position == 'number'){
15233                 position = target.dom.childNodes[position] || null;
15234             }
15235             if(position){
15236                 this.fieldTpl.insertBefore(position, args);
15237             }else{
15238                 this.fieldTpl.append(target, args);
15239             }
15240             c.render('x-form-el-'+c.id);
15241         }else {
15242             Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments);
15243         }
15244     },
15245
15246         adjustWidthAnchor : function(value, comp){
15247         return value - (comp.isFormField  ? (comp.hideLabel ? 0 : this.labelAdjust) : 0);
15248     },
15249
15250         isValidParent : function(c, target){
15251         return true;
15252     }
15253
15254     
15255 });
15256
15257 Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout;
15258
15259 Ext.layout.Accordion = Ext.extend(Ext.layout.FitLayout, {
15260     
15261     fill : true,
15262     
15263     autoWidth : true,
15264     
15265     titleCollapse : true,
15266     
15267     hideCollapseTool : false,
15268     
15269     collapseFirst : false,
15270     
15271     animate : false,
15272     
15273     sequence : false,
15274     
15275     activeOnTop : false,
15276
15277     renderItem : function(c){
15278         if(this.animate === false){
15279             c.animCollapse = false;
15280         }
15281         c.collapsible = true;
15282         if(this.autoWidth){
15283             c.autoWidth = true;
15284         }
15285         if(this.titleCollapse){
15286             c.titleCollapse = true;
15287         }
15288         if(this.hideCollapseTool){
15289             c.hideCollapseTool = true;
15290         }
15291         if(this.collapseFirst !== undefined){
15292             c.collapseFirst = this.collapseFirst;
15293         }
15294         if(!this.activeItem && !c.collapsed){
15295             this.activeItem = c;
15296         }else if(this.activeItem){
15297             c.collapsed = true;
15298         }
15299         Ext.layout.Accordion.superclass.renderItem.apply(this, arguments);
15300         c.header.addClass('x-accordion-hd');
15301         c.on('beforeexpand', this.beforeExpand, this);
15302     },
15303
15304     
15305     beforeExpand : function(p, anim){
15306         var ai = this.activeItem;
15307         if(ai){
15308             if(this.sequence){
15309                 delete this.activeItem;
15310                 ai.collapse({callback:function(){
15311                     p.expand(anim || true);
15312                 }, scope: this});
15313                 return false;
15314             }else{
15315                 ai.collapse(this.animate);
15316             }
15317         }
15318         this.activeItem = p;
15319         if(this.activeOnTop){
15320             p.el.dom.parentNode.insertBefore(p.el.dom, p.el.dom.parentNode.firstChild);
15321         }
15322         this.layout();
15323     },
15324
15325     
15326     setItemSize : function(item, size){
15327         if(this.fill && item){
15328             var items = this.container.items.items;
15329             var hh = 0;
15330             for(var i = 0, len = items.length; i < len; i++){
15331                 var p = items[i];
15332                 if(p != item){
15333                     hh += (p.getSize().height - p.bwrap.getHeight());
15334                 }
15335             }
15336             size.height -= hh;
15337             item.setSize(size);
15338         }
15339     }
15340 });
15341 Ext.Container.LAYOUTS['accordion'] = Ext.layout.Accordion;
15342
15343 Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {
15344     
15345
15346     
15347     monitorResize:false,
15348
15349     
15350     setContainer : function(ct){
15351         Ext.layout.TableLayout.superclass.setContainer.call(this, ct);
15352
15353         this.currentRow = 0;
15354         this.currentColumn = 0;
15355         this.cells = [];
15356     },
15357
15358     
15359     onLayout : function(ct, target){
15360         var cs = ct.items.items, len = cs.length, c, i;
15361
15362         if(!this.table){
15363             target.addClass('x-table-layout-ct');
15364
15365             this.table = target.createChild(
15366                 {tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, null, true);
15367
15368             this.renderAll(ct, target);
15369         }
15370     },
15371
15372     
15373     getRow : function(index){
15374         var row = this.table.tBodies[0].childNodes[index];
15375         if(!row){
15376             row = document.createElement('tr');
15377             this.table.tBodies[0].appendChild(row);
15378         }
15379         return row;
15380     },
15381
15382     
15383         getNextCell : function(c){
15384                 var cell = this.getNextNonSpan(this.currentColumn, this.currentRow);
15385                 var curCol = this.currentColumn = cell[0], curRow = this.currentRow = cell[1];
15386                 for(var rowIndex = curRow; rowIndex < curRow + (c.rowspan || 1); rowIndex++){
15387                         if(!this.cells[rowIndex]){
15388                                 this.cells[rowIndex] = [];
15389                         }
15390                         for(var colIndex = curCol; colIndex < curCol + (c.colspan || 1); colIndex++){
15391                                 this.cells[rowIndex][colIndex] = true;
15392                         }
15393                 }
15394                 var td = document.createElement('td');
15395                 if(c.cellId){
15396                         td.id = c.cellId;
15397                 }
15398                 var cls = 'x-table-layout-cell';
15399                 if(c.cellCls){
15400                         cls += ' ' + c.cellCls;
15401                 }
15402                 td.className = cls;
15403                 if(c.colspan){
15404                         td.colSpan = c.colspan;
15405                 }
15406                 if(c.rowspan){
15407                         td.rowSpan = c.rowspan;
15408                 }
15409                 this.getRow(curRow).appendChild(td);
15410                 return td;
15411         },
15412     
15413     
15414         getNextNonSpan: function(colIndex, rowIndex){
15415                 var cols = this.columns;
15416                 while((cols && colIndex >= cols) || (this.cells[rowIndex] && this.cells[rowIndex][colIndex])) {
15417                         if(cols && colIndex >= cols){
15418                                 rowIndex++;
15419                                 colIndex = 0;
15420                         }else{
15421                                 colIndex++;
15422                         }
15423                 }
15424                 return [colIndex, rowIndex];
15425         },
15426
15427     
15428     renderItem : function(c, position, target){
15429         if(c && !c.rendered){
15430             c.render(this.getNextCell(c));
15431         }
15432     },
15433
15434     
15435     isValidParent : function(c, target){
15436         return true;
15437     }
15438
15439     
15440 });
15441
15442 Ext.Container.LAYOUTS['table'] = Ext.layout.TableLayout;
15443
15444 Ext.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {
15445     extraCls: 'x-abs-layout-item',
15446     isForm: false,
15447     
15448     setContainer : function(ct){
15449         Ext.layout.AbsoluteLayout.superclass.setContainer.call(this, ct);
15450         if(ct.isXType('form')){
15451             this.isForm = true;
15452         }
15453     },
15454
15455     onLayout : function(ct, target){
15456         if(this.isForm){ ct.body.position(); } else { target.position(); }
15457         Ext.layout.AbsoluteLayout.superclass.onLayout.call(this, ct, target);
15458     },
15459
15460     
15461     getAnchorViewSize : function(ct, target){
15462         return this.isForm ? ct.body.getStyleSize() : Ext.layout.AbsoluteLayout.superclass.getAnchorViewSize.call(this, ct, target);
15463     },
15464
15465     
15466     isValidParent : function(c, target){
15467         return this.isForm ? true : Ext.layout.AbsoluteLayout.superclass.isValidParent.call(this, c, target);
15468     },
15469
15470     
15471     adjustWidthAnchor : function(value, comp){
15472         return value ? value - comp.getPosition(true)[0] : value;
15473     },
15474
15475     
15476     adjustHeightAnchor : function(value, comp){
15477         return  value ? value - comp.getPosition(true)[1] : value;
15478     }
15479     
15480 });
15481 Ext.Container.LAYOUTS['absolute'] = Ext.layout.AbsoluteLayout;
15482
15483 Ext.Viewport = Ext.extend(Ext.Container, {
15484         
15485     
15486     
15487     
15488     
15489     
15490     
15491     
15492     
15493     
15494     
15495     
15496     initComponent : function() {
15497         Ext.Viewport.superclass.initComponent.call(this);
15498         document.getElementsByTagName('html')[0].className += ' x-viewport';
15499         this.el = Ext.getBody();
15500         this.el.setHeight = Ext.emptyFn;
15501         this.el.setWidth = Ext.emptyFn;
15502         this.el.setSize = Ext.emptyFn;
15503         this.el.dom.scroll = 'no';
15504         this.allowDomMove = false;
15505         this.autoWidth = true;
15506         this.autoHeight = true;
15507         Ext.EventManager.onWindowResize(this.fireResize, this);
15508         this.renderTo = this.el;
15509     },
15510
15511     fireResize : function(w, h){
15512         this.fireEvent('resize', this, w, h, w, h);
15513     }
15514 });
15515 Ext.reg('viewport', Ext.Viewport);
15516
15517 Ext.Panel = Ext.extend(Ext.Container, {
15518     
15519     
15520     
15521     
15522     
15523     
15524     
15525     
15526     
15527     
15528     
15529     
15530     
15531     
15532     
15533     
15534     
15535     
15536     
15537     
15538     
15539     
15540     
15541     
15542     
15543     
15544     
15545     
15546         
15547         
15548
15549
15550     
15551     baseCls : 'x-panel',
15552     
15553     collapsedCls : 'x-panel-collapsed',
15554     
15555     maskDisabled: true,
15556     
15557     animCollapse: Ext.enableFx,
15558     
15559     headerAsText: true,
15560     
15561     buttonAlign: 'right',
15562     
15563     collapsed : false,
15564     
15565     collapseFirst: true,
15566     
15567     minButtonWidth:75,
15568     
15569     elements : 'body',
15570
15571                 toolTarget : 'header',
15572     collapseEl : 'bwrap',
15573     slideAnchor : 't',
15574
15575         deferHeight: true,
15576         expandDefaults: {
15577         duration:.25
15578     },
15579         collapseDefaults: {
15580         duration:.25
15581     },
15582
15583         initComponent : function(){
15584         Ext.Panel.superclass.initComponent.call(this);
15585
15586         this.addEvents(
15587             
15588             'bodyresize',
15589             
15590             'titlechange',
15591             
15592             'collapse',
15593             
15594             'expand',
15595             
15596             'beforecollapse',
15597             
15598             'beforeexpand',
15599             
15600             'beforeclose',
15601             
15602             'close',
15603             
15604             'activate',
15605             
15606             'deactivate'
15607         );
15608
15609                 if(this.tbar){
15610             this.elements += ',tbar';
15611             if(typeof this.tbar == 'object'){
15612                 this.topToolbar = this.tbar;
15613             }
15614             delete this.tbar;
15615         }
15616         if(this.bbar){
15617             this.elements += ',bbar';
15618             if(typeof this.bbar == 'object'){
15619                 this.bottomToolbar = this.bbar;
15620             }
15621             delete this.bbar;
15622         }
15623
15624         if(this.header === true){
15625             this.elements += ',header';
15626             delete this.header;
15627         }else if(this.title && this.header !== false){
15628             this.elements += ',header';
15629         }
15630
15631         if(this.footer === true){
15632             this.elements += ',footer';
15633             delete this.footer;
15634         }
15635
15636         if(this.buttons){
15637             var btns = this.buttons;
15638             
15639             this.buttons = [];
15640             for(var i = 0, len = btns.length; i < len; i++) {
15641                 if(btns[i].render){                     this.buttons.push(btns[i]);
15642                 }else{
15643                     this.addButton(btns[i]);
15644                 }
15645             }
15646         }
15647         if(this.autoLoad){
15648             this.on('render', this.doAutoLoad, this, {delay:10});
15649         }
15650     },
15651
15652         createElement : function(name, pnode){
15653         if(this[name]){
15654             pnode.appendChild(this[name].dom);
15655             return;
15656         }
15657
15658         if(name === 'bwrap' || this.elements.indexOf(name) != -1){
15659             if(this[name+'Cfg']){
15660                 this[name] = Ext.fly(pnode).createChild(this[name+'Cfg']);
15661             }else{
15662                 var el = document.createElement('div');
15663                 el.className = this[name+'Cls'];
15664                 this[name] = Ext.get(pnode.appendChild(el));
15665             }
15666         }
15667     },
15668
15669         onRender : function(ct, position){
15670         Ext.Panel.superclass.onRender.call(this, ct, position);
15671
15672         this.createClasses();
15673
15674         if(this.el){             this.el.addClass(this.baseCls);
15675             this.header = this.el.down('.'+this.headerCls);
15676             this.bwrap = this.el.down('.'+this.bwrapCls);
15677             var cp = this.bwrap ? this.bwrap : this.el;
15678             this.tbar = cp.down('.'+this.tbarCls);
15679             this.body = cp.down('.'+this.bodyCls);
15680             this.bbar = cp.down('.'+this.bbarCls);
15681             this.footer = cp.down('.'+this.footerCls);
15682             this.fromMarkup = true;
15683         }else{
15684             this.el = ct.createChild({
15685                 id: this.id,
15686                 cls: this.baseCls
15687             }, position);
15688         }
15689         var el = this.el, d = el.dom;
15690
15691         if(this.cls){
15692             this.el.addClass(this.cls);
15693         }
15694
15695         if(this.buttons){
15696             this.elements += ',footer';
15697         }
15698
15699         
15700                 if(this.frame){
15701             el.insertHtml('afterBegin', String.format(Ext.Element.boxMarkup, this.baseCls));
15702
15703             this.createElement('header', d.firstChild.firstChild.firstChild);
15704             this.createElement('bwrap', d);
15705
15706                         var bw = this.bwrap.dom;
15707             var ml = d.childNodes[1], bl = d.childNodes[2];
15708             bw.appendChild(ml);
15709             bw.appendChild(bl);
15710
15711             var mc = bw.firstChild.firstChild.firstChild;
15712             this.createElement('tbar', mc);
15713             this.createElement('body', mc);
15714             this.createElement('bbar', mc);
15715             this.createElement('footer', bw.lastChild.firstChild.firstChild);
15716
15717             if(!this.footer){
15718                 this.bwrap.dom.lastChild.className += ' x-panel-nofooter';
15719             }
15720         }else{
15721             this.createElement('header', d);
15722             this.createElement('bwrap', d);
15723
15724                         var bw = this.bwrap.dom;
15725             this.createElement('tbar', bw);
15726             this.createElement('body', bw);
15727             this.createElement('bbar', bw);
15728             this.createElement('footer', bw);
15729
15730             if(!this.header){
15731                 this.body.addClass(this.bodyCls + '-noheader');
15732                 if(this.tbar){
15733                     this.tbar.addClass(this.tbarCls + '-noheader');
15734                 }
15735             }
15736         }
15737
15738         if(this.border === false){
15739             this.el.addClass(this.baseCls + '-noborder');
15740             this.body.addClass(this.bodyCls + '-noborder');
15741             if(this.header){
15742                 this.header.addClass(this.headerCls + '-noborder');
15743             }
15744             if(this.footer){
15745                 this.footer.addClass(this.footerCls + '-noborder');
15746             }
15747             if(this.tbar){
15748                 this.tbar.addClass(this.tbarCls + '-noborder');
15749             }
15750             if(this.bbar){
15751                 this.bbar.addClass(this.bbarCls + '-noborder');
15752             }
15753         }
15754
15755         if(this.bodyBorder === false){
15756            this.body.addClass(this.bodyCls + '-noborder');
15757         }
15758
15759         if(this.bodyStyle){
15760            this.body.applyStyles(this.bodyStyle);
15761         }
15762
15763         this.bwrap.enableDisplayMode('block');
15764
15765         if(this.header){
15766             this.header.unselectable();
15767
15768                         if(this.headerAsText){
15769                 this.header.dom.innerHTML =
15770                     '<span class="' + this.headerTextCls + '">'+this.header.dom.innerHTML+'</span>';
15771
15772                 if(this.iconCls){
15773                     this.setIconClass(this.iconCls);
15774                 }
15775             }
15776         }
15777
15778         if(this.floating){
15779             this.makeFloating(this.floating);
15780         }
15781
15782         if(this.collapsible){
15783             this.tools = this.tools ? this.tools.slice(0) : [];
15784             if(!this.hideCollapseTool){
15785                 this.tools[this.collapseFirst?'unshift':'push']({
15786                     id: 'toggle',
15787                     handler : this.toggleCollapse,
15788                     scope: this
15789                 });
15790             }
15791             if(this.titleCollapse && this.header){
15792                 this.header.on('click', this.toggleCollapse, this);
15793                 this.header.setStyle('cursor', 'pointer');
15794             }
15795         }
15796         if(this.tools){
15797             var ts = this.tools;
15798             this.tools = {};
15799             this.addTool.apply(this, ts);
15800         }else{
15801             this.tools = {};
15802         }
15803
15804         if(this.buttons && this.buttons.length > 0){
15805                         var tb = this.footer.createChild({cls:'x-panel-btns-ct', cn: {
15806                 cls:"x-panel-btns x-panel-btns-"+this.buttonAlign,
15807                 html:'<table cellspacing="0"><tbody><tr></tr></tbody></table><div class="x-clear"></div>'
15808             }}, null, true);
15809             var tr = tb.getElementsByTagName('tr')[0];
15810             for(var i = 0, len = this.buttons.length; i < len; i++) {
15811                 var b = this.buttons[i];
15812                 var td = document.createElement('td');
15813                 td.className = 'x-panel-btn-td';
15814                 b.render(tr.appendChild(td));
15815             }
15816         }
15817
15818         if(this.tbar && this.topToolbar){
15819             if(Ext.isArray(this.topToolbar)){
15820                 this.topToolbar = new Ext.Toolbar(this.topToolbar);
15821             }
15822             this.topToolbar.render(this.tbar);
15823         }
15824         if(this.bbar && this.bottomToolbar){
15825             if(Ext.isArray(this.bottomToolbar)){
15826                 this.bottomToolbar = new Ext.Toolbar(this.bottomToolbar);
15827             }
15828             this.bottomToolbar.render(this.bbar);
15829         }
15830     },
15831
15832     
15833     setIconClass : function(cls){
15834         var old = this.iconCls;
15835         this.iconCls = cls;
15836         if(this.rendered && this.header){
15837             if(this.frame){
15838                 this.header.addClass('x-panel-icon');
15839                 this.header.replaceClass(old, this.iconCls);
15840             }else{
15841                 var hd = this.header.dom;
15842                 var img = hd.firstChild && String(hd.firstChild.tagName).toLowerCase() == 'img' ? hd.firstChild : null;
15843                 if(img){
15844                     Ext.fly(img).replaceClass(old, this.iconCls);
15845                 }else{
15846                     Ext.DomHelper.insertBefore(hd.firstChild, {
15847                         tag:'img', src: Ext.BLANK_IMAGE_URL, cls:'x-panel-inline-icon '+this.iconCls
15848                     });
15849                  }
15850             }
15851         }
15852     },
15853
15854         makeFloating : function(cfg){
15855         this.floating = true;
15856         this.el = new Ext.Layer(
15857             typeof cfg == 'object' ? cfg : {
15858                 shadow: this.shadow !== undefined ? this.shadow : 'sides',
15859                 shadowOffset: this.shadowOffset,
15860                 constrain:false,
15861                 shim: this.shim === false ? false : undefined
15862             }, this.el
15863         );
15864     },
15865
15866     
15867     getTopToolbar : function(){
15868         return this.topToolbar;
15869     },
15870
15871     
15872     getBottomToolbar : function(){
15873         return this.bottomToolbar;
15874     },
15875
15876     
15877     addButton : function(config, handler, scope){
15878         var bc = {
15879             handler: handler,
15880             scope: scope,
15881             minWidth: this.minButtonWidth,
15882             hideParent:true
15883         };
15884         if(typeof config == "string"){
15885             bc.text = config;
15886         }else{
15887             Ext.apply(bc, config);
15888         }
15889         var btn = new Ext.Button(bc);
15890         btn.ownerCt = this;
15891         if(!this.buttons){
15892             this.buttons = [];
15893         }
15894         this.buttons.push(btn);
15895         return btn;
15896     },
15897
15898         addTool : function(){
15899         if(!this[this.toolTarget]) {             return;
15900         }
15901         if(!this.toolTemplate){
15902                         var tt = new Ext.Template(
15903                  '<div class="x-tool x-tool-{id}">&#160;</div>'
15904             );
15905             tt.disableFormats = true;
15906             tt.compile();
15907             Ext.Panel.prototype.toolTemplate = tt;
15908         }
15909         for(var i = 0, a = arguments, len = a.length; i < len; i++) {
15910             var tc = a[i], overCls = 'x-tool-'+tc.id+'-over';
15911             var t = this.toolTemplate.insertFirst(this[this.toolTarget], tc, true);
15912             this.tools[tc.id] = t;
15913             t.enableDisplayMode('block');
15914             t.on('click', this.createToolHandler(t, tc, overCls, this));
15915             if(tc.on){
15916                 t.on(tc.on);
15917             }
15918             if(tc.hidden){
15919                 t.hide();
15920             }
15921             if(tc.qtip){
15922                 if(typeof tc.qtip == 'object'){
15923                     Ext.QuickTips.register(Ext.apply({
15924                           target: t.id
15925                     }, tc.qtip));
15926                 } else {
15927                     t.dom.qtip = tc.qtip;
15928                 }
15929             }
15930             t.addClassOnOver(overCls);
15931         }
15932     },
15933
15934         onShow : function(){
15935         if(this.floating){
15936             return this.el.show();
15937         }
15938         Ext.Panel.superclass.onShow.call(this);
15939     },
15940
15941         onHide : function(){
15942         if(this.floating){
15943             return this.el.hide();
15944         }
15945         Ext.Panel.superclass.onHide.call(this);
15946     },
15947
15948         createToolHandler : function(t, tc, overCls, panel){
15949         return function(e){
15950             t.removeClass(overCls);
15951             e.stopEvent();
15952             if(tc.handler){
15953                 tc.handler.call(tc.scope || t, e, t, panel);
15954             }
15955         };
15956     },
15957
15958         afterRender : function(){
15959         if(this.fromMarkup && this.height === undefined && !this.autoHeight){
15960             this.height = this.el.getHeight();
15961         }
15962         if(this.floating && !this.hidden && !this.initHidden){
15963             this.el.show();
15964         }
15965         if(this.title){
15966             this.setTitle(this.title);
15967         }
15968                 this.setAutoScroll();
15969         if(this.html){
15970             this.body.update(typeof this.html == 'object' ?
15971                              Ext.DomHelper.markup(this.html) :
15972                              this.html);
15973             delete this.html;
15974         }
15975         if(this.contentEl){
15976             var ce = Ext.getDom(this.contentEl);
15977             Ext.fly(ce).removeClass(['x-hidden', 'x-hide-display']);
15978             this.body.dom.appendChild(ce);
15979         }
15980         if(this.collapsed){
15981             this.collapsed = false;
15982             this.collapse(false);
15983         }
15984         Ext.Panel.superclass.afterRender.call(this);         this.initEvents();
15985     },
15986     
15987         setAutoScroll : function(){
15988         if(this.rendered && this.autoScroll){
15989                         this.body.setOverflow('auto');
15990         }
15991     },
15992
15993         getKeyMap : function(){
15994         if(!this.keyMap){
15995             this.keyMap = new Ext.KeyMap(this.el, this.keys);
15996         }
15997         return this.keyMap;
15998     },
15999
16000         initEvents : function(){
16001         if(this.keys){
16002             this.getKeyMap();
16003         }
16004         if(this.draggable){
16005             this.initDraggable();
16006         }
16007     },
16008
16009         initDraggable : function(){
16010         this.dd = new Ext.Panel.DD(this, typeof this.draggable == 'boolean' ? null : this.draggable);
16011     },
16012
16013         beforeEffect : function(){
16014         if(this.floating){
16015             this.el.beforeAction();
16016         }
16017         this.el.addClass('x-panel-animated');
16018     },
16019
16020         afterEffect : function(){
16021         this.syncShadow();
16022         this.el.removeClass('x-panel-animated');
16023     },
16024
16025         createEffect : function(a, cb, scope){
16026         var o = {
16027             scope:scope,
16028             block:true
16029         };
16030         if(a === true){
16031             o.callback = cb;
16032             return o;
16033         }else if(!a.callback){
16034             o.callback = cb;
16035         }else {             o.callback = function(){
16036                 cb.call(scope);
16037                 Ext.callback(a.callback, a.scope);
16038             };
16039         }
16040         return Ext.applyIf(o, a);
16041     },
16042
16043     
16044     collapse : function(animate){
16045         if(this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforecollapse', this, animate) === false){
16046             return;
16047         }
16048         var doAnim = animate === true || (animate !== false && this.animCollapse);
16049         this.beforeEffect();
16050         this.onCollapse(doAnim, animate);
16051         return this;
16052     },
16053
16054         onCollapse : function(doAnim, animArg){
16055         if(doAnim){
16056             this[this.collapseEl].slideOut(this.slideAnchor,
16057                     Ext.apply(this.createEffect(animArg||true, this.afterCollapse, this),
16058                         this.collapseDefaults));
16059         }else{
16060             this[this.collapseEl].hide();
16061             this.afterCollapse();
16062         }
16063     },
16064
16065         afterCollapse : function(){
16066         this.collapsed = true;
16067         this.el.addClass(this.collapsedCls);
16068         this.afterEffect();
16069         this.fireEvent('collapse', this);
16070     },
16071
16072     
16073     expand : function(animate){
16074         if(!this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforeexpand', this, animate) === false){
16075             return;
16076         }
16077         var doAnim = animate === true || (animate !== false && this.animCollapse);
16078         this.el.removeClass(this.collapsedCls);
16079         this.beforeEffect();
16080         this.onExpand(doAnim, animate);
16081         return this;
16082     },
16083
16084         onExpand : function(doAnim, animArg){
16085         if(doAnim){
16086             this[this.collapseEl].slideIn(this.slideAnchor,
16087                     Ext.apply(this.createEffect(animArg||true, this.afterExpand, this),
16088                         this.expandDefaults));
16089         }else{
16090             this[this.collapseEl].show();
16091             this.afterExpand();
16092         }
16093     },
16094
16095         afterExpand : function(){
16096         this.collapsed = false;
16097         this.afterEffect();
16098         this.fireEvent('expand', this);
16099     },
16100
16101     
16102     toggleCollapse : function(animate){
16103         this[this.collapsed ? 'expand' : 'collapse'](animate);
16104         return this;
16105     },
16106
16107         onDisable : function(){
16108         if(this.rendered && this.maskDisabled){
16109             this.el.mask();
16110         }
16111         Ext.Panel.superclass.onDisable.call(this);
16112     },
16113
16114         onEnable : function(){
16115         if(this.rendered && this.maskDisabled){
16116             this.el.unmask();
16117         }
16118         Ext.Panel.superclass.onEnable.call(this);
16119     },
16120
16121         onResize : function(w, h){
16122         if(w !== undefined || h !== undefined){
16123             if(!this.collapsed){
16124                 if(typeof w == 'number'){
16125                     this.body.setWidth(
16126                             this.adjustBodyWidth(w - this.getFrameWidth()));
16127                 }else if(w == 'auto'){
16128                     this.body.setWidth(w);
16129                 }
16130
16131                 if(typeof h == 'number'){
16132                     this.body.setHeight(
16133                             this.adjustBodyHeight(h - this.getFrameHeight()));
16134                 }else if(h == 'auto'){
16135                     this.body.setHeight(h);
16136                 }
16137             }else{
16138                 this.queuedBodySize = {width: w, height: h};
16139                 if(!this.queuedExpand && this.allowQueuedExpand !== false){
16140                     this.queuedExpand = true;
16141                     this.on('expand', function(){
16142                         delete this.queuedExpand;
16143                         this.onResize(this.queuedBodySize.width, this.queuedBodySize.height);
16144                         this.doLayout();
16145                     }, this, {single:true});
16146                 }
16147             }
16148             this.fireEvent('bodyresize', this, w, h);
16149         }
16150         this.syncShadow();
16151     },
16152
16153         adjustBodyHeight : function(h){
16154         return h;
16155     },
16156
16157         adjustBodyWidth : function(w){
16158         return w;
16159     },
16160
16161         onPosition : function(){
16162         this.syncShadow();
16163     },
16164
16165         onDestroy : function(){
16166         if(this.tools){
16167             for(var k in this.tools){
16168                 Ext.destroy(this.tools[k]);
16169             }
16170         }
16171         if(this.buttons){
16172             for(var b in this.buttons){
16173                 Ext.destroy(this.buttons[b]);
16174             }
16175         }
16176         Ext.destroy(
16177             this.topToolbar,
16178             this.bottomToolbar
16179         );
16180         Ext.Panel.superclass.onDestroy.call(this);
16181     },
16182
16183     
16184     getFrameWidth : function(){
16185         var w = this.el.getFrameWidth('lr');
16186
16187         if(this.frame){
16188             var l = this.bwrap.dom.firstChild;
16189             w += (Ext.fly(l).getFrameWidth('l') + Ext.fly(l.firstChild).getFrameWidth('r'));
16190             var mc = this.bwrap.dom.firstChild.firstChild.firstChild;
16191             w += Ext.fly(mc).getFrameWidth('lr');
16192         }
16193         return w;
16194     },
16195
16196     
16197     getFrameHeight : function(){
16198         var h  = this.el.getFrameWidth('tb');
16199         h += (this.tbar ? this.tbar.getHeight() : 0) +
16200              (this.bbar ? this.bbar.getHeight() : 0);
16201
16202         if(this.frame){
16203             var hd = this.el.dom.firstChild;
16204             var ft = this.bwrap.dom.lastChild;
16205             h += (hd.offsetHeight + ft.offsetHeight);
16206             var mc = this.bwrap.dom.firstChild.firstChild.firstChild;
16207             h += Ext.fly(mc).getFrameWidth('tb');
16208         }else{
16209             h += (this.header ? this.header.getHeight() : 0) +
16210                 (this.footer ? this.footer.getHeight() : 0);
16211         }
16212         return h;
16213     },
16214
16215     
16216     getInnerWidth : function(){
16217         return this.getSize().width - this.getFrameWidth();
16218     },
16219
16220     
16221     getInnerHeight : function(){
16222         return this.getSize().height - this.getFrameHeight();
16223     },
16224
16225         syncShadow : function(){
16226         if(this.floating){
16227             this.el.sync(true);
16228         }
16229     },
16230
16231         getLayoutTarget : function(){
16232         return this.body;
16233     },
16234
16235     
16236     setTitle : function(title, iconCls){
16237         this.title = title;
16238         if(this.header && this.headerAsText){
16239             this.header.child('span').update(title);
16240         }
16241         if(iconCls){
16242             this.setIconClass(iconCls);
16243         }
16244         this.fireEvent('titlechange', this, title);
16245         return this;
16246     },
16247
16248     
16249     getUpdater : function(){
16250         return this.body.getUpdater();
16251     },
16252
16253      
16254     load : function(){
16255         var um = this.body.getUpdater();
16256         um.update.apply(um, arguments);
16257         return this;
16258     },
16259
16260         beforeDestroy : function(){
16261         Ext.Element.uncache(
16262             this.header,
16263             this.tbar,
16264             this.bbar,
16265             this.footer,
16266             this.body
16267         );
16268     },
16269
16270         createClasses : function(){
16271         this.headerCls = this.baseCls + '-header';
16272         this.headerTextCls = this.baseCls + '-header-text';
16273         this.bwrapCls = this.baseCls + '-bwrap';
16274         this.tbarCls = this.baseCls + '-tbar';
16275         this.bodyCls = this.baseCls + '-body';
16276         this.bbarCls = this.baseCls + '-bbar';
16277         this.footerCls = this.baseCls + '-footer';
16278     },
16279
16280         createGhost : function(cls, useShim, appendTo){
16281         var el = document.createElement('div');
16282         el.className = 'x-panel-ghost ' + (cls ? cls : '');
16283         if(this.header){
16284             el.appendChild(this.el.dom.firstChild.cloneNode(true));
16285         }
16286         Ext.fly(el.appendChild(document.createElement('ul'))).setHeight(this.bwrap.getHeight());
16287         el.style.width = this.el.dom.offsetWidth + 'px';;
16288         if(!appendTo){
16289             this.container.dom.appendChild(el);
16290         }else{
16291             Ext.getDom(appendTo).appendChild(el);
16292         }
16293         if(useShim !== false && this.el.useShim !== false){
16294             var layer = new Ext.Layer({shadow:false, useDisplay:true, constrain:false}, el);
16295             layer.show();
16296             return layer;
16297         }else{
16298             return new Ext.Element(el);
16299         }
16300     },
16301
16302         doAutoLoad : function(){
16303         this.body.load(
16304             typeof this.autoLoad == 'object' ?
16305                 this.autoLoad : {url: this.autoLoad});
16306     }
16307
16308
16309 });
16310 Ext.reg('panel', Ext.Panel);
16311
16312
16313 Ext.Window = Ext.extend(Ext.Panel, {
16314     
16315     
16316     
16317     
16318     
16319     
16320     
16321     baseCls : 'x-window',
16322     
16323     resizable:true,
16324     
16325     draggable:true,
16326     
16327     closable : true,
16328     
16329     constrain:false,
16330     
16331     constrainHeader:false,
16332     
16333     plain:false,
16334     
16335     minimizable : false,
16336     
16337     maximizable : false,
16338     
16339     minHeight: 100,
16340     
16341     minWidth: 200,
16342     
16343     expandOnShow: true,
16344     
16345     closeAction: 'close',
16346
16347         collapsible:false,
16348
16349         initHidden : true,
16350     
16351     monitorResize : true,
16352
16353                     
16354     elements: 'header,body',
16355     
16356     frame:true,
16357     
16358     floating:true,
16359
16360         initComponent : function(){
16361         Ext.Window.superclass.initComponent.call(this);
16362         this.addEvents(
16363             
16364             
16365             
16366             'resize',
16367             
16368             'maximize',
16369             
16370             'minimize',
16371             
16372             'restore'
16373         );
16374     },
16375
16376         getState : function(){
16377         return Ext.apply(Ext.Window.superclass.getState.call(this) || {}, this.getBox());
16378     },
16379
16380         onRender : function(ct, position){
16381         Ext.Window.superclass.onRender.call(this, ct, position);
16382
16383         if(this.plain){
16384             this.el.addClass('x-window-plain');
16385         }
16386
16387                 this.focusEl = this.el.createChild({
16388                     tag: "a", href:"#", cls:"x-dlg-focus",
16389                     tabIndex:"-1", html: "&#160;"});
16390         this.focusEl.swallowEvent('click', true);
16391
16392         this.proxy = this.el.createProxy("x-window-proxy");
16393         this.proxy.enableDisplayMode('block');
16394
16395         if(this.modal){
16396             this.mask = this.container.createChild({cls:"ext-el-mask"}, this.el.dom);
16397             this.mask.enableDisplayMode("block");
16398             this.mask.hide();
16399         }
16400     },
16401
16402         initEvents : function(){
16403         Ext.Window.superclass.initEvents.call(this);
16404         if(this.animateTarget){
16405             this.setAnimateTarget(this.animateTarget);
16406         }
16407
16408         if(this.resizable){
16409             this.resizer = new Ext.Resizable(this.el, {
16410                 minWidth: this.minWidth,
16411                 minHeight:this.minHeight,
16412                 handles: this.resizeHandles || "all",
16413                 pinned: true,
16414                 resizeElement : this.resizerAction
16415             });
16416             this.resizer.window = this;
16417             this.resizer.on("beforeresize", this.beforeResize, this);
16418         }
16419
16420         if(this.draggable){
16421             this.header.addClass("x-window-draggable");
16422         }
16423         this.initTools();
16424
16425         this.el.on("mousedown", this.toFront, this);
16426         this.manager = this.manager || Ext.WindowMgr;
16427         this.manager.register(this);
16428         this.hidden = true;
16429         if(this.maximized){
16430             this.maximized = false;
16431             this.maximize();
16432         }
16433         if(this.closable){
16434             var km = this.getKeyMap();
16435             km.on(27, this.onEsc, this);
16436             km.disable();
16437         }
16438     },
16439
16440     initDraggable : function(){
16441         this.dd = new Ext.Window.DD(this);  
16442     },
16443
16444        onEsc : function(){
16445         this[this.closeAction]();  
16446     },
16447
16448         beforeDestroy : function(){
16449         Ext.destroy(
16450             this.resizer,
16451             this.dd,
16452             this.proxy,
16453             this.mask
16454         );
16455         Ext.Window.superclass.beforeDestroy.call(this);
16456     },
16457     
16458         onDestroy : function(){
16459         if(this.manager){
16460             this.manager.unregister(this);
16461         }
16462         Ext.Window.superclass.onDestroy.call(this);
16463     },
16464
16465         initTools : function(){
16466         if(this.minimizable){
16467             this.addTool({
16468                 id: 'minimize',
16469                 handler: this.minimize.createDelegate(this, [])
16470             });
16471         }
16472         if(this.maximizable){
16473             this.addTool({
16474                 id: 'maximize',
16475                 handler: this.maximize.createDelegate(this, [])
16476             });
16477             this.addTool({
16478                 id: 'restore',
16479                 handler: this.restore.createDelegate(this, []),
16480                 hidden:true
16481             });
16482             this.header.on('dblclick', this.toggleMaximize, this);
16483         }
16484         if(this.closable){
16485             this.addTool({
16486                 id: 'close',
16487                 handler: this[this.closeAction].createDelegate(this, [])
16488             });
16489         }
16490     },
16491
16492         resizerAction : function(){
16493         var box = this.proxy.getBox();
16494         this.proxy.hide();
16495         this.window.handleResize(box);
16496         return box;
16497     },
16498
16499         beforeResize : function(){
16500         this.resizer.minHeight = Math.max(this.minHeight, this.getFrameHeight() + 40);         this.resizer.minWidth = Math.max(this.minWidth, this.getFrameWidth() + 40);
16501         this.resizeBox = this.el.getBox();
16502     },
16503
16504         updateHandles : function(){
16505         if(Ext.isIE && this.resizer){
16506             this.resizer.syncHandleHeight();
16507             this.el.repaint();
16508         }
16509     },
16510
16511         handleResize : function(box){
16512         var rz = this.resizeBox;
16513         if(rz.x != box.x || rz.y != box.y){
16514             this.updateBox(box);
16515         }else{
16516             this.setSize(box);
16517         }
16518         this.focus();
16519         this.updateHandles();
16520         this.saveState();
16521         this.fireEvent("resize", this, box.width, box.height);
16522     },
16523
16524     
16525     focus : function(){
16526         var f = this.focusEl, db = this.defaultButton, t = typeof db;
16527         if(t != 'undefined'){
16528             if(t == 'number'){
16529                 f = this.buttons[db];
16530             }else if(t == 'string'){
16531                 f = Ext.getCmp(db);
16532             }else{
16533                 f = db;
16534             }
16535         }
16536         f.focus.defer(10, f);
16537     },
16538
16539     
16540     setAnimateTarget : function(el){
16541         el = Ext.get(el);
16542         this.animateTarget = el;
16543     },
16544
16545         beforeShow : function(){
16546         delete this.el.lastXY;
16547         delete this.el.lastLT;
16548         if(this.x === undefined || this.y === undefined){
16549             var xy = this.el.getAlignToXY(this.container, 'c-c');
16550             var pos = this.el.translatePoints(xy[0], xy[1]);
16551             this.x = this.x === undefined? pos.left : this.x;
16552             this.y = this.y === undefined? pos.top : this.y;
16553         }
16554         this.el.setLeftTop(this.x, this.y);
16555
16556         if(this.expandOnShow){
16557             this.expand(false);
16558         }
16559
16560         if(this.modal){
16561             Ext.getBody().addClass("x-body-masked");
16562             this.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
16563             this.mask.show();
16564         }
16565     },
16566
16567     
16568     show : function(animateTarget, cb, scope){
16569         if(!this.rendered){
16570             this.render(Ext.getBody());
16571         }
16572         if(this.hidden === false){
16573             this.toFront();
16574             return;
16575         }
16576         if(this.fireEvent("beforeshow", this) === false){
16577             return;
16578         }
16579         if(cb){
16580             this.on('show', cb, scope, {single:true});
16581         }
16582         this.hidden = false;
16583         if(animateTarget !== undefined){
16584             this.setAnimateTarget(animateTarget);
16585         }
16586         this.beforeShow();
16587         if(this.animateTarget){
16588             this.animShow();
16589         }else{
16590             this.afterShow();
16591         }
16592     },
16593
16594         afterShow : function(){
16595         this.proxy.hide();
16596         this.el.setStyle('display', 'block');
16597         this.el.show();
16598         if(this.maximized){
16599             this.fitContainer();
16600         }
16601         if(Ext.isMac && Ext.isGecko){           this.cascade(this.setAutoScroll);
16602         }
16603
16604         if(this.monitorResize || this.modal || this.constrain || this.constrainHeader){
16605             Ext.EventManager.onWindowResize(this.onWindowResize, this);
16606         }
16607         this.doConstrain();
16608         if(this.layout){
16609             this.doLayout();
16610         }
16611         if(this.keyMap){
16612             this.keyMap.enable();
16613         }
16614         this.toFront();
16615         this.updateHandles();
16616         this.fireEvent("show", this);
16617     },
16618
16619         animShow : function(){
16620         this.proxy.show();
16621         this.proxy.setBox(this.animateTarget.getBox());
16622         this.proxy.setOpacity(0);
16623         var b = this.getBox(false);
16624         b.callback = this.afterShow;
16625         b.scope = this;
16626         b.duration = .25;
16627         b.easing = 'easeNone';
16628         b.opacity = .5;
16629         b.block = true;
16630         this.el.setStyle('display', 'none');
16631         this.proxy.shift(b);
16632     },
16633
16634     
16635     hide : function(animateTarget, cb, scope){
16636         if(this.hidden || this.fireEvent("beforehide", this) === false){
16637             return;
16638         }
16639         if(cb){
16640             this.on('hide', cb, scope, {single:true});
16641         }
16642         this.hidden = true;
16643         if(animateTarget !== undefined){
16644             this.setAnimateTarget(animateTarget);
16645         }
16646         if(this.animateTarget){
16647             this.animHide();
16648         }else{
16649             this.el.hide();
16650             this.afterHide();
16651         }
16652     },
16653
16654         afterHide : function(){
16655         this.proxy.hide();
16656         if(this.monitorResize || this.modal || this.constrain || this.constrainHeader){
16657             Ext.EventManager.removeResizeListener(this.onWindowResize, this);
16658         }
16659         if(this.modal){
16660             this.mask.hide();
16661             Ext.getBody().removeClass("x-body-masked");
16662         }
16663         if(this.keyMap){
16664             this.keyMap.disable();
16665         }
16666         this.fireEvent("hide", this);
16667     },
16668
16669         animHide : function(){
16670         this.proxy.setOpacity(.5);
16671         this.proxy.show();
16672         var tb = this.getBox(false);
16673         this.proxy.setBox(tb);
16674         this.el.hide();
16675         var b = this.animateTarget.getBox();
16676         b.callback = this.afterHide;
16677         b.scope = this;
16678         b.duration = .25;
16679         b.easing = 'easeNone';
16680         b.block = true;
16681         b.opacity = 0;
16682         this.proxy.shift(b);
16683     },
16684
16685         onWindowResize : function(){
16686         if(this.maximized){
16687             this.fitContainer();
16688         }
16689         if(this.modal){
16690             this.mask.setSize('100%', '100%');
16691             var force = this.mask.dom.offsetHeight;
16692             this.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
16693         }
16694         this.doConstrain();
16695     },
16696
16697         doConstrain : function(){
16698         if(this.constrain || this.constrainHeader){
16699             var offsets;
16700             if(this.constrain){
16701                 offsets = {
16702                     right:this.el.shadowOffset,
16703                     left:this.el.shadowOffset,
16704                     bottom:this.el.shadowOffset
16705                 };
16706             }else {
16707                 var s = this.getSize();
16708                 offsets = {
16709                     right:-(s.width - 100),
16710                     bottom:-(s.height - 25)
16711                 };
16712             }
16713
16714             var xy = this.el.getConstrainToXY(this.container, true, offsets);
16715             if(xy){
16716                 this.setPosition(xy[0], xy[1]);
16717             }
16718         }
16719     },
16720
16721         ghost : function(cls){
16722         var ghost = this.createGhost(cls);
16723         var box = this.getBox(true);
16724         ghost.setLeftTop(box.x, box.y);
16725         ghost.setWidth(box.width);
16726         this.el.hide();
16727         this.activeGhost = ghost;
16728         return ghost;
16729     },
16730
16731         unghost : function(show, matchPosition){
16732         if(show !== false){
16733             this.el.show();
16734             this.focus();
16735                 if(Ext.isMac && Ext.isGecko){                   this.cascade(this.setAutoScroll);
16736                 }
16737         }
16738         if(matchPosition !== false){
16739             this.setPosition(this.activeGhost.getLeft(true), this.activeGhost.getTop(true));
16740         }
16741         this.activeGhost.hide();
16742         this.activeGhost.remove();
16743         delete this.activeGhost;
16744     },
16745
16746     
16747     minimize : function(){
16748         this.fireEvent('minimize', this);
16749     },
16750
16751     
16752     close : function(){
16753         if(this.fireEvent("beforeclose", this) !== false){
16754             this.hide(null, function(){
16755                 this.fireEvent('close', this);
16756                 this.destroy();
16757             }, this);
16758         }
16759     },
16760
16761     
16762     maximize : function(){
16763         if(!this.maximized){
16764             this.expand(false);
16765             this.restoreSize = this.getSize();
16766             this.restorePos = this.getPosition(true);
16767             this.tools.maximize.hide();
16768             this.tools.restore.show();
16769             this.maximized = true;
16770             this.el.disableShadow();
16771
16772             if(this.dd){
16773                 this.dd.lock();
16774             }
16775             if(this.collapsible){
16776                 this.tools.toggle.hide();
16777             }
16778             this.el.addClass('x-window-maximized');
16779             this.container.addClass('x-window-maximized-ct');
16780
16781             this.setPosition(0, 0);
16782             this.fitContainer();
16783             this.fireEvent('maximize', this);
16784         }
16785     },
16786
16787     
16788     restore : function(){
16789         if(this.maximized){
16790             this.el.removeClass('x-window-maximized');
16791             this.tools.restore.hide();
16792             this.tools.maximize.show();
16793             this.setPosition(this.restorePos[0], this.restorePos[1]);
16794             this.setSize(this.restoreSize.width, this.restoreSize.height);
16795             delete this.restorePos;
16796             delete this.restoreSize;
16797             this.maximized = false;
16798             this.el.enableShadow(true);
16799
16800             if(this.dd){
16801                 this.dd.unlock();
16802             }
16803             if(this.collapsible){
16804                 this.tools.toggle.show();
16805             }
16806             this.container.removeClass('x-window-maximized-ct');
16807
16808             this.doConstrain();
16809             this.fireEvent('restore', this);
16810         }
16811     },
16812
16813     
16814     toggleMaximize : function(){
16815         this[this.maximized ? 'restore' : 'maximize']();
16816     },
16817
16818         fitContainer : function(){
16819         var vs = this.container.getViewSize();
16820         this.setSize(vs.width, vs.height);
16821     },
16822
16823             setZIndex : function(index){
16824         if(this.modal){
16825             this.mask.setStyle("z-index", index);
16826         }
16827         this.el.setZIndex(++index);
16828         index += 5;
16829
16830         if(this.resizer){
16831             this.resizer.proxy.setStyle("z-index", ++index);
16832         }
16833
16834         this.lastZIndex = index;
16835     },
16836
16837     
16838     alignTo : function(element, position, offsets){
16839         var xy = this.el.getAlignToXY(element, position, offsets);
16840         this.setPagePosition(xy[0], xy[1]);
16841         return this;
16842     },
16843
16844     
16845     anchorTo : function(el, alignment, offsets, monitorScroll, _pname){
16846         var action = function(){
16847             this.alignTo(el, alignment, offsets);
16848         };
16849         Ext.EventManager.onWindowResize(action, this);
16850         var tm = typeof monitorScroll;
16851         if(tm != 'undefined'){
16852             Ext.EventManager.on(window, 'scroll', action, this,
16853                 {buffer: tm == 'number' ? monitorScroll : 50});
16854         }
16855         action.call(this);
16856         this[_pname] = action;
16857         return this;
16858     },
16859
16860     
16861     toFront : function(){
16862         if(this.manager.bringToFront(this)){
16863             this.focus();
16864         }
16865         return this;
16866     },
16867
16868     
16869     setActive : function(active){
16870         if(active){
16871             if(!this.maximized){
16872                 this.el.enableShadow(true);
16873             }
16874             this.fireEvent('activate', this);
16875         }else{
16876             this.el.disableShadow();
16877             this.fireEvent('deactivate', this);
16878         }
16879     },
16880
16881     
16882     toBack : function(){
16883         this.manager.sendToBack(this);
16884         return this;
16885     },
16886
16887     
16888     center : function(){
16889         var xy = this.el.getAlignToXY(this.container, 'c-c');
16890         this.setPagePosition(xy[0], xy[1]);
16891         return this;
16892     }
16893 });
16894 Ext.reg('window', Ext.Window);
16895
16896 Ext.Window.DD = function(win){
16897     this.win = win;
16898     Ext.Window.DD.superclass.constructor.call(this, win.el.id, 'WindowDD-'+win.id);
16899     this.setHandleElId(win.header.id);
16900     this.scroll = false;
16901 };
16902
16903 Ext.extend(Ext.Window.DD, Ext.dd.DD, {
16904     moveOnly:true,
16905     headerOffsets:[100, 25],
16906     startDrag : function(){
16907         var w = this.win;
16908         this.proxy = w.ghost();
16909         if(w.constrain !== false){
16910             var so = w.el.shadowOffset;
16911             this.constrainTo(w.container, {right: so, left: so, bottom: so});
16912         }else if(w.constrainHeader !== false){
16913             var s = this.proxy.getSize();
16914             this.constrainTo(w.container, {right: -(s.width-this.headerOffsets[0]), bottom: -(s.height-this.headerOffsets[1])});
16915         }
16916     },
16917     b4Drag : Ext.emptyFn,
16918
16919     onDrag : function(e){
16920         this.alignElWithMouse(this.proxy, e.getPageX(), e.getPageY());
16921     },
16922
16923     endDrag : function(e){
16924         this.win.unghost();
16925         this.win.saveState();
16926     }
16927 });
16928
16929 Ext.WindowGroup = function(){
16930     var list = {};
16931     var accessList = [];
16932     var front = null;
16933
16934         var sortWindows = function(d1, d2){
16935         return (!d1._lastAccess || d1._lastAccess < d2._lastAccess) ? -1 : 1;
16936     };
16937
16938         var orderWindows = function(){
16939         var a = accessList, len = a.length;
16940         if(len > 0){
16941             a.sort(sortWindows);
16942             var seed = a[0].manager.zseed;
16943             for(var i = 0; i < len; i++){
16944                 var win = a[i];
16945                 if(win && !win.hidden){
16946                     win.setZIndex(seed + (i*10));
16947                 }
16948             }
16949         }
16950         activateLast();
16951     };
16952
16953         var setActiveWin = function(win){
16954         if(win != front){
16955             if(front){
16956                 front.setActive(false);
16957             }
16958             front = win;
16959             if(win){
16960                 win.setActive(true);
16961             }
16962         }
16963     };
16964
16965         var activateLast = function(){
16966         for(var i = accessList.length-1; i >=0; --i) {
16967             if(!accessList[i].hidden){
16968                 setActiveWin(accessList[i]);
16969                 return;
16970             }
16971         }
16972                 setActiveWin(null);
16973     };
16974
16975     return {
16976         
16977         zseed : 9000,
16978
16979                 register : function(win){
16980             list[win.id] = win;
16981             accessList.push(win);
16982             win.on('hide', activateLast);
16983         },
16984
16985                 unregister : function(win){
16986             delete list[win.id];
16987             win.un('hide', activateLast);
16988             accessList.remove(win);
16989         },
16990
16991         
16992         get : function(id){
16993             return typeof id == "object" ? id : list[id];
16994         },
16995
16996         
16997         bringToFront : function(win){
16998             win = this.get(win);
16999             if(win != front){
17000                 win._lastAccess = new Date().getTime();
17001                 orderWindows();
17002                 return true;
17003             }
17004             return false;
17005         },
17006
17007         
17008         sendToBack : function(win){
17009             win = this.get(win);
17010             win._lastAccess = -(new Date().getTime());
17011             orderWindows();
17012             return win;
17013         },
17014
17015         
17016         hideAll : function(){
17017             for(var id in list){
17018                 if(list[id] && typeof list[id] != "function" && list[id].isVisible()){
17019                     list[id].hide();
17020                 }
17021             }
17022         },
17023
17024         
17025         getActive : function(){
17026             return front;
17027         },
17028
17029         
17030         getBy : function(fn, scope){
17031             var r = [];
17032             for(var i = accessList.length-1; i >=0; --i) {
17033                 var win = accessList[i];
17034                 if(fn.call(scope||win, win) !== false){
17035                     r.push(win);
17036                 }
17037             }
17038             return r;
17039         },
17040
17041         
17042         each : function(fn, scope){
17043             for(var id in list){
17044                 if(list[id] && typeof list[id] != "function"){
17045                     if(fn.call(scope || list[id], list[id]) === false){
17046                         return;
17047                     }
17048                 }
17049             }
17050         }
17051     };
17052 };
17053
17054
17055
17056 Ext.WindowMgr = new Ext.WindowGroup();
17057
17058 Ext.dd.PanelProxy = function(panel, config){
17059     this.panel = panel;
17060     this.id = this.panel.id +'-ddproxy';
17061     Ext.apply(this, config);
17062 };
17063
17064 Ext.dd.PanelProxy.prototype = {
17065     
17066     insertProxy : true,
17067
17068     
17069     setStatus : Ext.emptyFn,
17070     reset : Ext.emptyFn,
17071     update : Ext.emptyFn,
17072     stop : Ext.emptyFn,
17073     sync: Ext.emptyFn,
17074
17075     
17076     getEl : function(){
17077         return this.ghost;
17078     },
17079
17080     
17081     getGhost : function(){
17082         return this.ghost;
17083     },
17084
17085     
17086     getProxy : function(){
17087         return this.proxy;
17088     },
17089
17090     
17091     hide : function(){
17092         if(this.ghost){
17093             if(this.proxy){
17094                 this.proxy.remove();
17095                 delete this.proxy;
17096             }
17097             this.panel.el.dom.style.display = '';
17098             this.ghost.remove();
17099             delete this.ghost;
17100         }
17101     },
17102
17103     
17104     show : function(){
17105         if(!this.ghost){
17106             this.ghost = this.panel.createGhost(undefined, undefined, Ext.getBody());
17107             this.ghost.setXY(this.panel.el.getXY())
17108             if(this.insertProxy){
17109                 this.proxy = this.panel.el.insertSibling({cls:'x-panel-dd-spacer'});
17110                 this.proxy.setSize(this.panel.getSize());
17111             }
17112             this.panel.el.dom.style.display = 'none';
17113         }
17114     },
17115
17116     
17117     repair : function(xy, callback, scope){
17118         this.hide();
17119         if(typeof callback == "function"){
17120             callback.call(scope || this);
17121         }
17122     },
17123
17124     
17125     moveProxy : function(parentNode, before){
17126         if(this.proxy){
17127             parentNode.insertBefore(this.proxy.dom, before);
17128         }
17129     }
17130 };
17131
17132
17133 Ext.Panel.DD = function(panel, cfg){
17134     this.panel = panel;
17135     this.dragData = {panel: panel};
17136     this.proxy = new Ext.dd.PanelProxy(panel, cfg);
17137     Ext.Panel.DD.superclass.constructor.call(this, panel.el, cfg);
17138     this.setHandleElId(panel.header.id);
17139     panel.header.setStyle('cursor', 'move');
17140     this.scroll = false;
17141 };
17142
17143 Ext.extend(Ext.Panel.DD, Ext.dd.DragSource, {
17144     showFrame: Ext.emptyFn,
17145     startDrag: Ext.emptyFn,
17146     b4StartDrag: function(x, y) {
17147         this.proxy.show();
17148     },
17149     b4MouseDown: function(e) {
17150         var x = e.getPageX();
17151         var y = e.getPageY();
17152         this.autoOffset(x, y);
17153     },
17154     onInitDrag : function(x, y){
17155         this.onStartDrag(x, y);
17156         return true;
17157     },
17158     createFrame : Ext.emptyFn,
17159     getDragEl : function(e){
17160         return this.proxy.ghost.dom;
17161     },
17162     endDrag : function(e){
17163         this.proxy.hide();
17164         this.panel.saveState();
17165     },
17166
17167     autoOffset : function(x, y) {
17168         x -= this.startPageX;
17169         y -= this.startPageY;
17170         this.setDelta(x, y);
17171     }
17172 });
17173
17174 Ext.state.Provider = function(){
17175     
17176     this.addEvents("statechange");
17177     this.state = {};
17178     Ext.state.Provider.superclass.constructor.call(this);
17179 };
17180 Ext.extend(Ext.state.Provider, Ext.util.Observable, {
17181     
17182     get : function(name, defaultValue){
17183         return typeof this.state[name] == "undefined" ?
17184             defaultValue : this.state[name];
17185     },
17186     
17187     
17188     clear : function(name){
17189         delete this.state[name];
17190         this.fireEvent("statechange", this, name, null);
17191     },
17192     
17193     
17194     set : function(name, value){
17195         this.state[name] = value;
17196         
17197         this.fireEvent("statechange", this, name, value);
17198     },
17199     
17200     
17201     decodeValue : function(cookie){
17202         var re = /^(a|n|d|b|s|o)\:(.*)$/;
17203         var matches = re.exec(unescape(cookie));
17204         if(!matches || !matches[1]) return; 
17205         var type = matches[1];
17206         var v = matches[2];
17207         switch(type){
17208             case "n":
17209                 return parseFloat(v);
17210             case "d":
17211                 return new Date(Date.parse(v));
17212             case "b":
17213                 return (v == "1");
17214             case "a":
17215                 var all = [];
17216                 var values = v.split("^");
17217                 for(var i = 0, len = values.length; i < len; i++){
17218                     all.push(this.decodeValue(values[i]));
17219                 }
17220                 return all;
17221            case "o":
17222                 var all = {};
17223                 var values = v.split("^");
17224                 for(var i = 0, len = values.length; i < len; i++){
17225                     var kv = values[i].split("=");
17226                     all[kv[0]] = this.decodeValue(kv[1]);
17227                 }
17228                 return all;
17229            default:
17230                 return v;
17231         }
17232     },
17233     
17234     
17235     encodeValue : function(v){
17236         var enc;
17237         if(typeof v == "number"){
17238             enc = "n:" + v;
17239         }else if(typeof v == "boolean"){
17240             enc = "b:" + (v ? "1" : "0");
17241         }else if(Ext.isDate(v)){
17242             enc = "d:" + v.toGMTString();
17243         }else if(Ext.isArray(v)){
17244             var flat = "";
17245             for(var i = 0, len = v.length; i < len; i++){
17246                 flat += this.encodeValue(v[i]);
17247                 if(i != len-1) flat += "^";
17248             }
17249             enc = "a:" + flat;
17250         }else if(typeof v == "object"){
17251             var flat = "";
17252             for(var key in v){
17253                 if(typeof v[key] != "function" && v[key] !== undefined){
17254                     flat += key + "=" + this.encodeValue(v[key]) + "^";
17255                 }
17256             }
17257             enc = "o:" + flat.substring(0, flat.length-1);
17258         }else{
17259             enc = "s:" + v;
17260         }
17261         return escape(enc);        
17262     }
17263 });
17264
17265
17266 Ext.state.Manager = function(){
17267     var provider = new Ext.state.Provider();
17268
17269     return {
17270         
17271         setProvider : function(stateProvider){
17272             provider = stateProvider;
17273         },
17274
17275         
17276         get : function(key, defaultValue){
17277             return provider.get(key, defaultValue);
17278         },
17279
17280         
17281          set : function(key, value){
17282             provider.set(key, value);
17283         },
17284
17285         
17286         clear : function(key){
17287             provider.clear(key);
17288         },
17289
17290         
17291         getProvider : function(){
17292             return provider;
17293         }
17294     };
17295 }();
17296
17297
17298 Ext.state.CookieProvider = function(config){
17299     Ext.state.CookieProvider.superclass.constructor.call(this);
17300     this.path = "/";
17301     this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); 
17302     this.domain = null;
17303     this.secure = false;
17304     Ext.apply(this, config);
17305     this.state = this.readCookies();
17306 };
17307
17308 Ext.extend(Ext.state.CookieProvider, Ext.state.Provider, {
17309     
17310     set : function(name, value){
17311         if(typeof value == "undefined" || value === null){
17312             this.clear(name);
17313             return;
17314         }
17315         this.setCookie(name, value);
17316         Ext.state.CookieProvider.superclass.set.call(this, name, value);
17317     },
17318
17319     
17320     clear : function(name){
17321         this.clearCookie(name);
17322         Ext.state.CookieProvider.superclass.clear.call(this, name);
17323     },
17324
17325     
17326     readCookies : function(){
17327         var cookies = {};
17328         var c = document.cookie + ";";
17329         var re = /\s?(.*?)=(.*?);/g;
17330         var matches;
17331         while((matches = re.exec(c)) != null){
17332             var name = matches[1];
17333             var value = matches[2];
17334             if(name && name.substring(0,3) == "ys-"){
17335                 cookies[name.substr(3)] = this.decodeValue(value);
17336             }
17337         }
17338         return cookies;
17339     },
17340
17341     
17342     setCookie : function(name, value){
17343         document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
17344            ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
17345            ((this.path == null) ? "" : ("; path=" + this.path)) +
17346            ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
17347            ((this.secure == true) ? "; secure" : "");
17348     },
17349
17350     
17351     clearCookie : function(name){
17352         document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
17353            ((this.path == null) ? "" : ("; path=" + this.path)) +
17354            ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
17355            ((this.secure == true) ? "; secure" : "");
17356     }
17357 });
17358
17359 Ext.DataView = Ext.extend(Ext.BoxComponent, {
17360     
17361     
17362     
17363     
17364     
17365     
17366     
17367     
17368     
17369     selectedClass : "x-view-selected",
17370     
17371     emptyText : "",
17372
17373     
17374     last: false,
17375
17376     
17377     initComponent : function(){
17378         Ext.DataView.superclass.initComponent.call(this);
17379         if(typeof this.tpl == "string"){
17380             this.tpl = new Ext.XTemplate(this.tpl);
17381         }
17382
17383         this.addEvents(
17384             
17385             "beforeclick",
17386             
17387             "click",
17388             
17389             "containerclick",
17390             
17391             "dblclick",
17392             
17393             "contextmenu",
17394             
17395             "selectionchange",
17396
17397             
17398             "beforeselect"
17399         );
17400
17401         this.all = new Ext.CompositeElementLite();
17402         this.selected = new Ext.CompositeElementLite();
17403     },
17404
17405     
17406     onRender : function(){
17407         if(!this.el){
17408             this.el = document.createElement('div');
17409         }
17410         Ext.DataView.superclass.onRender.apply(this, arguments);
17411     },
17412
17413     
17414     afterRender : function(){
17415         Ext.DataView.superclass.afterRender.call(this);
17416
17417         this.el.on({
17418             "click": this.onClick,
17419             "dblclick": this.onDblClick,
17420             "contextmenu": this.onContextMenu,
17421             scope:this
17422         });
17423
17424         if(this.overClass){
17425             this.el.on({
17426                 "mouseover": this.onMouseOver,
17427                 "mouseout": this.onMouseOut,
17428                 scope:this
17429             });
17430         }
17431
17432         if(this.store){
17433             this.setStore(this.store, true);
17434         }
17435     },
17436
17437     
17438     refresh : function(){
17439         this.clearSelections(false, true);
17440         this.el.update("");
17441         var html = [];
17442         var records = this.store.getRange();
17443         if(records.length < 1){
17444             this.el.update(this.emptyText);
17445             this.all.clear();
17446             return;
17447         }
17448         this.tpl.overwrite(this.el, this.collectData(records, 0));
17449         this.all.fill(Ext.query(this.itemSelector, this.el.dom));
17450         this.updateIndexes(0);
17451     },
17452
17453     
17454     prepareData : function(data){
17455         return data;
17456     },
17457
17458     
17459     collectData : function(records, startIndex){
17460         var r = [];
17461         for(var i = 0, len = records.length; i < len; i++){
17462             r[r.length] = this.prepareData(records[i].data, startIndex+i, records[i]);
17463         }
17464         return r;
17465     },
17466
17467     
17468     bufferRender : function(records){
17469         var div = document.createElement('div');
17470         this.tpl.overwrite(div, this.collectData(records));
17471         return Ext.query(this.itemSelector, div);
17472     },
17473
17474     
17475     onUpdate : function(ds, record){
17476         var index = this.store.indexOf(record);
17477         var sel = this.isSelected(index);
17478         var original = this.all.elements[index];
17479         var node = this.bufferRender([record], index)[0];
17480
17481         this.all.replaceElement(index, node, true);
17482         if(sel){
17483             this.selected.replaceElement(original, node);
17484             this.all.item(index).addClass(this.selectedClass);
17485         }
17486         this.updateIndexes(index, index);
17487     },
17488
17489     
17490     onAdd : function(ds, records, index){
17491         if(this.all.getCount() == 0){
17492             this.refresh();
17493             return;
17494         }
17495         var nodes = this.bufferRender(records, index), n;
17496         if(index < this.all.getCount()){
17497             n = this.all.item(index).insertSibling(nodes, 'before', true);
17498             this.all.elements.splice(index, 0, n);
17499         }else{
17500             n = this.all.last().insertSibling(nodes, 'after', true);
17501             this.all.elements.push(n);
17502         }
17503         this.updateIndexes(index);
17504     },
17505
17506     
17507     onRemove : function(ds, record, index){
17508         this.deselect(index);
17509         this.all.removeElement(index, true);
17510         this.updateIndexes(index);
17511     },
17512
17513     
17514     refreshNode : function(index){
17515         this.onUpdate(this.store, this.store.getAt(index));
17516     },
17517
17518     
17519     updateIndexes : function(startIndex, endIndex){
17520         var ns = this.all.elements;
17521         startIndex = startIndex || 0;
17522         endIndex = endIndex || ((endIndex === 0) ? 0 : (ns.length - 1));
17523         for(var i = startIndex; i <= endIndex; i++){
17524             ns[i].viewIndex = i;
17525         }
17526     },
17527
17528     
17529     setStore : function(store, initial){
17530         if(!initial && this.store){
17531             this.store.un("beforeload", this.onBeforeLoad, this);
17532             this.store.un("datachanged", this.refresh, this);
17533             this.store.un("add", this.onAdd, this);
17534             this.store.un("remove", this.onRemove, this);
17535             this.store.un("update", this.onUpdate, this);
17536             this.store.un("clear", this.refresh, this);
17537         }
17538         if(store){
17539             store = Ext.StoreMgr.lookup(store);
17540             store.on("beforeload", this.onBeforeLoad, this);
17541             store.on("datachanged", this.refresh, this);
17542             store.on("add", this.onAdd, this);
17543             store.on("remove", this.onRemove, this);
17544             store.on("update", this.onUpdate, this);
17545             store.on("clear", this.refresh, this);
17546         }
17547         this.store = store;
17548         if(store){
17549             this.refresh();
17550         }
17551     },
17552
17553     
17554     findItemFromChild : function(node){
17555         return Ext.fly(node).findParent(this.itemSelector, this.el);
17556     },
17557
17558     
17559     onClick : function(e){
17560         var item = e.getTarget(this.itemSelector, this.el);
17561         if(item){
17562             var index = this.indexOf(item);
17563             if(this.onItemClick(item, index, e) !== false){
17564                 this.fireEvent("click", this, index, item, e);
17565             }
17566         }else{
17567             if(this.fireEvent("containerclick", this, e) !== false){
17568                 this.clearSelections();
17569             }
17570         }
17571     },
17572
17573     
17574     onContextMenu : function(e){
17575         var item = e.getTarget(this.itemSelector, this.el);
17576         if(item){
17577             this.fireEvent("contextmenu", this, this.indexOf(item), item, e);
17578         }
17579     },
17580
17581     
17582     onDblClick : function(e){
17583         var item = e.getTarget(this.itemSelector, this.el);
17584         if(item){
17585             this.fireEvent("dblclick", this, this.indexOf(item), item, e);
17586         }
17587     },
17588
17589     
17590     onMouseOver : function(e){
17591         var item = e.getTarget(this.itemSelector, this.el);
17592         if(item && item !== this.lastItem){
17593             this.lastItem = item;
17594             Ext.fly(item).addClass(this.overClass);
17595         }
17596     },
17597
17598     
17599     onMouseOut : function(e){
17600         if(this.lastItem){
17601             if(!e.within(this.lastItem, true)){
17602                 Ext.fly(this.lastItem).removeClass(this.overClass);
17603                 delete this.lastItem;
17604             }
17605         }
17606     },
17607
17608     
17609     onItemClick : function(item, index, e){
17610         if(this.fireEvent("beforeclick", this, index, item, e) === false){
17611             return false;
17612         }
17613         if(this.multiSelect){
17614             this.doMultiSelection(item, index, e);
17615             e.preventDefault();
17616         }else if(this.singleSelect){
17617             this.doSingleSelection(item, index, e);
17618             e.preventDefault();
17619         }
17620         return true;
17621     },
17622
17623     
17624     doSingleSelection : function(item, index, e){
17625         if(e.ctrlKey && this.isSelected(index)){
17626             this.deselect(index);
17627         }else{
17628             this.select(index, false);
17629         }
17630     },
17631
17632     
17633     doMultiSelection : function(item, index, e){
17634         if(e.shiftKey && this.last !== false){
17635             var last = this.last;
17636             this.selectRange(last, index, e.ctrlKey);
17637             this.last = last; 
17638         }else{
17639             if((e.ctrlKey||this.simpleSelect) && this.isSelected(index)){
17640                 this.deselect(index);
17641             }else{
17642                 this.select(index, e.ctrlKey || e.shiftKey || this.simpleSelect);
17643             }
17644         }
17645     },
17646
17647     
17648     getSelectionCount : function(){
17649         return this.selected.getCount()
17650     },
17651
17652     
17653     getSelectedNodes : function(){
17654         return this.selected.elements;
17655     },
17656
17657     
17658     getSelectedIndexes : function(){
17659         var indexes = [], s = this.selected.elements;
17660         for(var i = 0, len = s.length; i < len; i++){
17661             indexes.push(s[i].viewIndex);
17662         }
17663         return indexes;
17664     },
17665
17666     
17667     getSelectedRecords : function(){
17668         var r = [], s = this.selected.elements;
17669         for(var i = 0, len = s.length; i < len; i++){
17670             r[r.length] = this.store.getAt(s[i].viewIndex);
17671         }
17672         return r;
17673     },
17674
17675     
17676     getRecords : function(nodes){
17677         var r = [], s = nodes;
17678         for(var i = 0, len = s.length; i < len; i++){
17679             r[r.length] = this.store.getAt(s[i].viewIndex);
17680         }
17681         return r;
17682     },
17683
17684     
17685     getRecord : function(node){
17686         return this.store.getAt(node.viewIndex);
17687     },
17688
17689     
17690     clearSelections : function(suppressEvent, skipUpdate){
17691         if(this.multiSelect || this.singleSelect){
17692             if(!skipUpdate){
17693                 this.selected.removeClass(this.selectedClass);
17694             }
17695             this.selected.clear();
17696             this.last = false;
17697             if(!suppressEvent){
17698                 this.fireEvent("selectionchange", this, this.selected.elements);
17699             }
17700         }
17701     },
17702
17703     
17704     isSelected : function(node){
17705         return this.selected.contains(this.getNode(node));
17706     },
17707
17708     
17709     deselect : function(node){
17710         if(this.isSelected(node)){
17711             var node = this.getNode(node);
17712             this.selected.removeElement(node);
17713             if(this.last == node.viewIndex){
17714                 this.last = false;
17715             }
17716             Ext.fly(node).removeClass(this.selectedClass);
17717             this.fireEvent("selectionchange", this, this.selected.elements);
17718         }
17719     },
17720
17721     
17722     select : function(nodeInfo, keepExisting, suppressEvent){
17723         if(Ext.isArray(nodeInfo)){
17724             if(!keepExisting){
17725                 this.clearSelections(true);
17726             }
17727             for(var i = 0, len = nodeInfo.length; i < len; i++){
17728                 this.select(nodeInfo[i], true, true);
17729             }
17730         } else{
17731             var node = this.getNode(nodeInfo);
17732             if(!keepExisting){
17733                 this.clearSelections(true);
17734             }
17735             if(node && !this.isSelected(node)){
17736                 if(this.fireEvent("beforeselect", this, node, this.selected.elements) !== false){
17737                     Ext.fly(node).addClass(this.selectedClass);
17738                     this.selected.add(node);
17739                     this.last = node.viewIndex;
17740                     if(!suppressEvent){
17741                         this.fireEvent("selectionchange", this, this.selected.elements);
17742                     }
17743                 }
17744             }
17745         }
17746     },
17747
17748     
17749     selectRange : function(start, end, keepExisting){
17750         if(!keepExisting){
17751             this.clearSelections(true);
17752         }
17753         this.select(this.getNodes(start, end), true);
17754     },
17755
17756     
17757     getNode : function(nodeInfo){
17758         if(typeof nodeInfo == "string"){
17759             return document.getElementById(nodeInfo);
17760         }else if(typeof nodeInfo == "number"){
17761             return this.all.elements[nodeInfo];
17762         }
17763         return nodeInfo;
17764     },
17765
17766     
17767     getNodes : function(start, end){
17768         var ns = this.all.elements;
17769         start = start || 0;
17770         end = typeof end == "undefined" ? ns.length - 1 : end;
17771         var nodes = [], i;
17772         if(start <= end){
17773             for(i = start; i <= end; i++){
17774                 nodes.push(ns[i]);
17775             }
17776         } else{
17777             for(i = start; i >= end; i--){
17778                 nodes.push(ns[i]);
17779             }
17780         }
17781         return nodes;
17782     },
17783
17784     
17785     indexOf : function(node){
17786         node = this.getNode(node);
17787         if(typeof node.viewIndex == "number"){
17788             return node.viewIndex;
17789         }
17790         return this.all.indexOf(node);
17791     },
17792
17793     
17794     onBeforeLoad : function(){
17795         if(this.loadingText){
17796             this.clearSelections(false, true);
17797             this.el.update('<div class="loading-indicator">'+this.loadingText+'</div>');
17798             this.all.clear();
17799         }
17800     }
17801 });
17802
17803 Ext.reg('dataview', Ext.DataView);
17804
17805 Ext.ColorPalette = function(config){
17806     Ext.ColorPalette.superclass.constructor.call(this, config);
17807     this.addEvents(
17808         
17809         'select'
17810     );
17811
17812     if(this.handler){
17813         this.on("select", this.handler, this.scope, true);
17814     }
17815 };
17816 Ext.extend(Ext.ColorPalette, Ext.Component, {
17817     
17818     itemCls : "x-color-palette",
17819     
17820     value : null,
17821     clickEvent:'click',
17822         ctype: "Ext.ColorPalette",
17823
17824     
17825     allowReselect : false,
17826
17827     
17828     colors : [
17829         "000000", "993300", "333300", "003300", "003366", "000080", "333399", "333333",
17830         "800000", "FF6600", "808000", "008000", "008080", "0000FF", "666699", "808080",
17831         "FF0000", "FF9900", "99CC00", "339966", "33CCCC", "3366FF", "800080", "969696",
17832         "FF00FF", "FFCC00", "FFFF00", "00FF00", "00FFFF", "00CCFF", "993366", "C0C0C0",
17833         "FF99CC", "FFCC99", "FFFF99", "CCFFCC", "CCFFFF", "99CCFF", "CC99FF", "FFFFFF"
17834     ],
17835
17836         onRender : function(container, position){
17837         var t = this.tpl || new Ext.XTemplate(
17838             '<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on">&#160;</span></em></a></tpl>'
17839         );
17840         var el = document.createElement("div");
17841         el.className = this.itemCls;
17842         t.overwrite(el, this.colors);
17843         container.dom.insertBefore(el, position);
17844         this.el = Ext.get(el);
17845         this.el.on(this.clickEvent, this.handleClick,  this, {delegate: "a"});
17846         if(this.clickEvent != 'click'){
17847             this.el.on('click', Ext.emptyFn,  this, {delegate: "a", preventDefault:true});
17848         }
17849     },
17850
17851         afterRender : function(){
17852         Ext.ColorPalette.superclass.afterRender.call(this);
17853         if(this.value){
17854             var s = this.value;
17855             this.value = null;
17856             this.select(s);
17857         }
17858     },
17859
17860         handleClick : function(e, t){
17861         e.preventDefault();
17862         if(!this.disabled){
17863             var c = t.className.match(/(?:^|\s)color-(.{6})(?:\s|$)/)[1];
17864             this.select(c.toUpperCase());
17865         }
17866     },
17867
17868     
17869     select : function(color){
17870         color = color.replace("#", "");
17871         if(color != this.value || this.allowReselect){
17872             var el = this.el;
17873             if(this.value){
17874                 el.child("a.color-"+this.value).removeClass("x-color-palette-sel");
17875             }
17876             el.child("a.color-"+color).addClass("x-color-palette-sel");
17877             this.value = color;
17878             this.fireEvent("select", this, color);
17879         }
17880     }
17881
17882     
17883 });
17884 Ext.reg('colorpalette', Ext.ColorPalette);
17885
17886 Ext.DatePicker = Ext.extend(Ext.Component, {
17887     
17888     todayText : "Today",
17889     
17890     okText : "&#160;OK&#160;", 
17891     
17892     cancelText : "Cancel",
17893     
17894     todayTip : "{0} (Spacebar)",
17895     
17896     minDate : null,
17897     
17898     maxDate : null,
17899     
17900     minText : "This date is before the minimum date",
17901     
17902     maxText : "This date is after the maximum date",
17903     
17904     format : "m/d/y",
17905     
17906     disabledDays : null,
17907     
17908     disabledDaysText : "",
17909     
17910     disabledDatesRE : null,
17911     
17912     disabledDatesText : "",
17913     
17914     constrainToViewport : true,
17915     
17916     monthNames : Date.monthNames,
17917     
17918     dayNames : Date.dayNames,
17919     
17920     nextText: 'Next Month (Control+Right)',
17921     
17922     prevText: 'Previous Month (Control+Left)',
17923     
17924     monthYearText: 'Choose a month (Control+Up/Down to move years)',
17925     
17926     startDay : 0,
17927
17928     initComponent : function(){
17929         Ext.DatePicker.superclass.initComponent.call(this);
17930
17931         this.value = this.value ?
17932                  this.value.clearTime() : new Date().clearTime();
17933
17934         this.addEvents(
17935             
17936             'select'
17937         );
17938
17939         if(this.handler){
17940             this.on("select", this.handler,  this.scope || this);
17941         }
17942
17943         this.initDisabledDays();
17944     },
17945
17946     
17947     initDisabledDays : function(){
17948         if(!this.disabledDatesRE && this.disabledDates){
17949             var dd = this.disabledDates;
17950             var re = "(?:";
17951             for(var i = 0; i < dd.length; i++){
17952                 re += dd[i];
17953                 if(i != dd.length-1) re += "|";
17954             }
17955             this.disabledDatesRE = new RegExp(re + ")");
17956         }
17957     },
17958
17959     
17960     setValue : function(value){
17961         var old = this.value;
17962         this.value = value.clearTime(true);
17963         if(this.el){
17964             this.update(this.value);
17965         }
17966     },
17967
17968     
17969     getValue : function(){
17970         return this.value;
17971     },
17972
17973     
17974     focus : function(){
17975         if(this.el){
17976             this.update(this.activeDate);
17977         }
17978     },
17979
17980     
17981     onRender : function(container, position){
17982         var m = [
17983              '<table cellspacing="0">',
17984                 '<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>',
17985                 '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'];
17986         var dn = this.dayNames;
17987         for(var i = 0; i < 7; i++){
17988             var d = this.startDay+i;
17989             if(d > 6){
17990                 d = d-7;
17991             }
17992             m.push("<th><span>", dn[d].substr(0,1), "</span></th>");
17993         }
17994         m[m.length] = "</tr></thead><tbody><tr>";
17995         for(var i = 0; i < 42; i++) {
17996             if(i % 7 == 0 && i != 0){
17997                 m[m.length] = "</tr><tr>";
17998             }
17999             m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
18000         }
18001         m[m.length] = '</tr></tbody></table></td></tr><tr><td colspan="3" class="x-date-bottom" align="center"></td></tr></table><div class="x-date-mp"></div>';
18002
18003         var el = document.createElement("div");
18004         el.className = "x-date-picker";
18005         el.innerHTML = m.join("");
18006
18007         container.dom.insertBefore(el, position);
18008
18009         this.el = Ext.get(el);
18010         this.eventEl = Ext.get(el.firstChild);
18011
18012         new Ext.util.ClickRepeater(this.el.child("td.x-date-left a"), {
18013             handler: this.showPrevMonth,
18014             scope: this,
18015             preventDefault:true,
18016             stopDefault:true
18017         });
18018
18019         new Ext.util.ClickRepeater(this.el.child("td.x-date-right a"), {
18020             handler: this.showNextMonth,
18021             scope: this,
18022             preventDefault:true,
18023             stopDefault:true
18024         });
18025
18026         this.eventEl.on("mousewheel", this.handleMouseWheel,  this);
18027
18028         this.monthPicker = this.el.down('div.x-date-mp');
18029         this.monthPicker.enableDisplayMode('block');
18030         
18031         var kn = new Ext.KeyNav(this.eventEl, {
18032             "left" : function(e){
18033                 e.ctrlKey ?
18034                     this.showPrevMonth() :
18035                     this.update(this.activeDate.add("d", -1));
18036             },
18037
18038             "right" : function(e){
18039                 e.ctrlKey ?
18040                     this.showNextMonth() :
18041                     this.update(this.activeDate.add("d", 1));
18042             },
18043
18044             "up" : function(e){
18045                 e.ctrlKey ?
18046                     this.showNextYear() :
18047                     this.update(this.activeDate.add("d", -7));
18048             },
18049
18050             "down" : function(e){
18051                 e.ctrlKey ?
18052                     this.showPrevYear() :
18053                     this.update(this.activeDate.add("d", 7));
18054             },
18055
18056             "pageUp" : function(e){
18057                 this.showNextMonth();
18058             },
18059
18060             "pageDown" : function(e){
18061                 this.showPrevMonth();
18062             },
18063
18064             "enter" : function(e){
18065                 e.stopPropagation();
18066                 return true;
18067             },
18068
18069             scope : this
18070         });
18071
18072         this.eventEl.on("click", this.handleDateClick,  this, {delegate: "a.x-date-date"});
18073
18074         this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday,  this);
18075
18076         this.el.unselectable();
18077         
18078         this.cells = this.el.select("table.x-date-inner tbody td");
18079         this.textNodes = this.el.query("table.x-date-inner tbody span");
18080
18081         this.mbtn = new Ext.Button({
18082             text: "&#160;",
18083             tooltip: this.monthYearText,
18084             renderTo: this.el.child("td.x-date-middle", true)
18085         });
18086
18087         this.mbtn.on('click', this.showMonthPicker, this);
18088         this.mbtn.el.child(this.mbtn.menuClassTarget).addClass("x-btn-with-menu");
18089
18090
18091         var today = (new Date()).dateFormat(this.format);
18092         this.todayBtn = new Ext.Button({
18093             renderTo: this.el.child("td.x-date-bottom", true),
18094             text: String.format(this.todayText, today),
18095             tooltip: String.format(this.todayTip, today),
18096             handler: this.selectToday,
18097             scope: this
18098         });
18099         
18100         if(Ext.isIE){
18101             this.el.repaint();
18102         }
18103         this.update(this.value);
18104     },
18105
18106     createMonthPicker : function(){
18107         if(!this.monthPicker.dom.firstChild){
18108             var buf = ['<table border="0" cellspacing="0">'];
18109             for(var i = 0; i < 6; i++){
18110                 buf.push(
18111                     '<tr><td class="x-date-mp-month"><a href="#">', this.monthNames[i].substr(0, 3), '</a></td>',
18112                     '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', this.monthNames[i+6].substr(0, 3), '</a></td>',
18113                     i == 0 ?
18114                     '<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>' :
18115                     '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'
18116                 );
18117             }
18118             buf.push(
18119                 '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',
18120                     this.okText,
18121                     '</button><button type="button" class="x-date-mp-cancel">',
18122                     this.cancelText,
18123                     '</button></td></tr>',
18124                 '</table>'
18125             );
18126             this.monthPicker.update(buf.join(''));
18127             this.monthPicker.on('click', this.onMonthClick, this);
18128             this.monthPicker.on('dblclick', this.onMonthDblClick, this);
18129
18130             this.mpMonths = this.monthPicker.select('td.x-date-mp-month');
18131             this.mpYears = this.monthPicker.select('td.x-date-mp-year');
18132
18133             this.mpMonths.each(function(m, a, i){
18134                 i += 1;
18135                 if((i%2) == 0){
18136                     m.dom.xmonth = 5 + Math.round(i * .5);
18137                 }else{
18138                     m.dom.xmonth = Math.round((i-1) * .5);
18139                 }
18140             });
18141         }
18142     },
18143
18144     showMonthPicker : function(){
18145         this.createMonthPicker();
18146         var size = this.el.getSize();
18147         this.monthPicker.setSize(size);
18148         this.monthPicker.child('table').setSize(size);
18149
18150         this.mpSelMonth = (this.activeDate || this.value).getMonth();
18151         this.updateMPMonth(this.mpSelMonth);
18152         this.mpSelYear = (this.activeDate || this.value).getFullYear();
18153         this.updateMPYear(this.mpSelYear);
18154
18155         this.monthPicker.slideIn('t', {duration:.2});
18156     },
18157
18158     updateMPYear : function(y){
18159         this.mpyear = y;
18160         var ys = this.mpYears.elements;
18161         for(var i = 1; i <= 10; i++){
18162             var td = ys[i-1], y2;
18163             if((i%2) == 0){
18164                 y2 = y + Math.round(i * .5);
18165                 td.firstChild.innerHTML = y2;
18166                 td.xyear = y2;
18167             }else{
18168                 y2 = y - (5-Math.round(i * .5));
18169                 td.firstChild.innerHTML = y2;
18170                 td.xyear = y2;
18171             }
18172             this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');
18173         }
18174     },
18175
18176     updateMPMonth : function(sm){
18177         this.mpMonths.each(function(m, a, i){
18178             m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');
18179         });
18180     },
18181
18182     selectMPMonth: function(m){
18183         
18184     },
18185
18186     onMonthClick : function(e, t){
18187         e.stopEvent();
18188         var el = new Ext.Element(t), pn;
18189         if(el.is('button.x-date-mp-cancel')){
18190             this.hideMonthPicker();
18191         }
18192         else if(el.is('button.x-date-mp-ok')){
18193             this.update(new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
18194             this.hideMonthPicker();
18195         }
18196         else if(pn = el.up('td.x-date-mp-month', 2)){
18197             this.mpMonths.removeClass('x-date-mp-sel');
18198             pn.addClass('x-date-mp-sel');
18199             this.mpSelMonth = pn.dom.xmonth;
18200         }
18201         else if(pn = el.up('td.x-date-mp-year', 2)){
18202             this.mpYears.removeClass('x-date-mp-sel');
18203             pn.addClass('x-date-mp-sel');
18204             this.mpSelYear = pn.dom.xyear;
18205         }
18206         else if(el.is('a.x-date-mp-prev')){
18207             this.updateMPYear(this.mpyear-10);
18208         }
18209         else if(el.is('a.x-date-mp-next')){
18210             this.updateMPYear(this.mpyear+10);
18211         }
18212     },
18213
18214     onMonthDblClick : function(e, t){
18215         e.stopEvent();
18216         var el = new Ext.Element(t), pn;
18217         if(pn = el.up('td.x-date-mp-month', 2)){
18218             this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));
18219             this.hideMonthPicker();
18220         }
18221         else if(pn = el.up('td.x-date-mp-year', 2)){
18222             this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
18223             this.hideMonthPicker();
18224         }
18225     },
18226
18227     hideMonthPicker : function(disableAnim){
18228         if(this.monthPicker){
18229             if(disableAnim === true){
18230                 this.monthPicker.hide();
18231             }else{
18232                 this.monthPicker.slideOut('t', {duration:.2});
18233             }
18234         }
18235     },
18236
18237     
18238     showPrevMonth : function(e){
18239         this.update(this.activeDate.add("mo", -1));
18240     },
18241
18242     
18243     showNextMonth : function(e){
18244         this.update(this.activeDate.add("mo", 1));
18245     },
18246
18247     
18248     showPrevYear : function(){
18249         this.update(this.activeDate.add("y", -1));
18250     },
18251
18252     
18253     showNextYear : function(){
18254         this.update(this.activeDate.add("y", 1));
18255     },
18256
18257     
18258     handleMouseWheel : function(e){
18259         var delta = e.getWheelDelta();
18260         if(delta > 0){
18261             this.showPrevMonth();
18262             e.stopEvent();
18263         } else if(delta < 0){
18264             this.showNextMonth();
18265             e.stopEvent();
18266         }
18267     },
18268
18269     
18270     handleDateClick : function(e, t){
18271         e.stopEvent();
18272         if(t.dateValue && !Ext.fly(t.parentNode).hasClass("x-date-disabled")){
18273             this.setValue(new Date(t.dateValue));
18274             this.fireEvent("select", this, this.value);
18275         }
18276     },
18277
18278     
18279     selectToday : function(){
18280         this.setValue(new Date().clearTime());
18281         this.fireEvent("select", this, this.value);
18282     },
18283
18284     
18285     update : function(date){
18286         var vd = this.activeDate;
18287         this.activeDate = date;
18288         if(vd && this.el){
18289             var t = date.getTime();
18290             if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
18291                 this.cells.removeClass("x-date-selected");
18292                 this.cells.each(function(c){
18293                    if(c.dom.firstChild.dateValue == t){
18294                        c.addClass("x-date-selected");
18295                        setTimeout(function(){
18296                             try{c.dom.firstChild.focus();}catch(e){}
18297                        }, 50);
18298                        return false;
18299                    }
18300                 });
18301                 return;
18302             }
18303         }
18304         var days = date.getDaysInMonth();
18305         var firstOfMonth = date.getFirstDateOfMonth();
18306         var startingPos = firstOfMonth.getDay()-this.startDay;
18307
18308         if(startingPos <= this.startDay){
18309             startingPos += 7;
18310         }
18311
18312         var pm = date.add("mo", -1);
18313         var prevStart = pm.getDaysInMonth()-startingPos;
18314
18315         var cells = this.cells.elements;
18316         var textEls = this.textNodes;
18317         days += startingPos;
18318
18319         
18320         var day = 86400000;
18321         var d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart)).clearTime();
18322         var today = new Date().clearTime().getTime();
18323         var sel = date.clearTime().getTime();
18324         var min = this.minDate ? this.minDate.clearTime() : Number.NEGATIVE_INFINITY;
18325         var max = this.maxDate ? this.maxDate.clearTime() : Number.POSITIVE_INFINITY;
18326         var ddMatch = this.disabledDatesRE;
18327         var ddText = this.disabledDatesText;
18328         var ddays = this.disabledDays ? this.disabledDays.join("") : false;
18329         var ddaysText = this.disabledDaysText;
18330         var format = this.format;
18331
18332         var setCellClass = function(cal, cell){
18333             cell.title = "";
18334             var t = d.getTime();
18335             cell.firstChild.dateValue = t;
18336             if(t == today){
18337                 cell.className += " x-date-today";
18338                 cell.title = cal.todayText;
18339             }
18340             if(t == sel){
18341                 cell.className += " x-date-selected";
18342                 setTimeout(function(){
18343                     try{cell.firstChild.focus();}catch(e){}
18344                 }, 50);
18345             }
18346             
18347             if(t < min) {
18348                 cell.className = " x-date-disabled";
18349                 cell.title = cal.minText;
18350                 return;
18351             }
18352             if(t > max) {
18353                 cell.className = " x-date-disabled";
18354                 cell.title = cal.maxText;
18355                 return;
18356             }
18357             if(ddays){
18358                 if(ddays.indexOf(d.getDay()) != -1){
18359                     cell.title = ddaysText;
18360                     cell.className = " x-date-disabled";
18361                 }
18362             }
18363             if(ddMatch && format){
18364                 var fvalue = d.dateFormat(format);
18365                 if(ddMatch.test(fvalue)){
18366                     cell.title = ddText.replace("%0", fvalue);
18367                     cell.className = " x-date-disabled";
18368                 }
18369             }
18370         };
18371
18372         var i = 0;
18373         for(; i < startingPos; i++) {
18374             textEls[i].innerHTML = (++prevStart);
18375             d.setDate(d.getDate()+1);
18376             cells[i].className = "x-date-prevday";
18377             setCellClass(this, cells[i]);
18378         }
18379         for(; i < days; i++){
18380             intDay = i - startingPos + 1;
18381             textEls[i].innerHTML = (intDay);
18382             d.setDate(d.getDate()+1);
18383             cells[i].className = "x-date-active";
18384             setCellClass(this, cells[i]);
18385         }
18386         var extraDays = 0;
18387         for(; i < 42; i++) {
18388              textEls[i].innerHTML = (++extraDays);
18389              d.setDate(d.getDate()+1);
18390              cells[i].className = "x-date-nextday";
18391              setCellClass(this, cells[i]);
18392         }
18393
18394         this.mbtn.setText(this.monthNames[date.getMonth()] + " " + date.getFullYear());
18395
18396         if(!this.internalRender){
18397             var main = this.el.dom.firstChild;
18398             var w = main.offsetWidth;
18399             this.el.setWidth(w + this.el.getBorderWidth("lr"));
18400             Ext.fly(main).setWidth(w);
18401             this.internalRender = true;
18402             
18403             
18404             
18405             if(Ext.isOpera && !this.secondPass){
18406                 main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + "px";
18407                 this.secondPass = true;
18408                 this.update.defer(10, this, [date]);
18409             }
18410         }
18411     },
18412
18413     
18414     beforeDestroy : function() {
18415         this.mbtn.destroy();
18416         this.todayBtn.destroy();
18417     }
18418
18419     
18420 });
18421 Ext.reg('datepicker', Ext.DatePicker);
18422
18423 Ext.TabPanel = Ext.extend(Ext.Panel,  {
18424     
18425     
18426     monitorResize : true,
18427     
18428     deferredRender : true,
18429     
18430     tabWidth: 120,
18431     
18432     minTabWidth: 30,
18433     
18434     resizeTabs:false,
18435     
18436     enableTabScroll: false,
18437     
18438     scrollIncrement : 0,
18439     
18440     scrollRepeatInterval : 400,
18441     
18442     scrollDuration : .35,
18443     
18444     animScroll : true,
18445     
18446     tabPosition: 'top',
18447     
18448     baseCls: 'x-tab-panel',
18449     
18450     autoTabs : false,
18451     
18452     autoTabSelector:'div.x-tab',
18453     
18454     activeTab : null,
18455     
18456     tabMargin : 2,
18457     
18458     plain: false,
18459     
18460     wheelIncrement : 20,
18461
18462     
18463     idDelimiter : '__',
18464
18465         itemCls : 'x-tab-item',
18466
18467         elements: 'body',
18468     headerAsText: false,
18469     frame: false,
18470     hideBorders:true,
18471
18472         initComponent : function(){
18473         this.frame = false;
18474         Ext.TabPanel.superclass.initComponent.call(this);
18475         this.addEvents(
18476             
18477             'beforetabchange',
18478             
18479             'tabchange',
18480             
18481             'contextmenu'
18482         );
18483         this.setLayout(new Ext.layout.CardLayout({
18484             deferredRender: this.deferredRender
18485         }));
18486         if(this.tabPosition == 'top'){
18487             this.elements += ',header';
18488             this.stripTarget = 'header';
18489         }else {
18490             this.elements += ',footer';
18491             this.stripTarget = 'footer';
18492         }
18493         if(!this.stack){
18494             this.stack = Ext.TabPanel.AccessStack();
18495         }
18496         this.initItems();
18497     },
18498
18499         render : function(){
18500         Ext.TabPanel.superclass.render.apply(this, arguments);
18501         if(this.activeTab !== undefined){
18502             var item = this.activeTab;
18503             delete this.activeTab;
18504             this.setActiveTab(item);
18505         }
18506     },
18507
18508         onRender : function(ct, position){
18509         Ext.TabPanel.superclass.onRender.call(this, ct, position);
18510
18511         if(this.plain){
18512             var pos = this.tabPosition == 'top' ? 'header' : 'footer';
18513             this[pos].addClass('x-tab-panel-'+pos+'-plain');
18514         }
18515
18516         var st = this[this.stripTarget];
18517
18518         this.stripWrap = st.createChild({cls:'x-tab-strip-wrap', cn:{
18519             tag:'ul', cls:'x-tab-strip x-tab-strip-'+this.tabPosition}});
18520         this.stripSpacer = st.createChild({cls:'x-tab-strip-spacer'});
18521         this.strip = new Ext.Element(this.stripWrap.dom.firstChild);
18522
18523         this.edge = this.strip.createChild({tag:'li', cls:'x-tab-edge'});
18524         this.strip.createChild({cls:'x-clear'});
18525
18526         this.body.addClass('x-tab-panel-body-'+this.tabPosition);
18527
18528         if(!this.itemTpl){
18529             var tt = new Ext.Template(
18530                  '<li class="{cls}" id="{id}"><a class="x-tab-strip-close" onclick="return false;"></a>',
18531                  '<a class="x-tab-right" href="#" onclick="return false;"><em class="x-tab-left">',
18532                  '<span class="x-tab-strip-inner"><span class="x-tab-strip-text {iconCls}">{text}</span></span>',
18533                  '</em></a></li>'
18534             );
18535             tt.disableFormats = true;
18536             tt.compile();
18537             Ext.TabPanel.prototype.itemTpl = tt;
18538         }
18539
18540         this.items.each(this.initTab, this);
18541     },
18542
18543         afterRender : function(){
18544         Ext.TabPanel.superclass.afterRender.call(this);
18545         if(this.autoTabs){
18546             this.readTabs(false);
18547         }
18548     },
18549
18550         initEvents : function(){
18551         Ext.TabPanel.superclass.initEvents.call(this);
18552         this.on('add', this.onAdd, this);
18553         this.on('remove', this.onRemove, this);
18554
18555         this.strip.on('mousedown', this.onStripMouseDown, this);
18556         this.strip.on('click', this.onStripClick, this);
18557         this.strip.on('contextmenu', this.onStripContextMenu, this);
18558         if(this.enableTabScroll){
18559             this.strip.on('mousewheel', this.onWheel, this);
18560         }
18561     },
18562
18563         findTargets : function(e){
18564         var item = null;
18565         var itemEl = e.getTarget('li', this.strip);
18566         if(itemEl){
18567             item = this.getComponent(itemEl.id.split(this.idDelimiter)[1]);
18568             if(item.disabled){
18569                 return {
18570                     close : null,
18571                     item : null,
18572                     el : null
18573                 };
18574             }
18575         }
18576         return {
18577             close : e.getTarget('.x-tab-strip-close', this.strip),
18578             item : item,
18579             el : itemEl
18580         };
18581     },
18582
18583         onStripMouseDown : function(e){
18584         e.preventDefault();
18585         if(e.button != 0){
18586             return;
18587         }
18588         var t = this.findTargets(e);
18589         if(t.close){
18590             this.remove(t.item);
18591             return;
18592         }
18593         if(t.item && t.item != this.activeTab){
18594             this.setActiveTab(t.item);
18595         }
18596     },
18597
18598         onStripClick : function(e){
18599         var t = this.findTargets(e);
18600         if(!t.close && t.item && t.item != this.activeTab){
18601             this.setActiveTab(t.item);
18602         }
18603     },
18604
18605         onStripContextMenu : function(e){
18606         e.preventDefault();
18607         var t = this.findTargets(e);
18608         if(t.item){
18609             this.fireEvent('contextmenu', this, t.item, e);
18610         }
18611     },
18612
18613     
18614     readTabs : function(removeExisting){
18615         if(removeExisting === true){
18616             this.items.each(function(item){
18617                 this.remove(item);
18618             }, this);
18619         }
18620         var tabs = this.el.query(this.autoTabSelector);
18621         for(var i = 0, len = tabs.length; i < len; i++){
18622             var tab = tabs[i];
18623             var title = tab.getAttribute('title');
18624             tab.removeAttribute('title');
18625             this.add({
18626                 title: title,
18627                 el: tab
18628             });
18629         }
18630     },
18631
18632         initTab : function(item, index){
18633         var before = this.strip.dom.childNodes[index];
18634         var cls = item.closable ? 'x-tab-strip-closable' : '';
18635         if(item.disabled){
18636             cls += ' x-item-disabled';
18637         }
18638         if(item.iconCls){
18639             cls += ' x-tab-with-icon';
18640         }
18641         if(item.tabCls){
18642             cls += ' ' + item.tabCls;
18643         }
18644         
18645         var p = {
18646             id: this.id + this.idDelimiter + item.getItemId(),
18647             text: item.title,
18648             cls: cls,
18649             iconCls: item.iconCls || ''
18650         };
18651         var el = before ?
18652                  this.itemTpl.insertBefore(before, p) :
18653                  this.itemTpl.append(this.strip, p);
18654
18655         Ext.fly(el).addClassOnOver('x-tab-strip-over');
18656
18657         if(item.tabTip){
18658             Ext.fly(el).child('span.x-tab-strip-text', true).qtip = item.tabTip;
18659         }
18660         item.on('disable', this.onItemDisabled, this);
18661         item.on('enable', this.onItemEnabled, this);
18662         item.on('titlechange', this.onItemTitleChanged, this);
18663         item.on('beforeshow', this.onBeforeShowItem, this);
18664     },
18665
18666         onAdd : function(tp, item, index){
18667         this.initTab(item, index);
18668         if(this.items.getCount() == 1){
18669             this.syncSize();
18670         }
18671         this.delegateUpdates();
18672     },
18673
18674         onBeforeAdd : function(item){
18675         var existing = item.events ? (this.items.containsKey(item.getItemId()) ? item : null) : this.items.get(item);
18676         if(existing){
18677             this.setActiveTab(item);
18678             return false;
18679         }
18680         Ext.TabPanel.superclass.onBeforeAdd.apply(this, arguments);
18681         var es = item.elements;
18682         item.elements = es ? es.replace(',header', '') : es;
18683         item.border = (item.border === true);
18684     },
18685
18686         onRemove : function(tp, item){
18687         Ext.removeNode(this.getTabEl(item));
18688         this.stack.remove(item);
18689         if(item == this.activeTab){
18690             var next = this.stack.next();
18691             if(next){
18692                 this.setActiveTab(next);
18693             }else{
18694                 this.setActiveTab(0);
18695             }
18696         }
18697         this.delegateUpdates();
18698     },
18699
18700         onBeforeShowItem : function(item){
18701         if(item != this.activeTab){
18702             this.setActiveTab(item);
18703             return false;
18704         }
18705     },
18706
18707         onItemDisabled : function(item){
18708         var el = this.getTabEl(item);
18709         if(el){
18710             Ext.fly(el).addClass('x-item-disabled');
18711         }
18712         this.stack.remove(item);
18713     },
18714
18715         onItemEnabled : function(item){
18716         var el = this.getTabEl(item);
18717         if(el){
18718             Ext.fly(el).removeClass('x-item-disabled');
18719         }
18720     },
18721
18722         onItemTitleChanged : function(item){
18723         var el = this.getTabEl(item);
18724         if(el){
18725             Ext.fly(el).child('span.x-tab-strip-text', true).innerHTML = item.title;
18726         }
18727     },
18728
18729     
18730     getTabEl : function(item){
18731         var itemId = (typeof item === 'number')?this.items.items[item].getItemId() : item.getItemId();
18732         return document.getElementById(this.id+this.idDelimiter+itemId);
18733     },
18734
18735         onResize : function(){
18736         Ext.TabPanel.superclass.onResize.apply(this, arguments);
18737         this.delegateUpdates();
18738     },
18739
18740     
18741     beginUpdate : function(){
18742         this.suspendUpdates = true;
18743     },
18744
18745     
18746     endUpdate : function(){
18747         this.suspendUpdates = false;
18748         this.delegateUpdates();
18749     },
18750
18751     
18752     hideTabStripItem : function(item){
18753         item = this.getComponent(item);
18754         var el = this.getTabEl(item);
18755         if(el){
18756             el.style.display = 'none';
18757             this.delegateUpdates();
18758         }
18759     },
18760
18761     
18762     unhideTabStripItem : function(item){
18763         item = this.getComponent(item);
18764         var el = this.getTabEl(item);
18765         if(el){
18766             el.style.display = '';
18767             this.delegateUpdates();
18768         }
18769     },
18770
18771         delegateUpdates : function(){
18772         if(this.suspendUpdates){
18773             return;
18774         }
18775         if(this.resizeTabs && this.rendered){
18776             this.autoSizeTabs();
18777         }
18778         if(this.enableTabScroll && this.rendered){
18779             this.autoScrollTabs();
18780         }
18781     },
18782
18783         autoSizeTabs : function(){
18784         var count = this.items.length;
18785         var ce = this.tabPosition != 'bottom' ? 'header' : 'footer';
18786         var ow = this[ce].dom.offsetWidth;
18787         var aw = this[ce].dom.clientWidth;
18788
18789         if(!this.resizeTabs || count < 1 || !aw){             return;
18790         }
18791
18792         var each = Math.max(Math.min(Math.floor((aw-4) / count) - this.tabMargin, this.tabWidth), this.minTabWidth);         this.lastTabWidth = each;
18793         var lis = this.stripWrap.dom.getElementsByTagName('li');
18794         for(var i = 0, len = lis.length-1; i < len; i++) {             var li = lis[i];
18795             var inner = li.childNodes[1].firstChild.firstChild;
18796             var tw = li.offsetWidth;
18797             var iw = inner.offsetWidth;
18798             inner.style.width = (each - (tw-iw)) + 'px';
18799         }
18800     },
18801
18802         adjustBodyWidth : function(w){
18803         if(this.header){
18804             this.header.setWidth(w);
18805         }
18806         if(this.footer){
18807             this.footer.setWidth(w);
18808         }
18809         return w;
18810     },
18811
18812     
18813     setActiveTab : function(item){
18814         item = this.getComponent(item);
18815         if(!item || this.fireEvent('beforetabchange', this, item, this.activeTab) === false){
18816             return;
18817         }
18818         if(!this.rendered){
18819             this.activeTab = item;
18820             return;
18821         }
18822         if(this.activeTab != item){
18823             if(this.activeTab){
18824                 var oldEl = this.getTabEl(this.activeTab);
18825                 if(oldEl){
18826                     Ext.fly(oldEl).removeClass('x-tab-strip-active');
18827                 }
18828                 this.activeTab.fireEvent('deactivate', this.activeTab);
18829             }
18830             var el = this.getTabEl(item);
18831             Ext.fly(el).addClass('x-tab-strip-active');
18832             this.activeTab = item;
18833             this.stack.add(item);
18834
18835             this.layout.setActiveItem(item);
18836             if(this.layoutOnTabChange && item.doLayout){
18837                 item.doLayout();
18838             }
18839             if(this.scrolling){
18840                 this.scrollToTab(item, this.animScroll);
18841             }
18842
18843             item.fireEvent('activate', item);
18844             this.fireEvent('tabchange', this, item);
18845         }
18846     },
18847
18848     
18849     getActiveTab : function(){
18850         return this.activeTab || null;
18851     },
18852
18853     
18854     getItem : function(item){
18855         return this.getComponent(item);
18856     },
18857
18858         autoScrollTabs : function(){
18859         var count = this.items.length;
18860         var ow = this.header.dom.offsetWidth;
18861         var tw = this.header.dom.clientWidth;
18862
18863         var wrap = this.stripWrap;
18864         var wd = wrap.dom;
18865         var cw = wd.offsetWidth;
18866         var pos = this.getScrollPos();
18867         var l = this.edge.getOffsetsTo(this.stripWrap)[0] + pos;
18868
18869         if(!this.enableTabScroll || count < 1 || cw < 20){             return;
18870         }
18871         if(l <= tw){
18872             wd.scrollLeft = 0;
18873             wrap.setWidth(tw);
18874             if(this.scrolling){
18875                 this.scrolling = false;
18876                 this.header.removeClass('x-tab-scrolling');
18877                 this.scrollLeft.hide();
18878                 this.scrollRight.hide();
18879                 if(Ext.isAir){
18880                     wd.style.marginLeft = '';
18881                     wd.style.marginRight = '';
18882                 }
18883             }
18884         }else{
18885             if(!this.scrolling){
18886                 this.header.addClass('x-tab-scrolling');
18887                 if(Ext.isAir){
18888                     wd.style.marginLeft = '18px';
18889                     wd.style.marginRight = '18px';
18890                 }
18891             }
18892             tw -= wrap.getMargins('lr');
18893             wrap.setWidth(tw > 20 ? tw : 20);
18894             if(!this.scrolling){
18895                 if(!this.scrollLeft){
18896                     this.createScrollers();
18897                 }else{
18898                     this.scrollLeft.show();
18899                     this.scrollRight.show();
18900                 }
18901             }
18902             this.scrolling = true;
18903             if(pos > (l-tw)){                 wd.scrollLeft = l-tw;
18904             }else{                 this.scrollToTab(this.activeTab, false);
18905             }
18906             this.updateScrollButtons();
18907         }
18908     },
18909
18910         createScrollers : function(){
18911         var h = this.stripWrap.dom.offsetHeight;
18912
18913                 var sl = this.header.insertFirst({
18914             cls:'x-tab-scroller-left'
18915         });
18916         sl.setHeight(h);
18917         sl.addClassOnOver('x-tab-scroller-left-over');
18918         this.leftRepeater = new Ext.util.ClickRepeater(sl, {
18919             interval : this.scrollRepeatInterval,
18920             handler: this.onScrollLeft,
18921             scope: this
18922         });
18923         this.scrollLeft = sl;
18924
18925                 var sr = this.header.insertFirst({
18926             cls:'x-tab-scroller-right'
18927         });
18928         sr.setHeight(h);
18929         sr.addClassOnOver('x-tab-scroller-right-over');
18930         this.rightRepeater = new Ext.util.ClickRepeater(sr, {
18931             interval : this.scrollRepeatInterval,
18932             handler: this.onScrollRight,
18933             scope: this
18934         });
18935         this.scrollRight = sr;
18936     },
18937
18938         getScrollWidth : function(){
18939         return this.edge.getOffsetsTo(this.stripWrap)[0] + this.getScrollPos();
18940     },
18941
18942         getScrollPos : function(){
18943         return parseInt(this.stripWrap.dom.scrollLeft, 10) || 0;
18944     },
18945
18946         getScrollArea : function(){
18947         return parseInt(this.stripWrap.dom.clientWidth, 10) || 0;
18948     },
18949
18950         getScrollAnim : function(){
18951         return {duration:this.scrollDuration, callback: this.updateScrollButtons, scope: this};
18952     },
18953
18954         getScrollIncrement : function(){
18955         return this.scrollIncrement || (this.resizeTabs ? this.lastTabWidth+2 : 100);
18956     },
18957
18958     
18959
18960     scrollToTab : function(item, animate){
18961         if(!item){ return; }
18962         var el = this.getTabEl(item);
18963         var pos = this.getScrollPos(), area = this.getScrollArea();
18964         var left = Ext.fly(el).getOffsetsTo(this.stripWrap)[0] + pos;
18965         var right = left + el.offsetWidth;
18966         if(left < pos){
18967             this.scrollTo(left, animate);
18968         }else if(right > (pos + area)){
18969             this.scrollTo(right - area, animate);
18970         }
18971     },
18972
18973         scrollTo : function(pos, animate){
18974         this.stripWrap.scrollTo('left', pos, animate ? this.getScrollAnim() : false);
18975         if(!animate){
18976             this.updateScrollButtons();
18977         }
18978     },
18979
18980     onWheel : function(e){
18981         var d = e.getWheelDelta()*this.wheelIncrement*-1;
18982         e.stopEvent();
18983
18984         var pos = this.getScrollPos();
18985         var newpos = pos + d;
18986         var sw = this.getScrollWidth()-this.getScrollArea();
18987
18988         var s = Math.max(0, Math.min(sw, newpos));
18989         if(s != pos){
18990             this.scrollTo(s, false);
18991         }
18992     },
18993
18994         onScrollRight : function(){
18995         var sw = this.getScrollWidth()-this.getScrollArea();
18996         var pos = this.getScrollPos();
18997         var s = Math.min(sw, pos + this.getScrollIncrement());
18998         if(s != pos){
18999             this.scrollTo(s, this.animScroll);
19000         }
19001     },
19002
19003         onScrollLeft : function(){
19004         var pos = this.getScrollPos();
19005         var s = Math.max(0, pos - this.getScrollIncrement());
19006         if(s != pos){
19007             this.scrollTo(s, this.animScroll);
19008         }
19009     },
19010
19011         updateScrollButtons : function(){
19012         var pos = this.getScrollPos();
19013         this.scrollLeft[pos == 0 ? 'addClass' : 'removeClass']('x-tab-scroller-left-disabled');
19014         this.scrollRight[pos >= (this.getScrollWidth()-this.getScrollArea()) ? 'addClass' : 'removeClass']('x-tab-scroller-right-disabled');
19015     }
19016
19017     
19018     
19019     
19020     
19021     
19022     
19023     
19024     
19025     
19026
19027 });
19028 Ext.reg('tabpanel', Ext.TabPanel);
19029
19030
19031 Ext.TabPanel.prototype.activate = Ext.TabPanel.prototype.setActiveTab;
19032
19033 Ext.TabPanel.AccessStack = function(){
19034     var items = [];
19035     return {
19036         add : function(item){
19037             items.push(item);
19038             if(items.length > 10){
19039                 items.shift();
19040             }
19041         },
19042
19043         remove : function(item){
19044             var s = [];
19045             for(var i = 0, len = items.length; i < len; i++) {
19046                 if(items[i] != item){
19047                     s.push(items[i]);
19048                 }
19049             }
19050             items = s;
19051         },
19052
19053         next : function(){
19054             return items.pop();
19055         }
19056     };
19057 };
19058
19059
19060
19061
19062 Ext.Button = Ext.extend(Ext.Component, {
19063     
19064     hidden : false,
19065     
19066     disabled : false,
19067     
19068     pressed : false,
19069     
19070
19071     
19072
19073     
19074     enableToggle: false,
19075     
19076     
19077     menuAlign : "tl-bl?",
19078
19079     
19080     
19081     type : 'button',
19082
19083         menuClassTarget: 'tr',
19084
19085     
19086     clickEvent : 'click',
19087
19088     
19089     handleMouseEvents : true,
19090
19091     
19092     tooltipType : 'qtip',
19093
19094     buttonSelector : "button:first",
19095
19096     
19097
19098     
19099     initComponent : function(){
19100         Ext.Button.superclass.initComponent.call(this);
19101
19102         this.addEvents(
19103             
19104             "click",
19105             
19106             "toggle",
19107             
19108             'mouseover',
19109             
19110             'mouseout',
19111             
19112             'menushow',
19113             
19114             'menuhide',
19115             
19116             'menutriggerover',
19117             
19118             'menutriggerout'
19119         );
19120         if(this.menu){
19121             this.menu = Ext.menu.MenuMgr.get(this.menu);
19122         }
19123         if(typeof this.toggleGroup === 'string'){
19124             this.enableToggle = true;
19125         }
19126     },
19127
19128         onRender : function(ct, position){
19129         if(!this.template){
19130             if(!Ext.Button.buttonTemplate){
19131                                 Ext.Button.buttonTemplate = new Ext.Template(
19132                     '<table border="0" cellpadding="0" cellspacing="0" class="x-btn-wrap"><tbody><tr>',
19133                     '<td class="x-btn-left"><i>&#160;</i></td><td class="x-btn-center"><em unselectable="on"><button class="x-btn-text" type="{1}">{0}</button></em></td><td class="x-btn-right"><i>&#160;</i></td>',
19134                     "</tr></tbody></table>");
19135             }
19136             this.template = Ext.Button.buttonTemplate;
19137         }
19138         var btn, targs = [this.text || '&#160;', this.type];
19139
19140         if(position){
19141             btn = this.template.insertBefore(position, targs, true);
19142         }else{
19143             btn = this.template.append(ct, targs, true);
19144         }
19145         var btnEl = btn.child(this.buttonSelector);
19146         btnEl.on('focus', this.onFocus, this);
19147         btnEl.on('blur', this.onBlur, this);
19148
19149         this.initButtonEl(btn, btnEl);
19150
19151         if(this.menu){
19152             this.el.child(this.menuClassTarget).addClass("x-btn-with-menu");
19153         }
19154         Ext.ButtonToggleMgr.register(this);
19155     },
19156
19157         initButtonEl : function(btn, btnEl){
19158
19159         this.el = btn;
19160         btn.addClass("x-btn");
19161
19162         if(this.icon){
19163             btnEl.setStyle('background-image', 'url(' +this.icon +')');
19164         }
19165         if(this.iconCls){
19166             btnEl.addClass(this.iconCls);
19167             if(!this.cls){
19168                 btn.addClass(this.text ? 'x-btn-text-icon' : 'x-btn-icon');
19169             }
19170         }
19171         if(this.tabIndex !== undefined){
19172             btnEl.dom.tabIndex = this.tabIndex;
19173         }
19174         if(this.tooltip){
19175             if(typeof this.tooltip == 'object'){
19176                 Ext.QuickTips.register(Ext.apply({
19177                       target: btnEl.id
19178                 }, this.tooltip));
19179             } else {
19180                 btnEl.dom[this.tooltipType] = this.tooltip;
19181             }
19182         }
19183
19184         if(this.pressed){
19185             this.el.addClass("x-btn-pressed");
19186         }
19187
19188         if(this.handleMouseEvents){
19189             btn.on("mouseover", this.onMouseOver, this);
19190                                     btn.on("mousedown", this.onMouseDown, this);
19191         }
19192
19193         if(this.menu){
19194             this.menu.on("show", this.onMenuShow, this);
19195             this.menu.on("hide", this.onMenuHide, this);
19196         }
19197
19198         if(this.id){
19199             this.el.dom.id = this.el.id = this.id;
19200         }
19201
19202         if(this.repeat){
19203             var repeater = new Ext.util.ClickRepeater(btn,
19204                 typeof this.repeat == "object" ? this.repeat : {}
19205             );
19206             repeater.on("click", this.onClick,  this);
19207         }
19208
19209         btn.on(this.clickEvent, this.onClick, this);
19210     },
19211
19212         afterRender : function(){
19213         Ext.Button.superclass.afterRender.call(this);
19214         if(Ext.isIE6){
19215             this.autoWidth.defer(1, this);
19216         }else{
19217             this.autoWidth();
19218         }
19219     },
19220
19221     
19222     setIconClass : function(cls){
19223         if(this.el){
19224             this.el.child(this.buttonSelector).replaceClass(this.iconCls, cls);
19225         }
19226         this.iconCls = cls;
19227     },
19228
19229         beforeDestroy: function(){
19230         if(this.rendered){
19231                 var btn = this.el.child(this.buttonSelector);
19232                 if(btn){
19233                     btn.removeAllListeners();
19234                 }
19235             }
19236         if(this.menu){
19237             Ext.destroy(this.menu);
19238         }
19239     },
19240
19241         onDestroy : function(){
19242         if(this.rendered){
19243             Ext.ButtonToggleMgr.unregister(this);
19244         }
19245     },
19246
19247         autoWidth : function(){
19248         if(this.el){
19249             this.el.setWidth("auto");
19250             if(Ext.isIE7 && Ext.isStrict){
19251                 var ib = this.el.child(this.buttonSelector);
19252                 if(ib && ib.getWidth() > 20){
19253                     ib.clip();
19254                     ib.setWidth(Ext.util.TextMetrics.measure(ib, this.text).width+ib.getFrameWidth('lr'));
19255                 }
19256             }
19257             if(this.minWidth){
19258                 if(this.el.getWidth() < this.minWidth){
19259                     this.el.setWidth(this.minWidth);
19260                 }
19261             }
19262         }
19263     },
19264
19265     
19266     setHandler : function(handler, scope){
19267         this.handler = handler;
19268         this.scope = scope;
19269     },
19270
19271     
19272     setText : function(text){
19273         this.text = text;
19274         if(this.el){
19275             this.el.child("td.x-btn-center " + this.buttonSelector).update(text);
19276         }
19277         this.autoWidth();
19278     },
19279
19280     
19281     getText : function(){
19282         return this.text;
19283     },
19284
19285     
19286     toggle : function(state){
19287         state = state === undefined ? !this.pressed : state;
19288         if(state != this.pressed){
19289             if(state){
19290                 this.el.addClass("x-btn-pressed");
19291                 this.pressed = true;
19292                 this.fireEvent("toggle", this, true);
19293             }else{
19294                 this.el.removeClass("x-btn-pressed");
19295                 this.pressed = false;
19296                 this.fireEvent("toggle", this, false);
19297             }
19298             if(this.toggleHandler){
19299                 this.toggleHandler.call(this.scope || this, this, state);
19300             }
19301         }
19302     },
19303
19304     
19305     focus : function(){
19306         this.el.child(this.buttonSelector).focus();
19307     },
19308
19309         onDisable : function(){
19310         if(this.el){
19311             if(!Ext.isIE6 || !this.text){
19312                 this.el.addClass(this.disabledClass);
19313             }
19314             this.el.dom.disabled = true;
19315         }
19316         this.disabled = true;
19317     },
19318
19319         onEnable : function(){
19320         if(this.el){
19321             if(!Ext.isIE6 || !this.text){
19322                 this.el.removeClass(this.disabledClass);
19323             }
19324             this.el.dom.disabled = false;
19325         }
19326         this.disabled = false;
19327     },
19328
19329     
19330     showMenu : function(){
19331         if(this.menu){
19332             this.menu.show(this.el, this.menuAlign);
19333         }
19334         return this;
19335     },
19336
19337     
19338     hideMenu : function(){
19339         if(this.menu){
19340             this.menu.hide();
19341         }
19342         return this;
19343     },
19344
19345     
19346     hasVisibleMenu : function(){
19347         return this.menu && this.menu.isVisible();
19348     },
19349
19350         onClick : function(e){
19351         if(e){
19352             e.preventDefault();
19353         }
19354         if(e.button != 0){
19355             return;
19356         }
19357         if(!this.disabled){
19358             if(this.enableToggle && (this.allowDepress !== false || !this.pressed)){
19359                 this.toggle();
19360             }
19361             if(this.menu && !this.menu.isVisible() && !this.ignoreNextClick){
19362                 this.showMenu();
19363             }
19364             this.fireEvent("click", this, e);
19365             if(this.handler){
19366                                 this.handler.call(this.scope || this, this, e);
19367             }
19368         }
19369     },
19370
19371         isMenuTriggerOver : function(e, internal){
19372         return this.menu && !internal;
19373     },
19374
19375         isMenuTriggerOut : function(e, internal){
19376         return this.menu && !internal;
19377     },
19378
19379         onMouseOver : function(e){
19380         if(!this.disabled){
19381             var internal = e.within(this.el,  true);
19382             if(!internal){
19383                 this.el.addClass("x-btn-over");
19384                 Ext.getDoc().on('mouseover', this.monitorMouseOver, this);
19385                 this.fireEvent('mouseover', this, e);
19386             }
19387             if(this.isMenuTriggerOver(e, internal)){
19388                 this.fireEvent('menutriggerover', this, this.menu, e);
19389             }
19390         }
19391     },
19392
19393         monitorMouseOver : function(e){
19394         if(e.target != this.el.dom && !e.within(this.el)){
19395             Ext.getDoc().un('mouseover', this.monitorMouseOver, this);
19396             this.onMouseOut(e);
19397         }
19398     },
19399
19400         onMouseOut : function(e){
19401         var internal = e.within(this.el) && e.target != this.el.dom;
19402         this.el.removeClass("x-btn-over");
19403         this.fireEvent('mouseout', this, e);
19404         if(this.isMenuTriggerOut(e, internal)){
19405             this.fireEvent('menutriggerout', this, this.menu, e);
19406         }
19407     },
19408         onFocus : function(e){
19409         if(!this.disabled){
19410             this.el.addClass("x-btn-focus");
19411         }
19412     },
19413         onBlur : function(e){
19414         this.el.removeClass("x-btn-focus");
19415     },
19416
19417         getClickEl : function(e, isUp){
19418        return this.el;
19419     },
19420
19421         onMouseDown : function(e){
19422         if(!this.disabled && e.button == 0){
19423             this.getClickEl(e).addClass("x-btn-click");
19424             Ext.getDoc().on('mouseup', this.onMouseUp, this);
19425         }
19426     },
19427         onMouseUp : function(e){
19428         if(e.button == 0){
19429             this.getClickEl(e, true).removeClass("x-btn-click");
19430             Ext.getDoc().un('mouseup', this.onMouseUp, this);
19431         }
19432     },
19433         onMenuShow : function(e){
19434         this.ignoreNextClick = 0;
19435         this.el.addClass("x-btn-menu-active");
19436         this.fireEvent('menushow', this, this.menu);
19437     },
19438         onMenuHide : function(e){
19439         this.el.removeClass("x-btn-menu-active");
19440         this.ignoreNextClick = this.restoreClick.defer(250, this);
19441         this.fireEvent('menuhide', this, this.menu);
19442     },
19443
19444         restoreClick : function(){
19445         this.ignoreNextClick = 0;
19446     }
19447
19448
19449
19450     
19451 });
19452 Ext.reg('button', Ext.Button);
19453
19454 Ext.ButtonToggleMgr = function(){
19455    var groups = {};
19456
19457    function toggleGroup(btn, state){
19458        if(state){
19459            var g = groups[btn.toggleGroup];
19460            for(var i = 0, l = g.length; i < l; i++){
19461                if(g[i] != btn){
19462                    g[i].toggle(false);
19463                }
19464            }
19465        }
19466    }
19467
19468    return {
19469        register : function(btn){
19470            if(!btn.toggleGroup){
19471                return;
19472            }
19473            var g = groups[btn.toggleGroup];
19474            if(!g){
19475                g = groups[btn.toggleGroup] = [];
19476            }
19477            g.push(btn);
19478            btn.on("toggle", toggleGroup);
19479        },
19480
19481        unregister : function(btn){
19482            if(!btn.toggleGroup){
19483                return;
19484            }
19485            var g = groups[btn.toggleGroup];
19486            if(g){
19487                g.remove(btn);
19488                btn.un("toggle", toggleGroup);
19489            }
19490        }
19491    };
19492 }();
19493
19494 Ext.SplitButton = Ext.extend(Ext.Button, {
19495         
19496     arrowSelector : 'button:last',
19497
19498     
19499     initComponent : function(){
19500         Ext.SplitButton.superclass.initComponent.call(this);
19501         
19502         this.addEvents("arrowclick");
19503     },
19504
19505     
19506     onRender : function(ct, position){
19507         
19508         var tpl = new Ext.Template(
19509             '<table cellspacing="0" class="x-btn-menu-wrap x-btn"><tr><td>',
19510             '<table cellspacing="0" class="x-btn-wrap x-btn-menu-text-wrap"><tbody>',
19511             '<tr><td class="x-btn-left"><i>&#160;</i></td><td class="x-btn-center"><button class="x-btn-text" type="{1}">{0}</button></td></tr>',
19512             "</tbody></table></td><td>",
19513             '<table cellspacing="0" class="x-btn-wrap x-btn-menu-arrow-wrap"><tbody>',
19514             '<tr><td class="x-btn-center"><button class="x-btn-menu-arrow-el" type="button">&#160;</button></td><td class="x-btn-right"><i>&#160;</i></td></tr>',
19515             "</tbody></table></td></tr></table>"
19516         );
19517         var btn, targs = [this.text || '&#160;', this.type];
19518         if(position){
19519             btn = tpl.insertBefore(position, targs, true);
19520         }else{
19521             btn = tpl.append(ct, targs, true);
19522         }
19523         var btnEl = btn.child(this.buttonSelector);
19524
19525         this.initButtonEl(btn, btnEl);
19526         this.arrowBtnTable = btn.child("table:last");
19527         if(this.arrowTooltip){
19528             btn.child(this.arrowSelector).dom[this.tooltipType] = this.arrowTooltip;
19529         }
19530     },
19531
19532     
19533     autoWidth : function(){
19534         if(this.el){
19535             var tbl = this.el.child("table:first");
19536             var tbl2 = this.el.child("table:last");
19537             this.el.setWidth("auto");
19538             tbl.setWidth("auto");
19539             if(Ext.isIE7 && Ext.isStrict){
19540                 var ib = this.el.child(this.buttonSelector);
19541                 if(ib && ib.getWidth() > 20){
19542                     ib.clip();
19543                     ib.setWidth(Ext.util.TextMetrics.measure(ib, this.text).width+ib.getFrameWidth('lr'));
19544                 }
19545             }
19546             if(this.minWidth){
19547                 if((tbl.getWidth()+tbl2.getWidth()) < this.minWidth){
19548                     tbl.setWidth(this.minWidth-tbl2.getWidth());
19549                 }
19550             }
19551             this.el.setWidth(tbl.getWidth()+tbl2.getWidth());
19552         } 
19553     },
19554
19555     
19556     setArrowHandler : function(handler, scope){
19557         this.arrowHandler = handler;
19558         this.scope = scope;  
19559     },
19560
19561     
19562     onClick : function(e){
19563         e.preventDefault();
19564         if(!this.disabled){
19565             if(e.getTarget(".x-btn-menu-arrow-wrap")){
19566                 if(this.menu && !this.menu.isVisible() && !this.ignoreNextClick){
19567                     this.showMenu();
19568                 }
19569                 this.fireEvent("arrowclick", this, e);
19570                 if(this.arrowHandler){
19571                     this.arrowHandler.call(this.scope || this, this, e);
19572                 }
19573             }else{
19574                 if(this.enableToggle){
19575                     this.toggle();
19576                 }
19577                 this.fireEvent("click", this, e);
19578                 if(this.handler){
19579                     this.handler.call(this.scope || this, this, e);
19580                 }
19581             }
19582         }
19583     },
19584
19585     
19586     getClickEl : function(e, isUp){
19587         if(!isUp){
19588             return (this.lastClickEl = e.getTarget("table", 10, true));
19589         }
19590         return this.lastClickEl;
19591     },
19592
19593     
19594     onDisable : function(){
19595         if(this.el){
19596             if(!Ext.isIE6){
19597                 this.el.addClass("x-item-disabled");
19598             }
19599             this.el.child(this.buttonSelector).dom.disabled = true;
19600             this.el.child(this.arrowSelector).dom.disabled = true;
19601         }
19602         this.disabled = true;
19603     },
19604
19605     
19606     onEnable : function(){
19607         if(this.el){
19608             if(!Ext.isIE6){
19609                 this.el.removeClass("x-item-disabled");
19610             }
19611             this.el.child(this.buttonSelector).dom.disabled = false;
19612             this.el.child(this.arrowSelector).dom.disabled = false;
19613         }
19614         this.disabled = false;
19615     },
19616
19617     
19618     isMenuTriggerOver : function(e){
19619         return this.menu && e.within(this.arrowBtnTable) && !e.within(this.arrowBtnTable, true);
19620     },
19621
19622     
19623     isMenuTriggerOut : function(e, internal){
19624         return this.menu && !e.within(this.arrowBtnTable);
19625     },
19626
19627     
19628     onDestroy : function(){
19629         Ext.destroy(this.arrowBtnTable);
19630         Ext.SplitButton.superclass.onDestroy.call(this);
19631     }
19632 });
19633
19634
19635 Ext.MenuButton = Ext.SplitButton;
19636
19637
19638 Ext.reg('splitbutton', Ext.SplitButton);
19639
19640 Ext.CycleButton = Ext.extend(Ext.SplitButton, {
19641     
19642     
19643     
19644     
19645
19646     
19647     getItemText : function(item){
19648         if(item && this.showText === true){
19649             var text = '';
19650             if(this.prependText){
19651                 text += this.prependText;
19652             }
19653             text += item.text;
19654             return text;
19655         }
19656         return undefined;
19657     },
19658
19659     
19660     setActiveItem : function(item, suppressEvent){
19661         if(typeof item != 'object'){
19662             item = this.menu.items.get(item);
19663         }
19664         if(item){
19665             if(!this.rendered){
19666                 this.text = this.getItemText(item);
19667                 this.iconCls = item.iconCls;
19668             }else{
19669                 var t = this.getItemText(item);
19670                 if(t){
19671                     this.setText(t);
19672                 }
19673                 this.setIconClass(item.iconCls);
19674             }
19675             this.activeItem = item;
19676             if(!item.checked){
19677                 item.setChecked(true, true);
19678             }
19679             if(this.forceIcon){
19680                 this.setIconClass(this.forceIcon);
19681             }
19682             if(!suppressEvent){
19683                 this.fireEvent('change', this, item);
19684             }
19685         }
19686     },
19687
19688     
19689     getActiveItem : function(){
19690         return this.activeItem;
19691     },
19692
19693     
19694     initComponent : function(){
19695         this.addEvents(
19696             
19697             "change"
19698         );
19699
19700         if(this.changeHandler){
19701             this.on('change', this.changeHandler, this.scope||this);
19702             delete this.changeHandler;
19703         }
19704
19705         this.itemCount = this.items.length;
19706
19707         this.menu = {cls:'x-cycle-menu', items:[]};
19708         var checked;
19709         for(var i = 0, len = this.itemCount; i < len; i++){
19710             var item = this.items[i];
19711             item.group = item.group || this.id;
19712             item.itemIndex = i;
19713             item.checkHandler = this.checkHandler;
19714             item.scope = this;
19715             item.checked = item.checked || false;
19716             this.menu.items.push(item);
19717             if(item.checked){
19718                 checked = item;
19719             }
19720         }
19721         this.setActiveItem(checked, true);
19722         Ext.CycleButton.superclass.initComponent.call(this);
19723
19724         this.on('click', this.toggleSelected, this);
19725     },
19726
19727     
19728     checkHandler : function(item, pressed){
19729         if(pressed){
19730             this.setActiveItem(item);
19731         }
19732     },
19733
19734     
19735     toggleSelected : function(){
19736         this.menu.render();
19737                 
19738                 var nextIdx, checkItem;
19739                 for (var i = 1; i < this.itemCount; i++) {
19740                         nextIdx = (this.activeItem.itemIndex + i) % this.itemCount;
19741                         
19742                         checkItem = this.menu.items.itemAt(nextIdx);
19743                         
19744                         if (!checkItem.disabled) {
19745                                 checkItem.setChecked(true);
19746                                 break;
19747                         }
19748                 }
19749     }
19750 });
19751 Ext.reg('cycle', Ext.CycleButton);
19752  
19753  Ext.Toolbar = function(config){
19754     if(Ext.isArray(config)){
19755         config = {buttons:config};
19756     }
19757     Ext.Toolbar.superclass.constructor.call(this, config);
19758 };
19759
19760 (function(){
19761
19762 var T = Ext.Toolbar;
19763
19764 Ext.extend(T, Ext.BoxComponent, {
19765
19766     trackMenus : true,
19767
19768     
19769     initComponent : function(){
19770         T.superclass.initComponent.call(this);
19771
19772         if(this.items){
19773             this.buttons = this.items;
19774         }
19775         
19776         this.items = new Ext.util.MixedCollection(false, function(o){
19777             return o.itemId || o.id || Ext.id();
19778         });
19779     },
19780
19781     
19782     autoCreate: {
19783         cls:'x-toolbar x-small-editor',
19784         html:'<table cellspacing="0"><tr></tr></table>'
19785     },
19786
19787     
19788     onRender : function(ct, position){
19789         this.el = ct.createChild(Ext.apply({ id: this.id },this.autoCreate), position);
19790         this.tr = this.el.child("tr", true);
19791     },
19792
19793     
19794     afterRender : function(){
19795         T.superclass.afterRender.call(this);
19796         if(this.buttons){
19797             this.add.apply(this, this.buttons);
19798             delete this.buttons;
19799         }
19800     },
19801
19802     
19803     add : function(){
19804         var a = arguments, l = a.length;
19805         for(var i = 0; i < l; i++){
19806             var el = a[i];
19807             if(el.isFormField){ 
19808                 this.addField(el);
19809             }else if(el.render){ 
19810                 this.addItem(el);
19811             }else if(typeof el == "string"){ 
19812                 if(el == "separator" || el == "-"){
19813                     this.addSeparator();
19814                 }else if(el == " "){
19815                     this.addSpacer();
19816                 }else if(el == "->"){
19817                     this.addFill();
19818                 }else{
19819                     this.addText(el);
19820                 }
19821             }else if(el.tagName){ 
19822                 this.addElement(el);
19823             }else if(typeof el == "object"){ 
19824                 if(el.xtype){
19825                     this.addField(Ext.ComponentMgr.create(el, 'button'));
19826                 }else{
19827                     this.addButton(el);
19828                 }
19829             }
19830         }
19831     },
19832     
19833     
19834     addSeparator : function(){
19835         return this.addItem(new T.Separator());
19836     },
19837
19838     
19839     addSpacer : function(){
19840         return this.addItem(new T.Spacer());
19841     },
19842
19843     
19844     addFill : function(){
19845         return this.addItem(new T.Fill());
19846     },
19847
19848     
19849     addElement : function(el){
19850         return this.addItem(new T.Item(el));
19851     },
19852     
19853     
19854     addItem : function(item){
19855         var td = this.nextBlock();
19856         this.initMenuTracking(item);
19857         item.render(td);
19858         this.items.add(item);
19859         return item;
19860     },
19861     
19862     
19863     addButton : function(config){
19864         if(Ext.isArray(config)){
19865             var buttons = [];
19866             for(var i = 0, len = config.length; i < len; i++) {
19867                 buttons.push(this.addButton(config[i]));
19868             }
19869             return buttons;
19870         }
19871         var b = config;
19872         if(!(config instanceof T.Button)){
19873             b = config.split ? 
19874                 new T.SplitButton(config) :
19875                 new T.Button(config);
19876         }
19877         var td = this.nextBlock();
19878         this.initMenuTracking(b);
19879         b.render(td);
19880         this.items.add(b);
19881         return b;
19882     },
19883
19884     
19885     initMenuTracking : function(item){
19886         if(this.trackMenus && item.menu){
19887             item.on({
19888                 'menutriggerover' : this.onButtonTriggerOver,
19889                 'menushow' : this.onButtonMenuShow,
19890                 'menuhide' : this.onButtonMenuHide,
19891                 scope: this
19892             })
19893         }
19894     },
19895
19896     
19897     addText : function(text){
19898         return this.addItem(new T.TextItem(text));
19899     },
19900     
19901     
19902     insertButton : function(index, item){
19903         if(Ext.isArray(item)){
19904             var buttons = [];
19905             for(var i = 0, len = item.length; i < len; i++) {
19906                buttons.push(this.insertButton(index + i, item[i]));
19907             }
19908             return buttons;
19909         }
19910         if (!(item instanceof T.Button)){
19911            item = new T.Button(item);
19912         }
19913         var td = document.createElement("td");
19914         this.tr.insertBefore(td, this.tr.childNodes[index]);
19915         this.initMenuTracking(item);
19916         item.render(td);
19917         this.items.insert(index, item);
19918         return item;
19919     },
19920     
19921     
19922     addDom : function(config, returnEl){
19923         var td = this.nextBlock();
19924         Ext.DomHelper.overwrite(td, config);
19925         var ti = new T.Item(td.firstChild);
19926         ti.render(td);
19927         this.items.add(ti);
19928         return ti;
19929     },
19930
19931     
19932     addField : function(field){
19933         var td = this.nextBlock();
19934         field.render(td);
19935         var ti = new T.Item(td.firstChild);
19936         ti.render(td);
19937         this.items.add(ti);
19938         return ti;
19939     },
19940
19941     
19942     nextBlock : function(){
19943         var td = document.createElement("td");
19944         this.tr.appendChild(td);
19945         return td;
19946     },
19947
19948     
19949     onDestroy : function(){
19950         Ext.Toolbar.superclass.onDestroy.call(this);
19951         if(this.rendered){
19952             if(this.items){ 
19953                 Ext.destroy.apply(Ext, this.items.items);
19954             }
19955             Ext.Element.uncache(this.tr);
19956         }
19957     },
19958
19959     
19960     onDisable : function(){
19961         this.items.each(function(item){
19962              if(item.disable){
19963                  item.disable();
19964              }
19965         });
19966     },
19967
19968     
19969     onEnable : function(){
19970         this.items.each(function(item){
19971              if(item.enable){
19972                  item.enable();
19973              }
19974         });
19975     },
19976
19977     
19978     onButtonTriggerOver : function(btn){
19979         if(this.activeMenuBtn && this.activeMenuBtn != btn){
19980             this.activeMenuBtn.hideMenu();
19981             btn.showMenu();
19982             this.activeMenuBtn = btn;
19983         }
19984     },
19985
19986     
19987     onButtonMenuShow : function(btn){
19988         this.activeMenuBtn = btn;
19989     },
19990
19991     
19992     onButtonMenuHide : function(btn){
19993         delete this.activeMenuBtn;
19994     }
19995
19996     
19997 });
19998 Ext.reg('toolbar', Ext.Toolbar);
19999
20000
20001 T.Item = function(el){
20002     this.el = Ext.getDom(el);
20003     this.id = Ext.id(this.el);
20004     this.hidden = false;
20005 };
20006
20007 T.Item.prototype = {
20008     
20009     
20010     getEl : function(){
20011        return this.el;  
20012     },
20013
20014     
20015     render : function(td){
20016         this.td = td;
20017         td.appendChild(this.el);
20018     },
20019     
20020     
20021     destroy : function(){
20022         if(this.td && this.td.parentNode){
20023             this.td.parentNode.removeChild(this.td);
20024         }
20025     },
20026     
20027     
20028     show: function(){
20029         this.hidden = false;
20030         this.td.style.display = "";
20031     },
20032     
20033     
20034     hide: function(){
20035         this.hidden = true;
20036         this.td.style.display = "none";
20037     },
20038     
20039     
20040     setVisible: function(visible){
20041         if(visible) {
20042             this.show();
20043         }else{
20044             this.hide();
20045         }
20046     },
20047     
20048     
20049     focus : function(){
20050         Ext.fly(this.el).focus();
20051     },
20052     
20053     
20054     disable : function(){
20055         Ext.fly(this.td).addClass("x-item-disabled");
20056         this.disabled = true;
20057         this.el.disabled = true;
20058     },
20059     
20060     
20061     enable : function(){
20062         Ext.fly(this.td).removeClass("x-item-disabled");
20063         this.disabled = false;
20064         this.el.disabled = false;
20065     }
20066 };
20067 Ext.reg('tbitem', T.Item);
20068
20069
20070
20071 T.Separator = function(){
20072     var s = document.createElement("span");
20073     s.className = "xtb-sep";
20074     T.Separator.superclass.constructor.call(this, s);
20075 };
20076 Ext.extend(T.Separator, T.Item, {
20077     enable:Ext.emptyFn,
20078     disable:Ext.emptyFn,
20079     focus:Ext.emptyFn
20080 });
20081 Ext.reg('tbseparator', T.Separator);
20082
20083
20084 T.Spacer = function(){
20085     var s = document.createElement("div");
20086     s.className = "xtb-spacer";
20087     T.Spacer.superclass.constructor.call(this, s);
20088 };
20089 Ext.extend(T.Spacer, T.Item, {
20090     enable:Ext.emptyFn,
20091     disable:Ext.emptyFn,
20092     focus:Ext.emptyFn
20093 });
20094
20095 Ext.reg('tbspacer', T.Spacer);
20096
20097
20098 T.Fill = Ext.extend(T.Spacer, {
20099     
20100     render : function(td){
20101         td.style.width = '100%';
20102         T.Fill.superclass.render.call(this, td);
20103     }
20104 });
20105 Ext.reg('tbfill', T.Fill);
20106
20107
20108 T.TextItem = function(t){
20109     var s = document.createElement("span");
20110     s.className = "xtb-text";
20111     s.innerHTML = t.text ? t.text : t;
20112     T.TextItem.superclass.constructor.call(this, s);
20113 };
20114 Ext.extend(T.TextItem, T.Item, {
20115     enable:Ext.emptyFn,
20116     disable:Ext.emptyFn,
20117     focus:Ext.emptyFn
20118 });
20119 Ext.reg('tbtext', T.TextItem);
20120
20121
20122
20123 T.Button = Ext.extend(Ext.Button, {
20124     hideParent : true,
20125
20126     onDestroy : function(){
20127         T.Button.superclass.onDestroy.call(this);
20128         if(this.container){
20129             this.container.remove();
20130         }
20131     }
20132 });
20133 Ext.reg('tbbutton', T.Button);
20134
20135
20136 T.SplitButton = Ext.extend(Ext.SplitButton, {
20137     hideParent : true,
20138
20139     onDestroy : function(){
20140         T.SplitButton.superclass.onDestroy.call(this);
20141         if(this.container){
20142             this.container.remove();
20143         }
20144     }
20145 });
20146
20147 Ext.reg('tbsplit', T.SplitButton);
20148
20149 T.MenuButton = T.SplitButton;
20150
20151 })();
20152
20153
20154 Ext.PagingToolbar = Ext.extend(Ext.Toolbar, {
20155     
20156     
20157     
20158     pageSize: 20,
20159     
20160     displayMsg : 'Displaying {0} - {1} of {2}',
20161     
20162     emptyMsg : 'No data to display',
20163     
20164     beforePageText : "Page",
20165     
20166     afterPageText : "of {0}",
20167     
20168     firstText : "First Page",
20169     
20170     prevText : "Previous Page",
20171     
20172     nextText : "Next Page",
20173     
20174     lastText : "Last Page",
20175     
20176     refreshText : "Refresh",
20177
20178     
20179     paramNames : {start: 'start', limit: 'limit'},
20180
20181     initComponent : function(){
20182         Ext.PagingToolbar.superclass.initComponent.call(this);
20183         this.cursor = 0;
20184         this.bind(this.store);
20185     },
20186
20187         onRender : function(ct, position){
20188         Ext.PagingToolbar.superclass.onRender.call(this, ct, position);
20189         this.first = this.addButton({
20190             tooltip: this.firstText,
20191             iconCls: "x-tbar-page-first",
20192             disabled: true,
20193             handler: this.onClick.createDelegate(this, ["first"])
20194         });
20195         this.prev = this.addButton({
20196             tooltip: this.prevText,
20197             iconCls: "x-tbar-page-prev",
20198             disabled: true,
20199             handler: this.onClick.createDelegate(this, ["prev"])
20200         });
20201         this.addSeparator();
20202         this.add(this.beforePageText);
20203         this.field = Ext.get(this.addDom({
20204            tag: "input",
20205            type: "text",
20206            size: "3",
20207            value: "1",
20208            cls: "x-tbar-page-number"
20209         }).el);
20210         this.field.on("keydown", this.onPagingKeydown, this);
20211         this.field.on("focus", function(){this.dom.select();});
20212         this.afterTextEl = this.addText(String.format(this.afterPageText, 1));
20213         this.field.setHeight(18);
20214         this.addSeparator();
20215         this.next = this.addButton({
20216             tooltip: this.nextText,
20217             iconCls: "x-tbar-page-next",
20218             disabled: true,
20219             handler: this.onClick.createDelegate(this, ["next"])
20220         });
20221         this.last = this.addButton({
20222             tooltip: this.lastText,
20223             iconCls: "x-tbar-page-last",
20224             disabled: true,
20225             handler: this.onClick.createDelegate(this, ["last"])
20226         });
20227         this.addSeparator();
20228         this.loading = this.addButton({
20229             tooltip: this.refreshText,
20230             iconCls: "x-tbar-loading",
20231             handler: this.onClick.createDelegate(this, ["refresh"])
20232         });
20233
20234         if(this.displayInfo){
20235             this.displayEl = Ext.fly(this.el.dom).createChild({cls:'x-paging-info'});
20236         }
20237         if(this.dsLoaded){
20238             this.onLoad.apply(this, this.dsLoaded);
20239         }
20240     },
20241
20242         updateInfo : function(){
20243         if(this.displayEl){
20244             var count = this.store.getCount();
20245             var msg = count == 0 ?
20246                 this.emptyMsg :
20247                 String.format(
20248                     this.displayMsg,
20249                     this.cursor+1, this.cursor+count, this.store.getTotalCount()
20250                 );
20251             this.displayEl.update(msg);
20252         }
20253     },
20254
20255         onLoad : function(store, r, o){
20256         if(!this.rendered){
20257             this.dsLoaded = [store, r, o];
20258             return;
20259         }
20260        this.cursor = o.params ? o.params[this.paramNames.start] : 0;
20261        var d = this.getPageData(), ap = d.activePage, ps = d.pages;
20262
20263        this.afterTextEl.el.innerHTML = String.format(this.afterPageText, d.pages);
20264        this.field.dom.value = ap;
20265        this.first.setDisabled(ap == 1);
20266        this.prev.setDisabled(ap == 1);
20267        this.next.setDisabled(ap == ps);
20268        this.last.setDisabled(ap == ps);
20269        this.loading.enable();
20270        this.updateInfo();
20271     },
20272
20273         getPageData : function(){
20274         var total = this.store.getTotalCount();
20275         return {
20276             total : total,
20277             activePage : Math.ceil((this.cursor+this.pageSize)/this.pageSize),
20278             pages :  total < this.pageSize ? 1 : Math.ceil(total/this.pageSize)
20279         };
20280     },
20281
20282         onLoadError : function(){
20283         if(!this.rendered){
20284             return;
20285         }
20286         this.loading.enable();
20287     },
20288
20289     readPage : function(d){
20290         var v = this.field.dom.value, pageNum;
20291         if (!v || isNaN(pageNum = parseInt(v, 10))) {
20292             this.field.dom.value = d.activePage;
20293             return false;
20294         }
20295         return pageNum;
20296     },
20297
20298         onPagingKeydown : function(e){
20299         var k = e.getKey(), d = this.getPageData(), pageNum;
20300         if (k == e.RETURN) {
20301             e.stopEvent();
20302             if(pageNum = this.readPage(d)){
20303                 pageNum = Math.min(Math.max(1, pageNum), d.pages) - 1;
20304                 this.doLoad(pageNum * this.pageSize);
20305             }
20306         }else if (k == e.HOME || k == e.END){
20307             e.stopEvent();
20308             pageNum = k == e.HOME ? 1 : d.pages;
20309             this.field.dom.value = pageNum;
20310         }else if (k == e.UP || k == e.PAGEUP || k == e.DOWN || k == e.PAGEDOWN){
20311             e.stopEvent();
20312             if(pageNum = this.readPage(d)){
20313                 var increment = e.shiftKey ? 10 : 1;
20314                 if(k == e.DOWN || k == e.PAGEDOWN){
20315                     increment *= -1;
20316                 }
20317                 pageNum += increment;
20318                 if(pageNum >= 1 & pageNum <= d.pages){
20319                     this.field.dom.value = pageNum;
20320                 }
20321             }
20322         }
20323     },
20324
20325         beforeLoad : function(){
20326         if(this.rendered && this.loading){
20327             this.loading.disable();
20328         }
20329     },
20330
20331     doLoad : function(start){
20332         var o = {}, pn = this.paramNames;
20333         o[pn.start] = start;
20334         o[pn.limit] = this.pageSize;
20335         this.store.load({params:o});
20336     },
20337
20338         onClick : function(which){
20339         var store = this.store;
20340         switch(which){
20341             case "first":
20342                 this.doLoad(0);
20343             break;
20344             case "prev":
20345                 this.doLoad(Math.max(0, this.cursor-this.pageSize));
20346             break;
20347             case "next":
20348                 this.doLoad(this.cursor+this.pageSize);
20349             break;
20350             case "last":
20351                 var total = store.getTotalCount();
20352                 var extra = total % this.pageSize;
20353                 var lastStart = extra ? (total - extra) : total-this.pageSize;
20354                 this.doLoad(lastStart);
20355             break;
20356             case "refresh":
20357                 this.doLoad(this.cursor);
20358             break;
20359         }
20360     },
20361
20362     
20363     unbind : function(store){
20364         store = Ext.StoreMgr.lookup(store);
20365         store.un("beforeload", this.beforeLoad, this);
20366         store.un("load", this.onLoad, this);
20367         store.un("loadexception", this.onLoadError, this);
20368         this.store = undefined;
20369     },
20370
20371     
20372     bind : function(store){
20373         store = Ext.StoreMgr.lookup(store);
20374         store.on("beforeload", this.beforeLoad, this);
20375         store.on("load", this.onLoad, this);
20376         store.on("loadexception", this.onLoadError, this);
20377         this.store = store;
20378     }
20379 });
20380 Ext.reg('paging', Ext.PagingToolbar);
20381
20382 Ext.Resizable = function(el, config){
20383     this.el = Ext.get(el);
20384     
20385     if(config && config.wrap){
20386         config.resizeChild = this.el;
20387         this.el = this.el.wrap(typeof config.wrap == "object" ? config.wrap : {cls:"xresizable-wrap"});
20388         this.el.id = this.el.dom.id = config.resizeChild.id + "-rzwrap";
20389         this.el.setStyle("overflow", "hidden");
20390         this.el.setPositioning(config.resizeChild.getPositioning());
20391         config.resizeChild.clearPositioning();
20392         if(!config.width || !config.height){
20393             var csize = config.resizeChild.getSize();
20394             this.el.setSize(csize.width, csize.height);
20395         }
20396         if(config.pinned && !config.adjustments){
20397             config.adjustments = "auto";
20398         }
20399     }
20400
20401     this.proxy = this.el.createProxy({tag: "div", cls: "x-resizable-proxy", id: this.el.id + "-rzproxy"});
20402     this.proxy.unselectable();
20403     this.proxy.enableDisplayMode('block');
20404
20405     Ext.apply(this, config);
20406     
20407     if(this.pinned){
20408         this.disableTrackOver = true;
20409         this.el.addClass("x-resizable-pinned");
20410     }
20411     
20412     var position = this.el.getStyle("position");
20413     if(position != "absolute" && position != "fixed"){
20414         this.el.setStyle("position", "relative");
20415     }
20416     if(!this.handles){ 
20417         this.handles = 's,e,se';
20418         if(this.multiDirectional){
20419             this.handles += ',n,w';
20420         }
20421     }
20422     if(this.handles == "all"){
20423         this.handles = "n s e w ne nw se sw";
20424     }
20425     var hs = this.handles.split(/\s*?[,;]\s*?| /);
20426     var ps = Ext.Resizable.positions;
20427     for(var i = 0, len = hs.length; i < len; i++){
20428         if(hs[i] && ps[hs[i]]){
20429             var pos = ps[hs[i]];
20430             this[pos] = new Ext.Resizable.Handle(this, pos, this.disableTrackOver, this.transparent);
20431         }
20432     }
20433     
20434     this.corner = this.southeast;
20435     
20436     if(this.handles.indexOf("n") != -1 || this.handles.indexOf("w") != -1){
20437         this.updateBox = true;
20438     }   
20439    
20440     this.activeHandle = null;
20441     
20442     if(this.resizeChild){
20443         if(typeof this.resizeChild == "boolean"){
20444             this.resizeChild = Ext.get(this.el.dom.firstChild, true);
20445         }else{
20446             this.resizeChild = Ext.get(this.resizeChild, true);
20447         }
20448     }
20449     
20450     if(this.adjustments == "auto"){
20451         var rc = this.resizeChild;
20452         var hw = this.west, he = this.east, hn = this.north, hs = this.south;
20453         if(rc && (hw || hn)){
20454             rc.position("relative");
20455             rc.setLeft(hw ? hw.el.getWidth() : 0);
20456             rc.setTop(hn ? hn.el.getHeight() : 0);
20457         }
20458         this.adjustments = [
20459             (he ? -he.el.getWidth() : 0) + (hw ? -hw.el.getWidth() : 0),
20460             (hn ? -hn.el.getHeight() : 0) + (hs ? -hs.el.getHeight() : 0) -1 
20461         ];
20462     }
20463     
20464     if(this.draggable){
20465         this.dd = this.dynamic ? 
20466             this.el.initDD(null) : this.el.initDDProxy(null, {dragElId: this.proxy.id});
20467         this.dd.setHandleElId(this.resizeChild ? this.resizeChild.id : this.el.id);
20468     }
20469     
20470     
20471     this.addEvents(
20472         "beforeresize",
20473         "resize"
20474     );
20475     
20476     if(this.width !== null && this.height !== null){
20477         this.resizeTo(this.width, this.height);
20478     }else{
20479         this.updateChildSize();
20480     }
20481     if(Ext.isIE){
20482         this.el.dom.style.zoom = 1;
20483     }
20484     Ext.Resizable.superclass.constructor.call(this);
20485 };
20486
20487 Ext.extend(Ext.Resizable, Ext.util.Observable, {
20488         resizeChild : false,
20489         adjustments : [0, 0],
20490         minWidth : 5,
20491         minHeight : 5,
20492         maxWidth : 10000,
20493         maxHeight : 10000,
20494         enabled : true,
20495         animate : false,
20496         duration : .35,
20497         dynamic : false,
20498         handles : false,
20499         multiDirectional : false,
20500         disableTrackOver : false,
20501         easing : 'easeOutStrong',
20502         widthIncrement : 0,
20503         heightIncrement : 0,
20504         pinned : false,
20505         width : null,
20506         height : null,
20507         preserveRatio : false,
20508         transparent: false,
20509         minX: 0,
20510         minY: 0,
20511         draggable: false,
20512
20513         
20514         
20515
20516         
20517         
20518     
20519     
20520     resizeTo : function(width, height){
20521         this.el.setSize(width, height);
20522         this.updateChildSize();
20523         this.fireEvent("resize", this, width, height, null);
20524     },
20525
20526     
20527     startSizing : function(e, handle){
20528         this.fireEvent("beforeresize", this, e);
20529         if(this.enabled){ 
20530
20531             if(!this.overlay){
20532                 this.overlay = this.el.createProxy({tag: "div", cls: "x-resizable-overlay", html: "&#160;"}, Ext.getBody());
20533                 this.overlay.unselectable();
20534                 this.overlay.enableDisplayMode("block");
20535                 this.overlay.on("mousemove", this.onMouseMove, this);
20536                 this.overlay.on("mouseup", this.onMouseUp, this);
20537             }
20538             this.overlay.setStyle("cursor", handle.el.getStyle("cursor"));
20539
20540             this.resizing = true;
20541             this.startBox = this.el.getBox();
20542             this.startPoint = e.getXY();
20543             this.offsets = [(this.startBox.x + this.startBox.width) - this.startPoint[0],
20544                             (this.startBox.y + this.startBox.height) - this.startPoint[1]];
20545
20546             this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
20547             this.overlay.show();
20548
20549             if(this.constrainTo) {
20550                 var ct = Ext.get(this.constrainTo);
20551                 this.resizeRegion = ct.getRegion().adjust(
20552                     ct.getFrameWidth('t'),
20553                     ct.getFrameWidth('l'),
20554                     -ct.getFrameWidth('b'),
20555                     -ct.getFrameWidth('r')
20556                 );
20557             }
20558
20559             this.proxy.setStyle('visibility', 'hidden'); 
20560             this.proxy.show();
20561             this.proxy.setBox(this.startBox);
20562             if(!this.dynamic){
20563                 this.proxy.setStyle('visibility', 'visible');
20564             }
20565         }
20566     },
20567
20568     
20569     onMouseDown : function(handle, e){
20570         if(this.enabled){
20571             e.stopEvent();
20572             this.activeHandle = handle;
20573             this.startSizing(e, handle);
20574         }          
20575     },
20576
20577     
20578     onMouseUp : function(e){
20579         var size = this.resizeElement();
20580         this.resizing = false;
20581         this.handleOut();
20582         this.overlay.hide();
20583         this.proxy.hide();
20584         this.fireEvent("resize", this, size.width, size.height, e);
20585     },
20586
20587     
20588     updateChildSize : function(){
20589         if(this.resizeChild){
20590             var el = this.el;
20591             var child = this.resizeChild;
20592             var adj = this.adjustments;
20593             if(el.dom.offsetWidth){
20594                 var b = el.getSize(true);
20595                 child.setSize(b.width+adj[0], b.height+adj[1]);
20596             }
20597             
20598             
20599             
20600             
20601             if(Ext.isIE){
20602                 setTimeout(function(){
20603                     if(el.dom.offsetWidth){
20604                         var b = el.getSize(true);
20605                         child.setSize(b.width+adj[0], b.height+adj[1]);
20606                     }
20607                 }, 10);
20608             }
20609         }
20610     },
20611
20612     
20613     snap : function(value, inc, min){
20614         if(!inc || !value) return value;
20615         var newValue = value;
20616         var m = value % inc;
20617         if(m > 0){
20618             if(m > (inc/2)){
20619                 newValue = value + (inc-m);
20620             }else{
20621                 newValue = value - m;
20622             }
20623         }
20624         return Math.max(min, newValue);
20625     },
20626
20627     
20628     resizeElement : function(){
20629         var box = this.proxy.getBox();
20630         if(this.updateBox){
20631             this.el.setBox(box, false, this.animate, this.duration, null, this.easing);
20632         }else{
20633             this.el.setSize(box.width, box.height, this.animate, this.duration, null, this.easing);
20634         }
20635         this.updateChildSize();
20636         if(!this.dynamic){
20637             this.proxy.hide();
20638         }
20639         return box;
20640     },
20641
20642     
20643     constrain : function(v, diff, m, mx){
20644         if(v - diff < m){
20645             diff = v - m;    
20646         }else if(v - diff > mx){
20647             diff = mx - v; 
20648         }
20649         return diff;                
20650     },
20651
20652     
20653     onMouseMove : function(e){
20654         if(this.enabled){
20655             try{
20656
20657             if(this.resizeRegion && !this.resizeRegion.contains(e.getPoint())) {
20658                 return;
20659             }
20660
20661             
20662             var curSize = this.curSize || this.startBox;
20663             var x = this.startBox.x, y = this.startBox.y;
20664             var ox = x, oy = y;
20665             var w = curSize.width, h = curSize.height;
20666             var ow = w, oh = h;
20667             var mw = this.minWidth, mh = this.minHeight;
20668             var mxw = this.maxWidth, mxh = this.maxHeight;
20669             var wi = this.widthIncrement;
20670             var hi = this.heightIncrement;
20671             
20672             var eventXY = e.getXY();
20673             var diffX = -(this.startPoint[0] - Math.max(this.minX, eventXY[0]));
20674             var diffY = -(this.startPoint[1] - Math.max(this.minY, eventXY[1]));
20675             
20676             var pos = this.activeHandle.position;
20677             
20678             switch(pos){
20679                 case "east":
20680                     w += diffX; 
20681                     w = Math.min(Math.max(mw, w), mxw);
20682                     break;
20683                 case "south":
20684                     h += diffY;
20685                     h = Math.min(Math.max(mh, h), mxh);
20686                     break;
20687                 case "southeast":
20688                     w += diffX; 
20689                     h += diffY;
20690                     w = Math.min(Math.max(mw, w), mxw);
20691                     h = Math.min(Math.max(mh, h), mxh);
20692                     break;
20693                 case "north":
20694                     diffY = this.constrain(h, diffY, mh, mxh);
20695                     y += diffY;
20696                     h -= diffY;
20697                     break;
20698                 case "west":
20699                     diffX = this.constrain(w, diffX, mw, mxw);
20700                     x += diffX;
20701                     w -= diffX;
20702                     break;
20703                 case "northeast":
20704                     w += diffX; 
20705                     w = Math.min(Math.max(mw, w), mxw);
20706                     diffY = this.constrain(h, diffY, mh, mxh);
20707                     y += diffY;
20708                     h -= diffY;
20709                     break;
20710                 case "northwest":
20711                     diffX = this.constrain(w, diffX, mw, mxw);
20712                     diffY = this.constrain(h, diffY, mh, mxh);
20713                     y += diffY;
20714                     h -= diffY;
20715                     x += diffX;
20716                     w -= diffX;
20717                     break;
20718                case "southwest":
20719                     diffX = this.constrain(w, diffX, mw, mxw);
20720                     h += diffY;
20721                     h = Math.min(Math.max(mh, h), mxh);
20722                     x += diffX;
20723                     w -= diffX;
20724                     break;
20725             }
20726             
20727             var sw = this.snap(w, wi, mw);
20728             var sh = this.snap(h, hi, mh);
20729             if(sw != w || sh != h){
20730                 switch(pos){
20731                     case "northeast":
20732                         y -= sh - h;
20733                     break;
20734                     case "north":
20735                         y -= sh - h;
20736                         break;
20737                     case "southwest":
20738                         x -= sw - w;
20739                     break;
20740                     case "west":
20741                         x -= sw - w;
20742                         break;
20743                     case "northwest":
20744                         x -= sw - w;
20745                         y -= sh - h;
20746                     break;
20747                 }
20748                 w = sw;
20749                 h = sh;
20750             }
20751             
20752             if(this.preserveRatio){
20753                 switch(pos){
20754                     case "southeast":
20755                     case "east":
20756                         h = oh * (w/ow);
20757                         h = Math.min(Math.max(mh, h), mxh);
20758                         w = ow * (h/oh);
20759                        break;
20760                     case "south":
20761                         w = ow * (h/oh);
20762                         w = Math.min(Math.max(mw, w), mxw);
20763                         h = oh * (w/ow);
20764                         break;
20765                     case "northeast":
20766                         w = ow * (h/oh);
20767                         w = Math.min(Math.max(mw, w), mxw);
20768                         h = oh * (w/ow);
20769                     break;
20770                     case "north":
20771                         var tw = w;
20772                         w = ow * (h/oh);
20773                         w = Math.min(Math.max(mw, w), mxw);
20774                         h = oh * (w/ow);
20775                         x += (tw - w) / 2;
20776                         break;
20777                     case "southwest":
20778                         h = oh * (w/ow);
20779                         h = Math.min(Math.max(mh, h), mxh);
20780                         var tw = w;
20781                         w = ow * (h/oh);
20782                         x += tw - w;
20783                         break;
20784                     case "west":
20785                         var th = h;
20786                         h = oh * (w/ow);
20787                         h = Math.min(Math.max(mh, h), mxh);
20788                         y += (th - h) / 2;
20789                         var tw = w;
20790                         w = ow * (h/oh);
20791                         x += tw - w;
20792                        break;
20793                     case "northwest":
20794                         var tw = w;
20795                         var th = h;
20796                         h = oh * (w/ow);
20797                         h = Math.min(Math.max(mh, h), mxh);
20798                         w = ow * (h/oh);
20799                         y += th - h;
20800                          x += tw - w;
20801                        break;
20802                         
20803                 }
20804             }
20805             this.proxy.setBounds(x, y, w, h);
20806             if(this.dynamic){
20807                 this.resizeElement();
20808             }
20809             }catch(e){}
20810         }
20811     },
20812
20813     
20814     handleOver : function(){
20815         if(this.enabled){
20816             this.el.addClass("x-resizable-over");
20817         }
20818     },
20819
20820     
20821     handleOut : function(){
20822         if(!this.resizing){
20823             this.el.removeClass("x-resizable-over");
20824         }
20825     },
20826     
20827     
20828     getEl : function(){
20829         return this.el;
20830     },
20831     
20832     
20833     getResizeChild : function(){
20834         return this.resizeChild;
20835     },
20836     
20837     
20838     destroy : function(removeEl){
20839         this.proxy.remove();
20840         if(this.overlay){
20841             this.overlay.removeAllListeners();
20842             this.overlay.remove();
20843         }
20844         var ps = Ext.Resizable.positions;
20845         for(var k in ps){
20846             if(typeof ps[k] != "function" && this[ps[k]]){
20847                 var h = this[ps[k]];
20848                 h.el.removeAllListeners();
20849                 h.el.remove();
20850             }
20851         }
20852         if(removeEl){
20853             this.el.update("");
20854             this.el.remove();
20855         }
20856     },
20857
20858     syncHandleHeight : function(){
20859         var h = this.el.getHeight(true);
20860         if(this.west){
20861             this.west.el.setHeight(h);
20862         }
20863         if(this.east){
20864             this.east.el.setHeight(h);
20865         }
20866     }
20867 });
20868
20869
20870
20871 Ext.Resizable.positions = {
20872     n: "north", s: "south", e: "east", w: "west", se: "southeast", sw: "southwest", nw: "northwest", ne: "northeast"
20873 };
20874
20875
20876 Ext.Resizable.Handle = function(rz, pos, disableTrackOver, transparent){
20877     if(!this.tpl){
20878         
20879         var tpl = Ext.DomHelper.createTemplate(
20880             {tag: "div", cls: "x-resizable-handle x-resizable-handle-{0}"}
20881         );
20882         tpl.compile();
20883         Ext.Resizable.Handle.prototype.tpl = tpl;
20884     }
20885     this.position = pos;
20886     this.rz = rz;
20887     this.el = this.tpl.append(rz.el.dom, [this.position], true);
20888     this.el.unselectable();
20889     if(transparent){
20890         this.el.setOpacity(0);
20891     }
20892     this.el.on("mousedown", this.onMouseDown, this);
20893     if(!disableTrackOver){
20894         this.el.on("mouseover", this.onMouseOver, this);
20895         this.el.on("mouseout", this.onMouseOut, this);
20896     }
20897 };
20898
20899
20900 Ext.Resizable.Handle.prototype = {
20901     afterResize : function(rz){
20902         
20903     },
20904     
20905     onMouseDown : function(e){
20906         this.rz.onMouseDown(this, e);
20907     },
20908     
20909     onMouseOver : function(e){
20910         this.rz.handleOver(this, e);
20911     },
20912     
20913     onMouseOut : function(e){
20914         this.rz.handleOut(this, e);
20915     }  
20916 };
20917
20918
20919
20920
20921
20922 Ext.Editor = function(field, config){
20923     this.field = field;
20924     Ext.Editor.superclass.constructor.call(this, config);
20925 };
20926
20927 Ext.extend(Ext.Editor, Ext.Component, {
20928     
20929     
20930     
20931     
20932     
20933     value : "",
20934     
20935     alignment: "c-c?",
20936     
20937     shadow : "frame",
20938     
20939     constrain : false,
20940     
20941     swallowKeys : true,
20942     
20943     completeOnEnter : false,
20944     
20945     cancelOnEsc : false,
20946     
20947     updateEl : false,
20948
20949     initComponent : function(){
20950         Ext.Editor.superclass.initComponent.call(this);
20951         this.addEvents(
20952             
20953             "beforestartedit",
20954             
20955             "startedit",
20956             
20957             "beforecomplete",
20958             
20959             "complete",
20960             
20961             "specialkey"
20962         );
20963     },
20964
20965         onRender : function(ct, position){
20966         this.el = new Ext.Layer({
20967             shadow: this.shadow,
20968             cls: "x-editor",
20969             parentEl : ct,
20970             shim : this.shim,
20971             shadowOffset:4,
20972             id: this.id,
20973             constrain: this.constrain
20974         });
20975         this.el.setStyle("overflow", Ext.isGecko ? "auto" : "hidden");
20976         if(this.field.msgTarget != 'title'){
20977             this.field.msgTarget = 'qtip';
20978         }
20979         this.field.inEditor = true;
20980         this.field.render(this.el);
20981         if(Ext.isGecko){
20982             this.field.el.dom.setAttribute('autocomplete', 'off');
20983         }
20984         this.field.on("specialkey", this.onSpecialKey, this);
20985         if(this.swallowKeys){
20986             this.field.el.swallowEvent(['keydown','keypress']);
20987         }
20988         this.field.show();
20989         this.field.on("blur", this.onBlur, this);
20990         if(this.field.grow){
20991             this.field.on("autosize", this.el.sync,  this.el, {delay:1});
20992         }
20993     },
20994
20995     onSpecialKey : function(field, e){
20996         if(this.completeOnEnter && e.getKey() == e.ENTER){
20997             e.stopEvent();
20998             this.completeEdit();
20999         }else if(this.cancelOnEsc && e.getKey() == e.ESC){
21000             this.cancelEdit();
21001         }else{
21002             this.fireEvent('specialkey', field, e);
21003         }
21004     },
21005
21006     
21007     startEdit : function(el, value){
21008         if(this.editing){
21009             this.completeEdit();
21010         }
21011         this.boundEl = Ext.get(el);
21012         var v = value !== undefined ? value : this.boundEl.dom.innerHTML;
21013         if(!this.rendered){
21014             this.render(this.parentEl || document.body);
21015         }
21016         if(this.fireEvent("beforestartedit", this, this.boundEl, v) === false){
21017             return;
21018         }
21019         this.startValue = v;
21020         this.field.setValue(v);
21021         this.doAutoSize();
21022         this.el.alignTo(this.boundEl, this.alignment);
21023         this.editing = true;
21024         this.show();
21025     },
21026
21027         doAutoSize : function(){
21028         if(this.autoSize){
21029             var sz = this.boundEl.getSize();
21030             switch(this.autoSize){
21031                 case "width":
21032                     this.setSize(sz.width,  "");
21033                 break;
21034                 case "height":
21035                     this.setSize("",  sz.height);
21036                 break;
21037                 default:
21038                     this.setSize(sz.width,  sz.height);
21039             }
21040         }
21041     },
21042
21043     
21044     setSize : function(w, h){
21045         delete this.field.lastSize;
21046         this.field.setSize(w, h);
21047         if(this.el){
21048             this.el.sync();
21049         }
21050     },
21051
21052     
21053     realign : function(){
21054         this.el.alignTo(this.boundEl, this.alignment);
21055     },
21056
21057     
21058     completeEdit : function(remainVisible){
21059         if(!this.editing){
21060             return;
21061         }
21062         var v = this.getValue();
21063         if(this.revertInvalid !== false && !this.field.isValid()){
21064             v = this.startValue;
21065             this.cancelEdit(true);
21066         }
21067         if(String(v) === String(this.startValue) && this.ignoreNoChange){
21068             this.editing = false;
21069             this.hide();
21070             return;
21071         }
21072         if(this.fireEvent("beforecomplete", this, v, this.startValue) !== false){
21073             this.editing = false;
21074             if(this.updateEl && this.boundEl){
21075                 this.boundEl.update(v);
21076             }
21077             if(remainVisible !== true){
21078                 this.hide();
21079             }
21080             this.fireEvent("complete", this, v, this.startValue);
21081         }
21082     },
21083
21084         onShow : function(){
21085         this.el.show();
21086         if(this.hideEl !== false){
21087             this.boundEl.hide();
21088         }
21089         this.field.show();
21090         if(Ext.isIE && !this.fixIEFocus){             this.fixIEFocus = true;
21091             this.deferredFocus.defer(50, this);
21092         }else{
21093             this.field.focus();
21094         }
21095         this.fireEvent("startedit", this.boundEl, this.startValue);
21096     },
21097
21098     deferredFocus : function(){
21099         if(this.editing){
21100             this.field.focus();
21101         }
21102     },
21103
21104     
21105     cancelEdit : function(remainVisible){
21106         if(this.editing){
21107             this.setValue(this.startValue);
21108             if(remainVisible !== true){
21109                 this.hide();
21110             }
21111         }
21112     },
21113
21114         onBlur : function(){
21115         if(this.allowBlur !== true && this.editing){
21116             this.completeEdit();
21117         }
21118     },
21119
21120         onHide : function(){
21121         if(this.editing){
21122             this.completeEdit();
21123             return;
21124         }
21125         this.field.blur();
21126         if(this.field.collapse){
21127             this.field.collapse();
21128         }
21129         this.el.hide();
21130         if(this.hideEl !== false){
21131             this.boundEl.show();
21132         }
21133     },
21134
21135     
21136     setValue : function(v){
21137         this.field.setValue(v);
21138     },
21139
21140     
21141     getValue : function(){
21142         return this.field.getValue();
21143     },
21144
21145     beforeDestroy : function(){
21146         this.field.destroy();
21147         this.field = null;
21148     }
21149 });
21150 Ext.reg('editor', Ext.Editor);
21151
21152 Ext.MessageBox = function(){
21153     var dlg, opt, mask, waitTimer;
21154     var bodyEl, msgEl, textboxEl, textareaEl, progressBar, pp, iconEl, spacerEl;
21155     var buttons, activeTextEl, bwidth, iconCls = '';
21156
21157     
21158     var handleButton = function(button){
21159         dlg.hide();
21160         Ext.callback(opt.fn, opt.scope||window, [button, activeTextEl.dom.value], 1);
21161     };
21162
21163     
21164     var handleHide = function(){
21165         if(opt && opt.cls){
21166             dlg.el.removeClass(opt.cls);
21167         }
21168         progressBar.reset();
21169     };
21170
21171     
21172     var handleEsc = function(d, k, e){
21173         if(opt && opt.closable !== false){
21174             dlg.hide();
21175         }
21176         if(e){
21177             e.stopEvent();
21178         }
21179     };
21180
21181     
21182     var updateButtons = function(b){
21183         var width = 0;
21184         if(!b){
21185             buttons["ok"].hide();
21186             buttons["cancel"].hide();
21187             buttons["yes"].hide();
21188             buttons["no"].hide();
21189             return width;
21190         }
21191         dlg.footer.dom.style.display = '';
21192         for(var k in buttons){
21193             if(typeof buttons[k] != "function"){
21194                 if(b[k]){
21195                     buttons[k].show();
21196                     buttons[k].setText(typeof b[k] == "string" ? b[k] : Ext.MessageBox.buttonText[k]);
21197                     width += buttons[k].el.getWidth()+15;
21198                 }else{
21199                     buttons[k].hide();
21200                 }
21201             }
21202         }
21203         return width;
21204     };
21205
21206     return {
21207         
21208         getDialog : function(titleText){
21209            if(!dlg){
21210                 dlg = new Ext.Window({
21211                     autoCreate : true,
21212                     title:titleText,
21213                     resizable:false,
21214                     constrain:true,
21215                     constrainHeader:true,
21216                     minimizable : false,
21217                     maximizable : false,
21218                     stateful: false,
21219                     modal: true,
21220                     shim:true,
21221                     buttonAlign:"center",
21222                     width:400,
21223                     height:100,
21224                     minHeight: 80,
21225                     plain:true,
21226                     footer:true,
21227                     closable:true,
21228                     close : function(){
21229                         if(opt && opt.buttons && opt.buttons.no && !opt.buttons.cancel){
21230                             handleButton("no");
21231                         }else{
21232                             handleButton("cancel");
21233                         }
21234                     }
21235                 });
21236                 buttons = {};
21237                 var bt = this.buttonText;
21238                 
21239                 buttons["ok"] = dlg.addButton(bt["ok"], handleButton.createCallback("ok"));
21240                 buttons["yes"] = dlg.addButton(bt["yes"], handleButton.createCallback("yes"));
21241                 buttons["no"] = dlg.addButton(bt["no"], handleButton.createCallback("no"));
21242                 buttons["cancel"] = dlg.addButton(bt["cancel"], handleButton.createCallback("cancel"));
21243                 buttons["ok"].hideMode = buttons["yes"].hideMode = buttons["no"].hideMode = buttons["cancel"].hideMode = 'offsets';
21244                 dlg.render(document.body);
21245                 dlg.getEl().addClass('x-window-dlg');
21246                 mask = dlg.mask;
21247                 bodyEl = dlg.body.createChild({
21248                     html:'<div class="ext-mb-icon"></div><div class="ext-mb-content"><span class="ext-mb-text"></span><br /><input type="text" class="ext-mb-input" /><textarea class="ext-mb-textarea"></textarea></div>'
21249                 });
21250                 iconEl = Ext.get(bodyEl.dom.firstChild);
21251                 var contentEl = bodyEl.dom.childNodes[1];
21252                 msgEl = Ext.get(contentEl.firstChild);
21253                 textboxEl = Ext.get(contentEl.childNodes[2]);
21254                 textboxEl.enableDisplayMode();
21255                 textboxEl.addKeyListener([10,13], function(){
21256                     if(dlg.isVisible() && opt && opt.buttons){
21257                         if(opt.buttons.ok){
21258                             handleButton("ok");
21259                         }else if(opt.buttons.yes){
21260                             handleButton("yes");
21261                         }
21262                     }
21263                 });
21264                 textareaEl = Ext.get(contentEl.childNodes[3]);
21265                 textareaEl.enableDisplayMode();
21266                 progressBar = new Ext.ProgressBar({
21267                     renderTo:bodyEl
21268                 });
21269                bodyEl.createChild({cls:'x-clear'});
21270             }
21271             return dlg;
21272         },
21273
21274         
21275         updateText : function(text){
21276             if(!dlg.isVisible() && !opt.width){
21277                 dlg.setSize(this.maxWidth, 100); 
21278             }
21279             msgEl.update(text || '&#160;');
21280
21281             var iw = iconCls != '' ? (iconEl.getWidth() + iconEl.getMargins('lr')) : 0;
21282             var mw = msgEl.getWidth() + msgEl.getMargins('lr');
21283             var fw = dlg.getFrameWidth('lr');
21284             var bw = dlg.body.getFrameWidth('lr');
21285             if (Ext.isIE && iw > 0){
21286                 
21287                 
21288                 iw += 3;
21289             }
21290             var w = Math.max(Math.min(opt.width || iw+mw+fw+bw, this.maxWidth),
21291                         Math.max(opt.minWidth || this.minWidth, bwidth || 0));
21292
21293             if(opt.prompt === true){
21294                 activeTextEl.setWidth(w-iw-fw-bw);
21295             }
21296             if(opt.progress === true || opt.wait === true){
21297                 progressBar.setSize(w-iw-fw-bw);
21298             }
21299             dlg.setSize(w, 'auto').center();
21300             return this;
21301         },
21302
21303         
21304         updateProgress : function(value, progressText, msg){
21305             progressBar.updateProgress(value, progressText);
21306             if(msg){
21307                 this.updateText(msg);
21308             }
21309             return this;
21310         },
21311
21312         
21313         isVisible : function(){
21314             return dlg && dlg.isVisible();
21315         },
21316
21317         
21318         hide : function(){
21319             if(this.isVisible()){
21320                 dlg.hide();
21321                 handleHide();
21322             }
21323             return this;
21324         },
21325
21326         
21327         show : function(options){
21328             if(this.isVisible()){
21329                 this.hide();
21330             }
21331             opt = options;
21332             var d = this.getDialog(opt.title || "&#160;");
21333
21334             d.setTitle(opt.title || "&#160;");
21335             var allowClose = (opt.closable !== false && opt.progress !== true && opt.wait !== true);
21336             d.tools.close.setDisplayed(allowClose);
21337             activeTextEl = textboxEl;
21338             opt.prompt = opt.prompt || (opt.multiline ? true : false);
21339             if(opt.prompt){
21340                 if(opt.multiline){
21341                     textboxEl.hide();
21342                     textareaEl.show();
21343                     textareaEl.setHeight(typeof opt.multiline == "number" ?
21344                         opt.multiline : this.defaultTextHeight);
21345                     activeTextEl = textareaEl;
21346                 }else{
21347                     textboxEl.show();
21348                     textareaEl.hide();
21349                 }
21350             }else{
21351                 textboxEl.hide();
21352                 textareaEl.hide();
21353             }
21354             activeTextEl.dom.value = opt.value || "";
21355             if(opt.prompt){
21356                 d.focusEl = activeTextEl;
21357             }else{
21358                 var bs = opt.buttons;
21359                 var db = null;
21360                 if(bs && bs.ok){
21361                     db = buttons["ok"];
21362                 }else if(bs && bs.yes){
21363                     db = buttons["yes"];
21364                 }
21365                 if (db){
21366                     d.focusEl = db;
21367                 }
21368             }
21369             this.setIcon(opt.icon);
21370             bwidth = updateButtons(opt.buttons);
21371             progressBar.setVisible(opt.progress === true || opt.wait === true);
21372             this.updateProgress(0, opt.progressText);
21373             this.updateText(opt.msg);
21374             if(opt.cls){
21375                 d.el.addClass(opt.cls);
21376             }
21377             d.proxyDrag = opt.proxyDrag === true;
21378             d.modal = opt.modal !== false;
21379             d.mask = opt.modal !== false ? mask : false;
21380             if(!d.isVisible()){
21381                 
21382                 document.body.appendChild(dlg.el.dom);
21383                 d.setAnimateTarget(opt.animEl);
21384                 d.show(opt.animEl);
21385             }
21386
21387             
21388             d.on('show', function(){
21389                 if(allowClose === true){
21390                     d.keyMap.enable();
21391                 }else{
21392                     d.keyMap.disable();
21393                 }
21394             }, this, {single:true});
21395
21396             if(opt.wait === true){
21397                 progressBar.wait(opt.waitConfig);
21398             }
21399             return this;
21400         },
21401
21402         
21403         setIcon : function(icon){
21404             if(icon && icon != ''){
21405                 iconEl.removeClass('x-hidden');
21406                 iconEl.replaceClass(iconCls, icon);
21407                 iconCls = icon;
21408             }else{
21409                 iconEl.replaceClass(iconCls, 'x-hidden');
21410                 iconCls = '';
21411             }
21412             return this;
21413         },
21414
21415         
21416         progress : function(title, msg, progressText){
21417             this.show({
21418                 title : title,
21419                 msg : msg,
21420                 buttons: false,
21421                 progress:true,
21422                 closable:false,
21423                 minWidth: this.minProgressWidth,
21424                 progressText: progressText
21425             });
21426             return this;
21427         },
21428
21429         
21430         wait : function(msg, title, config){
21431             this.show({
21432                 title : title,
21433                 msg : msg,
21434                 buttons: false,
21435                 closable:false,
21436                 wait:true,
21437                 modal:true,
21438                 minWidth: this.minProgressWidth,
21439                 waitConfig: config
21440             });
21441             return this;
21442         },
21443
21444         
21445         alert : function(title, msg, fn, scope){
21446             this.show({
21447                 title : title,
21448                 msg : msg,
21449                 buttons: this.OK,
21450                 fn: fn,
21451                 scope : scope
21452             });
21453             return this;
21454         },
21455
21456         
21457         confirm : function(title, msg, fn, scope){
21458             this.show({
21459                 title : title,
21460                 msg : msg,
21461                 buttons: this.YESNO,
21462                 fn: fn,
21463                 scope : scope,
21464                 icon: this.QUESTION
21465             });
21466             return this;
21467         },
21468
21469         
21470         prompt : function(title, msg, fn, scope, multiline){
21471             this.show({
21472                 title : title,
21473                 msg : msg,
21474                 buttons: this.OKCANCEL,
21475                 fn: fn,
21476                 minWidth:250,
21477                 scope : scope,
21478                 prompt:true,
21479                 multiline: multiline
21480             });
21481             return this;
21482         },
21483
21484         
21485         OK : {ok:true},
21486         
21487         CANCEL : {cancel:true},
21488         
21489         OKCANCEL : {ok:true, cancel:true},
21490         
21491         YESNO : {yes:true, no:true},
21492         
21493         YESNOCANCEL : {yes:true, no:true, cancel:true},
21494         
21495         INFO : 'ext-mb-info',
21496         
21497         WARNING : 'ext-mb-warning',
21498         
21499         QUESTION : 'ext-mb-question',
21500         
21501         ERROR : 'ext-mb-error',
21502
21503         
21504         defaultTextHeight : 75,
21505         
21506         maxWidth : 600,
21507         
21508         minWidth : 100,
21509         
21510         minProgressWidth : 250,
21511         
21512         buttonText : {
21513             ok : "OK",
21514             cancel : "Cancel",
21515             yes : "Yes",
21516             no : "No"
21517         }
21518     };
21519 }();
21520
21521
21522 Ext.Msg = Ext.MessageBox;
21523
21524 Ext.Tip = Ext.extend(Ext.Panel, {
21525     
21526     
21527     
21528     minWidth : 40,
21529     
21530     maxWidth : 300,
21531     
21532     shadow : "sides",
21533     
21534     defaultAlign : "tl-bl?",
21535     autoRender: true,
21536     quickShowInterval : 250,
21537
21538     
21539     frame:true,
21540     hidden:true,
21541     baseCls: 'x-tip',
21542     floating:{shadow:true,shim:true,useDisplay:true,constrain:false},
21543     autoHeight:true,
21544
21545     
21546     initComponent : function(){
21547         Ext.Tip.superclass.initComponent.call(this);
21548         if(this.closable && !this.title){
21549             this.elements += ',header';
21550         }
21551     },
21552
21553     
21554     afterRender : function(){
21555         Ext.Tip.superclass.afterRender.call(this);
21556         if(this.closable){
21557             this.addTool({
21558                 id: 'close',
21559                 handler: this.hide,
21560                 scope: this
21561             });
21562         }
21563     },
21564
21565     
21566     showAt : function(xy){
21567         Ext.Tip.superclass.show.call(this);
21568         if(this.measureWidth !== false && (!this.initialConfig || typeof this.initialConfig.width != 'number')){
21569             var bw = this.body.getTextWidth();
21570             if(this.title){
21571                 bw = Math.max(bw, this.header.child('span').getTextWidth(this.title));
21572             }
21573             bw += this.getFrameWidth() + (this.closable ? 20 : 0) + this.body.getPadding("lr");
21574             this.setWidth(bw.constrain(this.minWidth, this.maxWidth));
21575         }
21576         if(this.constrainPosition){
21577             xy = this.el.adjustForConstraints(xy);
21578         }
21579         this.setPagePosition(xy[0], xy[1]);
21580     },
21581
21582     
21583     showBy : function(el, pos){
21584         if(!this.rendered){
21585             this.render(Ext.getBody());
21586         }
21587         this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign));
21588     },
21589
21590     initDraggable : function(){
21591         this.dd = new Ext.Tip.DD(this, typeof this.draggable == 'boolean' ? null : this.draggable);
21592         this.header.addClass('x-tip-draggable');
21593     }
21594 });
21595
21596
21597 Ext.Tip.DD = function(tip, config){
21598     Ext.apply(this, config);
21599     this.tip = tip;
21600     Ext.Tip.DD.superclass.constructor.call(this, tip.el.id, 'WindowDD-'+tip.id);
21601     this.setHandleElId(tip.header.id);
21602     this.scroll = false;
21603 };
21604
21605 Ext.extend(Ext.Tip.DD, Ext.dd.DD, {
21606     moveOnly:true,
21607     scroll:false,
21608     headerOffsets:[100, 25],
21609     startDrag : function(){
21610         this.tip.el.disableShadow();
21611     },
21612     endDrag : function(e){
21613         this.tip.el.enableShadow(true);
21614     }
21615 });
21616
21617 Ext.ToolTip = Ext.extend(Ext.Tip, {
21618     
21619     
21620     
21621     showDelay: 500,
21622     
21623     hideDelay: 200,
21624     
21625     dismissDelay: 5000,
21626     
21627     mouseOffset: [15,18],
21628     
21629     trackMouse : false,
21630     constrainPosition: true,
21631
21632     
21633     initComponent: function(){
21634         Ext.ToolTip.superclass.initComponent.call(this);
21635         this.lastActive = new Date();
21636         this.initTarget();
21637     },
21638
21639     
21640     initTarget : function(){
21641         if(this.target){
21642             this.target = Ext.get(this.target);
21643             this.target.on('mouseover', this.onTargetOver, this);
21644             this.target.on('mouseout', this.onTargetOut, this);
21645             this.target.on('mousemove', this.onMouseMove, this);
21646         }
21647     },
21648
21649     
21650     onMouseMove : function(e){
21651         this.targetXY = e.getXY();
21652         if(!this.hidden && this.trackMouse){
21653             this.setPagePosition(this.getTargetXY());
21654         }
21655     },
21656
21657     
21658     getTargetXY : function(){
21659         return [this.targetXY[0]+this.mouseOffset[0], this.targetXY[1]+this.mouseOffset[1]];
21660     },
21661
21662     
21663     onTargetOver : function(e){
21664         if(this.disabled || e.within(this.target.dom, true)){
21665             return;
21666         }
21667         this.clearTimer('hide');
21668         this.targetXY = e.getXY();
21669         this.delayShow();
21670     },
21671
21672     
21673     delayShow : function(){
21674         if(this.hidden && !this.showTimer){
21675             if(this.lastActive.getElapsed() < this.quickShowInterval){
21676                 this.show();
21677             }else{
21678                 this.showTimer = this.show.defer(this.showDelay, this);
21679             }
21680         }else if(!this.hidden && this.autoHide !== false){
21681             this.show();
21682         }
21683     },
21684
21685     
21686     onTargetOut : function(e){
21687         if(this.disabled || e.within(this.target.dom, true)){
21688             return;
21689         }
21690         this.clearTimer('show');
21691         if(this.autoHide !== false){
21692             this.delayHide();
21693         }
21694     },
21695
21696     
21697     delayHide : function(){
21698         if(!this.hidden && !this.hideTimer){
21699             this.hideTimer = this.hide.defer(this.hideDelay, this);
21700         }
21701     },
21702
21703     
21704     hide: function(){
21705         this.clearTimer('dismiss');
21706         this.lastActive = new Date();
21707         Ext.ToolTip.superclass.hide.call(this);
21708     },
21709
21710     
21711     show : function(){
21712         this.showAt(this.getTargetXY());
21713     },
21714
21715     
21716     showAt : function(xy){
21717         this.lastActive = new Date();
21718         this.clearTimers();
21719         Ext.ToolTip.superclass.showAt.call(this, xy);
21720         if(this.dismissDelay && this.autoHide !== false){
21721             this.dismissTimer = this.hide.defer(this.dismissDelay, this);
21722         }
21723     },
21724
21725     
21726     clearTimer : function(name){
21727         name = name + 'Timer';
21728         clearTimeout(this[name]);
21729         delete this[name];
21730     },
21731
21732     
21733     clearTimers : function(){
21734         this.clearTimer('show');
21735         this.clearTimer('dismiss');
21736         this.clearTimer('hide');
21737     },
21738
21739     
21740     onShow : function(){
21741         Ext.ToolTip.superclass.onShow.call(this);
21742         Ext.getDoc().on('mousedown', this.onDocMouseDown, this);
21743     },
21744
21745     
21746     onHide : function(){
21747         Ext.ToolTip.superclass.onHide.call(this);
21748         Ext.getDoc().un('mousedown', this.onDocMouseDown, this);
21749     },
21750
21751     
21752     onDocMouseDown : function(e){
21753         if(this.autoHide !== false && !e.within(this.el.dom)){
21754             this.disable();
21755             this.enable.defer(100, this);
21756         }
21757     },
21758
21759     
21760     onDisable : function(){
21761         this.clearTimers();
21762         this.hide();
21763     },
21764
21765     
21766     adjustPosition : function(x, y){
21767         
21768         var ay = this.targetXY[1], h = this.getSize().height;
21769         if(this.constrainPosition && y <= ay && (y+h) >= ay){
21770             y = ay-h-5;
21771         }
21772         return {x : x, y: y};
21773     },
21774
21775     
21776     onDestroy : function(){
21777         Ext.ToolTip.superclass.onDestroy.call(this);
21778         if(this.target){
21779             this.target.un('mouseover', this.onTargetOver, this);
21780             this.target.un('mouseout', this.onTargetOut, this);
21781             this.target.un('mousemove', this.onMouseMove, this);
21782         }
21783     }
21784 });
21785
21786 Ext.QuickTip = Ext.extend(Ext.ToolTip, {
21787     
21788     
21789     interceptTitles : false,
21790
21791     
21792     tagConfig : {
21793         namespace : "ext",
21794         attribute : "qtip",
21795         width : "qwidth",
21796         target : "target",
21797         title : "qtitle",
21798         hide : "hide",
21799         cls : "qclass",
21800         align : "qalign"
21801     },
21802
21803     
21804     initComponent : function(){
21805         this.target = this.target || Ext.getDoc();
21806         this.targets = this.targets || {};
21807         Ext.QuickTip.superclass.initComponent.call(this);
21808     },
21809
21810     
21811     register : function(config){
21812         var cs = Ext.isArray(config) ? config : arguments;
21813         for(var i = 0, len = cs.length; i < len; i++){
21814             var c = cs[i];
21815             var target = c.target;
21816             if(target){
21817                 if(Ext.isArray(target)){
21818                     for(var j = 0, jlen = target.length; j < jlen; j++){
21819                         this.targets[Ext.id(target[j])] = c;
21820                     }
21821                 } else{
21822                     this.targets[Ext.id(target)] = c;
21823                 }
21824             }
21825         }
21826     },
21827
21828     
21829     unregister : function(el){
21830         delete this.targets[Ext.id(el)];
21831     },
21832
21833     
21834     onTargetOver : function(e){
21835         if(this.disabled){
21836             return;
21837         }
21838         this.targetXY = e.getXY();
21839         var t = e.getTarget();
21840         if(!t || t.nodeType !== 1 || t == document || t == document.body){
21841             return;
21842         }
21843         if(this.activeTarget && t == this.activeTarget.el){
21844             this.clearTimer('hide');
21845             this.show();
21846             return;
21847         }
21848         if(t && this.targets[t.id]){
21849             this.activeTarget = this.targets[t.id];
21850             this.activeTarget.el = t;
21851             this.delayShow();
21852             return;
21853         }
21854         var ttp, et = Ext.fly(t), cfg = this.tagConfig;
21855         var ns = cfg.namespace;
21856         if(this.interceptTitles && t.title){
21857             ttp = t.title;
21858             t.qtip = ttp;
21859             t.removeAttribute("title");
21860             e.preventDefault();
21861         } else{
21862             ttp = t.qtip || et.getAttributeNS(ns, cfg.attribute);
21863         }
21864         if(ttp){
21865             var autoHide = et.getAttributeNS(ns, cfg.hide);
21866             this.activeTarget = {
21867                 el: t,
21868                 text: ttp,
21869                 width: et.getAttributeNS(ns, cfg.width),
21870                 autoHide: autoHide != "user" && autoHide !== 'false',
21871                 title: et.getAttributeNS(ns, cfg.title),
21872                 cls: et.getAttributeNS(ns, cfg.cls),
21873                 align: et.getAttributeNS(ns, cfg.align)
21874             };
21875             this.delayShow();
21876         }
21877     },
21878
21879     
21880     onTargetOut : function(e){
21881         this.clearTimer('show');
21882         if(this.autoHide !== false){
21883             this.delayHide();
21884         }
21885     },
21886
21887     
21888     showAt : function(xy){
21889         var t = this.activeTarget;
21890         if(t){
21891             if(!this.rendered){
21892                 this.render(Ext.getBody());
21893                 this.activeTarget = t;
21894             }
21895             if(t.width){
21896                 this.setWidth(t.width);
21897                 this.body.setWidth(this.adjustBodyWidth(t.width - this.getFrameWidth()));
21898                 this.measureWidth = false;
21899             } else{
21900                 this.measureWidth = true;
21901             }
21902             this.setTitle(t.title || '');
21903             this.body.update(t.text);
21904             this.autoHide = t.autoHide;
21905             this.dismissDelay = t.dismissDelay || this.dismissDelay;
21906             if(this.lastCls){
21907                 this.el.removeClass(this.lastCls);
21908                 delete this.lastCls;
21909             }
21910             if(t.cls){
21911                 this.el.addClass(t.cls);
21912                 this.lastCls = t.cls;
21913             }
21914             if(t.align){ 
21915                 xy = this.el.getAlignToXY(t.el, t.align);
21916                 this.constrainPosition = false;
21917             } else{
21918                 this.constrainPosition = true;
21919             }
21920         }
21921         Ext.QuickTip.superclass.showAt.call(this, xy);
21922     },
21923
21924     
21925     hide: function(){
21926         delete this.activeTarget;
21927         Ext.QuickTip.superclass.hide.call(this);
21928     }
21929 });
21930
21931 Ext.QuickTips = function(){
21932     var tip, locks = [];
21933     return {
21934         
21935         init : function(){
21936             if(!tip){
21937                 tip = new Ext.QuickTip({elements:'header,body'});
21938             }
21939         },
21940
21941         
21942         enable : function(){
21943             if(tip){
21944                 locks.pop();
21945                 if(locks.length < 1){
21946                     tip.enable();
21947                 }
21948             }
21949         },
21950
21951         
21952         disable : function(){
21953             if(tip){
21954                 tip.disable();
21955             }
21956             locks.push(1);
21957         },
21958
21959         
21960         isEnabled : function(){
21961             return tip && !tip.disabled;
21962         },
21963
21964         
21965         getQuickTip : function(){
21966             return tip;
21967         },
21968
21969         
21970         register : function(){
21971             tip.register.apply(tip, arguments);
21972         },
21973
21974         
21975         unregister : function(){
21976             tip.unregister.apply(tip, arguments);
21977         },
21978
21979         
21980         tips :function(){
21981             tip.register.apply(tip, arguments);
21982         }
21983     }
21984 }();
21985
21986 Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
21987     rootVisible : true,
21988     animate: Ext.enableFx,
21989     lines : true,
21990     enableDD : false,
21991     hlDrop : Ext.enableFx,
21992     pathSeparator: "/",
21993
21994     initComponent : function(){
21995         Ext.tree.TreePanel.superclass.initComponent.call(this);
21996
21997         if(!this.eventModel){
21998             this.eventModel = new Ext.tree.TreeEventModel(this);
21999         }
22000         
22001         this.nodeHash = {};
22002
22003         
22004         if(this.root){
22005            this.setRootNode(this.root);
22006         }
22007
22008         this.addEvents(
22009
22010             
22011            "append",
22012            
22013            "remove",
22014            
22015            "movenode",
22016            
22017            "insert",
22018            
22019            "beforeappend",
22020            
22021            "beforeremove",
22022            
22023            "beforemovenode",
22024            
22025             "beforeinsert",
22026
22027             
22028             "beforeload",
22029             
22030             "load",
22031             
22032             "textchange",
22033             
22034             "beforeexpandnode",
22035             
22036             "beforecollapsenode",
22037             
22038             "expandnode",
22039             
22040             "disabledchange",
22041             
22042             "collapsenode",
22043             
22044             "beforeclick",
22045             
22046             "click",
22047             
22048             "checkchange",
22049             
22050             "dblclick",
22051             
22052             "contextmenu",
22053             
22054             "beforechildrenrendered",
22055            
22056             "startdrag",
22057             
22058             "enddrag",
22059             
22060             "dragdrop",
22061             
22062             "beforenodedrop",
22063             
22064             "nodedrop",
22065              
22066             "nodedragover"
22067         );
22068         if(this.singleExpand){
22069             this.on("beforeexpandnode", this.restrictExpand, this);
22070         }
22071     },
22072
22073     
22074     proxyNodeEvent : function(ename, a1, a2, a3, a4, a5, a6){
22075         if(ename == 'collapse' || ename == 'expand' || ename == 'beforecollapse' || ename == 'beforeexpand' || ename == 'move' || ename == 'beforemove'){
22076             ename = ename+'node';
22077         }
22078         
22079         return this.fireEvent(ename, a1, a2, a3, a4, a5, a6);
22080     },
22081
22082
22083     
22084     getRootNode : function(){
22085         return this.root;
22086     },
22087
22088     
22089     setRootNode : function(node){
22090         this.root = node;
22091         node.ownerTree = this;
22092         node.isRoot = true;
22093         this.registerNode(node);
22094         if(!this.rootVisible){
22095                 var uiP = node.attributes.uiProvider;
22096                 node.ui = uiP ? new uiP(node) : new Ext.tree.RootTreeNodeUI(node); 
22097         }
22098         return node;
22099     },
22100
22101     
22102     getNodeById : function(id){
22103         return this.nodeHash[id];
22104     },
22105
22106     
22107     registerNode : function(node){
22108         this.nodeHash[node.id] = node;
22109     },
22110
22111     
22112     unregisterNode : function(node){
22113         delete this.nodeHash[node.id];
22114     },
22115
22116     
22117     toString : function(){
22118         return "[Tree"+(this.id?" "+this.id:"")+"]";
22119     },
22120
22121     
22122     restrictExpand : function(node){
22123         var p = node.parentNode;
22124         if(p){
22125             if(p.expandedChild && p.expandedChild.parentNode == p){
22126                 p.expandedChild.collapse();
22127             }
22128             p.expandedChild = node;
22129         }
22130     },
22131
22132     
22133     getChecked : function(a, startNode){
22134         startNode = startNode || this.root;
22135         var r = [];
22136         var f = function(){
22137             if(this.attributes.checked){
22138                 r.push(!a ? this : (a == 'id' ? this.id : this.attributes[a]));
22139             }
22140         }
22141         startNode.cascade(f);
22142         return r;
22143     },
22144
22145     
22146     getEl : function(){
22147         return this.el;
22148     },
22149
22150     
22151     getLoader : function(){
22152         return this.loader;
22153     },
22154
22155     
22156     expandAll : function(){
22157         this.root.expand(true);
22158     },
22159
22160     
22161     collapseAll : function(){
22162         this.root.collapse(true);
22163     },
22164
22165     
22166     getSelectionModel : function(){
22167         if(!this.selModel){
22168             this.selModel = new Ext.tree.DefaultSelectionModel();
22169         }
22170         return this.selModel;
22171     },
22172
22173     
22174     expandPath : function(path, attr, callback){
22175         attr = attr || "id";
22176         var keys = path.split(this.pathSeparator);
22177         var curNode = this.root;
22178         if(curNode.attributes[attr] != keys[1]){ 
22179             if(callback){
22180                 callback(false, null);
22181             }
22182             return;
22183         }
22184         var index = 1;
22185         var f = function(){
22186             if(++index == keys.length){
22187                 if(callback){
22188                     callback(true, curNode);
22189                 }
22190                 return;
22191             }
22192             var c = curNode.findChild(attr, keys[index]);
22193             if(!c){
22194                 if(callback){
22195                     callback(false, curNode);
22196                 }
22197                 return;
22198             }
22199             curNode = c;
22200             c.expand(false, false, f);
22201         };
22202         curNode.expand(false, false, f);
22203     },
22204
22205     
22206     selectPath : function(path, attr, callback){
22207         attr = attr || "id";
22208         var keys = path.split(this.pathSeparator);
22209         var v = keys.pop();
22210         if(keys.length > 0){
22211             var f = function(success, node){
22212                 if(success && node){
22213                     var n = node.findChild(attr, v);
22214                     if(n){
22215                         n.select();
22216                         if(callback){
22217                             callback(true, n);
22218                         }
22219                     }else if(callback){
22220                         callback(false, n);
22221                     }
22222                 }else{
22223                     if(callback){
22224                         callback(false, n);
22225                     }
22226                 }
22227             };
22228             this.expandPath(keys.join(this.pathSeparator), attr, f);
22229         }else{
22230             this.root.select();
22231             if(callback){
22232                 callback(true, this.root);
22233             }
22234         }
22235     },
22236
22237     
22238     getTreeEl : function(){
22239         return this.body;
22240     },
22241
22242     
22243     onRender : function(ct, position){
22244         Ext.tree.TreePanel.superclass.onRender.call(this, ct, position);
22245         this.el.addClass('x-tree');
22246         this.innerCt = this.body.createChild({tag:"ul",
22247                cls:"x-tree-root-ct " +
22248                (this.useArrows ? 'x-tree-arrows' : this.lines ? "x-tree-lines" : "x-tree-no-lines")});
22249     },
22250
22251     
22252     initEvents : function(){
22253         Ext.tree.TreePanel.superclass.initEvents.call(this);
22254
22255         if(this.containerScroll){
22256             Ext.dd.ScrollManager.register(this.body);
22257         }
22258         if((this.enableDD || this.enableDrop) && !this.dropZone){
22259            
22260              this.dropZone = new Ext.tree.TreeDropZone(this, this.dropConfig || {
22261                ddGroup: this.ddGroup || "TreeDD", appendOnly: this.ddAppendOnly === true
22262            });
22263         }
22264         if((this.enableDD || this.enableDrag) && !this.dragZone){
22265            
22266             this.dragZone = new Ext.tree.TreeDragZone(this, this.dragConfig || {
22267                ddGroup: this.ddGroup || "TreeDD",
22268                scroll: this.ddScroll
22269            });
22270         }
22271         this.getSelectionModel().init(this);
22272     },
22273
22274     
22275     afterRender : function(){
22276         Ext.tree.TreePanel.superclass.afterRender.call(this);
22277         this.root.render();
22278         if(!this.rootVisible){
22279             this.root.renderChildren();
22280         }
22281     },
22282
22283     onDestroy : function(){
22284         if(this.rendered){
22285             this.body.removeAllListeners();
22286             Ext.dd.ScrollManager.unregister(this.body);
22287             if(this.dropZone){
22288                 this.dropZone.unreg();
22289             }
22290             if(this.dragZone){
22291                this.dragZone.unreg();
22292             }
22293         }
22294         this.root.destroy();
22295         this.nodeHash = null;
22296         Ext.tree.TreePanel.superclass.onDestroy.call(this);
22297     }
22298     
22299     
22300     
22301     
22302     
22303     
22304     
22305     
22306     
22307     
22308     
22309     
22310     
22311     
22312     
22313     
22314     
22315     
22316     
22317     
22318     
22319     
22320     
22321     
22322     
22323     
22324     
22325     
22326     
22327     
22328     
22329     
22330
22331
22332
22333     
22334     
22335     
22336     
22337     
22338     
22339     
22340     
22341     
22342     
22343     
22344     
22345 });
22346 Ext.reg('treepanel', Ext.tree.TreePanel);
22347 Ext.tree.TreeEventModel = function(tree){
22348     this.tree = tree;
22349     this.tree.on('render', this.initEvents, this);
22350 }
22351
22352 Ext.tree.TreeEventModel.prototype = {
22353     initEvents : function(){
22354         var el = this.tree.getTreeEl();
22355         el.on('click', this.delegateClick, this);
22356         if(this.tree.trackMouseOver !== false){
22357             el.on('mouseover', this.delegateOver, this);
22358             el.on('mouseout', this.delegateOut, this);
22359         }
22360         el.on('dblclick', this.delegateDblClick, this);
22361         el.on('contextmenu', this.delegateContextMenu, this);
22362     },
22363
22364     getNode : function(e){
22365         var t;
22366         if(t = e.getTarget('.x-tree-node-el', 10)){
22367             var id = Ext.fly(t, '_treeEvents').getAttributeNS('ext', 'tree-node-id');
22368             if(id){
22369                 return this.tree.getNodeById(id);
22370             }
22371         }
22372         return null;
22373     },
22374
22375     getNodeTarget : function(e){
22376         var t = e.getTarget('.x-tree-node-icon', 1);
22377         if(!t){
22378             t = e.getTarget('.x-tree-node-el', 6);
22379         }
22380         return t;
22381     },
22382
22383     delegateOut : function(e, t){
22384         if(!this.beforeEvent(e)){
22385             return;
22386         }
22387         if(e.getTarget('.x-tree-ec-icon', 1)){
22388             var n = this.getNode(e);
22389             this.onIconOut(e, n);
22390             if(n == this.lastEcOver){
22391                 delete this.lastEcOver;
22392             }
22393         }
22394         if((t = this.getNodeTarget(e)) && !e.within(t, true)){
22395             this.onNodeOut(e, this.getNode(e));
22396         }
22397     },
22398
22399     delegateOver : function(e, t){
22400         if(!this.beforeEvent(e)){
22401             return;
22402         }
22403         if(this.lastEcOver){ 
22404             this.onIconOut(e, this.lastEcOver);
22405             delete this.lastEcOver;
22406         }
22407         if(e.getTarget('.x-tree-ec-icon', 1)){
22408             this.lastEcOver = this.getNode(e);
22409             this.onIconOver(e, this.lastEcOver);
22410         }
22411         if(t = this.getNodeTarget(e)){
22412             this.onNodeOver(e, this.getNode(e));
22413         }
22414     },
22415
22416     delegateClick : function(e, t){
22417         if(!this.beforeEvent(e)){
22418             return;
22419         }
22420
22421         if(e.getTarget('input[type=checkbox]', 1)){
22422             this.onCheckboxClick(e, this.getNode(e));
22423         }
22424         else if(e.getTarget('.x-tree-ec-icon', 1)){
22425             this.onIconClick(e, this.getNode(e));
22426         }
22427         else if(this.getNodeTarget(e)){
22428             this.onNodeClick(e, this.getNode(e));
22429         }
22430     },
22431
22432     delegateDblClick : function(e, t){
22433         if(this.beforeEvent(e) && this.getNodeTarget(e)){
22434             this.onNodeDblClick(e, this.getNode(e));
22435         }
22436     },
22437
22438     delegateContextMenu : function(e, t){
22439         if(this.beforeEvent(e) && this.getNodeTarget(e)){
22440             this.onNodeContextMenu(e, this.getNode(e));
22441         }
22442     },
22443
22444     onNodeClick : function(e, node){
22445         node.ui.onClick(e);
22446     },
22447
22448     onNodeOver : function(e, node){
22449         node.ui.onOver(e);
22450     },
22451
22452     onNodeOut : function(e, node){
22453         node.ui.onOut(e);
22454     },
22455
22456     onIconOver : function(e, node){
22457         node.ui.addClass('x-tree-ec-over');
22458     },
22459
22460     onIconOut : function(e, node){
22461         node.ui.removeClass('x-tree-ec-over');
22462     },
22463
22464     onIconClick : function(e, node){
22465         node.ui.ecClick(e);
22466     },
22467
22468     onCheckboxClick : function(e, node){
22469         node.ui.onCheckChange(e);
22470     },
22471
22472     onNodeDblClick : function(e, node){
22473         node.ui.onDblClick(e);
22474     },
22475
22476     onNodeContextMenu : function(e, node){
22477         node.ui.onContextMenu(e);
22478     },
22479
22480     beforeEvent : function(e){
22481         if(this.disabled){
22482             e.stopEvent();
22483             return false;
22484         }
22485         return true;
22486     },
22487
22488     disable: function(){
22489         this.disabled = true;
22490     },
22491
22492     enable: function(){
22493         this.disabled = false;
22494     }
22495 };
22496
22497 Ext.tree.DefaultSelectionModel = function(config){
22498    this.selNode = null;
22499    
22500    this.addEvents(
22501        
22502        "selectionchange",
22503
22504        
22505        "beforeselect"
22506    );
22507
22508     Ext.apply(this, config);
22509     Ext.tree.DefaultSelectionModel.superclass.constructor.call(this);
22510 };
22511
22512 Ext.extend(Ext.tree.DefaultSelectionModel, Ext.util.Observable, {
22513     init : function(tree){
22514         this.tree = tree;
22515         tree.getTreeEl().on("keydown", this.onKeyDown, this);
22516         tree.on("click", this.onNodeClick, this);
22517     },
22518     
22519     onNodeClick : function(node, e){
22520         this.select(node);
22521     },
22522     
22523     
22524     select : function(node){
22525         var last = this.selNode;
22526         if(last != node && this.fireEvent('beforeselect', this, node, last) !== false){
22527             if(last){
22528                 last.ui.onSelectedChange(false);
22529             }
22530             this.selNode = node;
22531             node.ui.onSelectedChange(true);
22532             this.fireEvent("selectionchange", this, node, last);
22533         }
22534         return node;
22535     },
22536     
22537     
22538     unselect : function(node){
22539         if(this.selNode == node){
22540             this.clearSelections();
22541         }    
22542     },
22543     
22544     
22545     clearSelections : function(){
22546         var n = this.selNode;
22547         if(n){
22548             n.ui.onSelectedChange(false);
22549             this.selNode = null;
22550             this.fireEvent("selectionchange", this, null);
22551         }
22552         return n;
22553     },
22554     
22555     
22556     getSelectedNode : function(){
22557         return this.selNode;    
22558     },
22559     
22560     
22561     isSelected : function(node){
22562         return this.selNode == node;  
22563     },
22564
22565     
22566     selectPrevious : function(){
22567         var s = this.selNode || this.lastSelNode;
22568         if(!s){
22569             return null;
22570         }
22571         var ps = s.previousSibling;
22572         if(ps){
22573             if(!ps.isExpanded() || ps.childNodes.length < 1){
22574                 return this.select(ps);
22575             } else{
22576                 var lc = ps.lastChild;
22577                 while(lc && lc.isExpanded() && lc.childNodes.length > 0){
22578                     lc = lc.lastChild;
22579                 }
22580                 return this.select(lc);
22581             }
22582         } else if(s.parentNode && (this.tree.rootVisible || !s.parentNode.isRoot)){
22583             return this.select(s.parentNode);
22584         }
22585         return null;
22586     },
22587
22588     
22589     selectNext : function(){
22590         var s = this.selNode || this.lastSelNode;
22591         if(!s){
22592             return null;
22593         }
22594         if(s.firstChild && s.isExpanded()){
22595              return this.select(s.firstChild);
22596          }else if(s.nextSibling){
22597              return this.select(s.nextSibling);
22598          }else if(s.parentNode){
22599             var newS = null;
22600             s.parentNode.bubble(function(){
22601                 if(this.nextSibling){
22602                     newS = this.getOwnerTree().selModel.select(this.nextSibling);
22603                     return false;
22604                 }
22605             });
22606             return newS;
22607          }
22608         return null;
22609     },
22610
22611     onKeyDown : function(e){
22612         var s = this.selNode || this.lastSelNode;
22613         
22614         var sm = this;
22615         if(!s){
22616             return;
22617         }
22618         var k = e.getKey();
22619         switch(k){
22620              case e.DOWN:
22621                  e.stopEvent();
22622                  this.selectNext();
22623              break;
22624              case e.UP:
22625                  e.stopEvent();
22626                  this.selectPrevious();
22627              break;
22628              case e.RIGHT:
22629                  e.preventDefault();
22630                  if(s.hasChildNodes()){
22631                      if(!s.isExpanded()){
22632                          s.expand();
22633                      }else if(s.firstChild){
22634                          this.select(s.firstChild, e);
22635                      }
22636                  }
22637              break;
22638              case e.LEFT:
22639                  e.preventDefault();
22640                  if(s.hasChildNodes() && s.isExpanded()){
22641                      s.collapse();
22642                  }else if(s.parentNode && (this.tree.rootVisible || s.parentNode != this.tree.getRootNode())){
22643                      this.select(s.parentNode, e);
22644                  }
22645              break;
22646         };
22647     }
22648 });
22649
22650
22651 Ext.tree.MultiSelectionModel = function(config){
22652    this.selNodes = [];
22653    this.selMap = {};
22654    this.addEvents(
22655        
22656        "selectionchange"
22657    );
22658     Ext.apply(this, config);
22659     Ext.tree.MultiSelectionModel.superclass.constructor.call(this);
22660 };
22661
22662 Ext.extend(Ext.tree.MultiSelectionModel, Ext.util.Observable, {
22663     init : function(tree){
22664         this.tree = tree;
22665         tree.getTreeEl().on("keydown", this.onKeyDown, this);
22666         tree.on("click", this.onNodeClick, this);
22667     },
22668     
22669     onNodeClick : function(node, e){
22670         this.select(node, e, e.ctrlKey);
22671     },
22672     
22673     
22674     select : function(node, e, keepExisting){
22675         if(keepExisting !== true){
22676             this.clearSelections(true);
22677         }
22678         if(this.isSelected(node)){
22679             this.lastSelNode = node;
22680             return node;
22681         }
22682         this.selNodes.push(node);
22683         this.selMap[node.id] = node;
22684         this.lastSelNode = node;
22685         node.ui.onSelectedChange(true);
22686         this.fireEvent("selectionchange", this, this.selNodes);
22687         return node;
22688     },
22689     
22690     
22691     unselect : function(node){
22692         if(this.selMap[node.id]){
22693             node.ui.onSelectedChange(false);
22694             var sn = this.selNodes;
22695             var index = sn.indexOf(node);
22696             if(index != -1){
22697                 this.selNodes.splice(index, 1);
22698             }
22699             delete this.selMap[node.id];
22700             this.fireEvent("selectionchange", this, this.selNodes);
22701         }
22702     },
22703     
22704     
22705     clearSelections : function(suppressEvent){
22706         var sn = this.selNodes;
22707         if(sn.length > 0){
22708             for(var i = 0, len = sn.length; i < len; i++){
22709                 sn[i].ui.onSelectedChange(false);
22710             }
22711             this.selNodes = [];
22712             this.selMap = {};
22713             if(suppressEvent !== true){
22714                 this.fireEvent("selectionchange", this, this.selNodes);
22715             }
22716         }
22717     },
22718     
22719     
22720     isSelected : function(node){
22721         return this.selMap[node.id] ? true : false;  
22722     },
22723     
22724     
22725     getSelectedNodes : function(){
22726         return this.selNodes;    
22727     },
22728
22729     onKeyDown : Ext.tree.DefaultSelectionModel.prototype.onKeyDown,
22730
22731     selectNext : Ext.tree.DefaultSelectionModel.prototype.selectNext,
22732
22733     selectPrevious : Ext.tree.DefaultSelectionModel.prototype.selectPrevious
22734 });
22735
22736 Ext.tree.TreeNode = function(attributes){
22737     attributes = attributes || {};
22738     if(typeof attributes == "string"){
22739         attributes = {text: attributes};
22740     }
22741     this.childrenRendered = false;
22742     this.rendered = false;
22743     Ext.tree.TreeNode.superclass.constructor.call(this, attributes);
22744     this.expanded = attributes.expanded === true;
22745     this.isTarget = attributes.isTarget !== false;
22746     this.draggable = attributes.draggable !== false && attributes.allowDrag !== false;
22747     this.allowChildren = attributes.allowChildren !== false && attributes.allowDrop !== false;
22748
22749     
22750     this.text = attributes.text;
22751     
22752     this.disabled = attributes.disabled === true;
22753
22754     this.addEvents(
22755         
22756         "textchange",
22757         
22758         "beforeexpand",
22759         
22760         "beforecollapse",
22761         
22762         "expand",
22763         
22764         "disabledchange",
22765         
22766         "collapse",
22767         
22768         "beforeclick",
22769         
22770         "click",
22771         
22772         "checkchange",
22773         
22774         "dblclick",
22775         
22776         "contextmenu",
22777         
22778         "beforechildrenrendered"
22779     );
22780
22781     var uiClass = this.attributes.uiProvider || this.defaultUI || Ext.tree.TreeNodeUI;
22782
22783     
22784     this.ui = new uiClass(this);
22785 };
22786 Ext.extend(Ext.tree.TreeNode, Ext.data.Node, {
22787     preventHScroll: true,
22788     
22789     isExpanded : function(){
22790         return this.expanded;
22791     },
22792
22793
22794     getUI : function(){
22795         return this.ui;
22796     },
22797
22798     
22799     setFirstChild : function(node){
22800         var of = this.firstChild;
22801         Ext.tree.TreeNode.superclass.setFirstChild.call(this, node);
22802         if(this.childrenRendered && of && node != of){
22803             of.renderIndent(true, true);
22804         }
22805         if(this.rendered){
22806             this.renderIndent(true, true);
22807         }
22808     },
22809
22810     
22811     setLastChild : function(node){
22812         var ol = this.lastChild;
22813         Ext.tree.TreeNode.superclass.setLastChild.call(this, node);
22814         if(this.childrenRendered && ol && node != ol){
22815             ol.renderIndent(true, true);
22816         }
22817         if(this.rendered){
22818             this.renderIndent(true, true);
22819         }
22820     },
22821
22822     
22823     
22824     appendChild : function(){
22825         var node = Ext.tree.TreeNode.superclass.appendChild.apply(this, arguments);
22826         if(node && this.childrenRendered){
22827             node.render();
22828         }
22829         this.ui.updateExpandIcon();
22830         return node;
22831     },
22832
22833     
22834     removeChild : function(node){
22835         this.ownerTree.getSelectionModel().unselect(node);
22836         Ext.tree.TreeNode.superclass.removeChild.apply(this, arguments);
22837         
22838         if(this.childrenRendered){
22839             node.ui.remove();
22840         }
22841         if(this.childNodes.length < 1){
22842             this.collapse(false, false);
22843         }else{
22844             this.ui.updateExpandIcon();
22845         }
22846         if(!this.firstChild && !this.isHiddenRoot()) {
22847             this.childrenRendered = false;
22848         }
22849         return node;
22850     },
22851
22852     
22853     insertBefore : function(node, refNode){
22854         var newNode = Ext.tree.TreeNode.superclass.insertBefore.apply(this, arguments);
22855         if(newNode && refNode && this.childrenRendered){
22856             node.render();
22857         }
22858         this.ui.updateExpandIcon();
22859         return newNode;
22860     },
22861
22862     
22863     setText : function(text){
22864         var oldText = this.text;
22865         this.text = text;
22866         this.attributes.text = text;
22867         if(this.rendered){ 
22868             this.ui.onTextChange(this, text, oldText);
22869         }
22870         this.fireEvent("textchange", this, text, oldText);
22871     },
22872
22873     
22874     select : function(){
22875         this.getOwnerTree().getSelectionModel().select(this);
22876     },
22877
22878     
22879     unselect : function(){
22880         this.getOwnerTree().getSelectionModel().unselect(this);
22881     },
22882
22883     
22884     isSelected : function(){
22885         return this.getOwnerTree().getSelectionModel().isSelected(this);
22886     },
22887
22888     
22889     expand : function(deep, anim, callback){
22890         if(!this.expanded){
22891             if(this.fireEvent("beforeexpand", this, deep, anim) === false){
22892                 return;
22893             }
22894             if(!this.childrenRendered){
22895                 this.renderChildren();
22896             }
22897             this.expanded = true;
22898             if(!this.isHiddenRoot() && (this.getOwnerTree().animate && anim !== false) || anim){
22899                 this.ui.animExpand(function(){
22900                     this.fireEvent("expand", this);
22901                     if(typeof callback == "function"){
22902                         callback(this);
22903                     }
22904                     if(deep === true){
22905                         this.expandChildNodes(true);
22906                     }
22907                 }.createDelegate(this));
22908                 return;
22909             }else{
22910                 this.ui.expand();
22911                 this.fireEvent("expand", this);
22912                 if(typeof callback == "function"){
22913                     callback(this);
22914                 }
22915             }
22916         }else{
22917            if(typeof callback == "function"){
22918                callback(this);
22919            }
22920         }
22921         if(deep === true){
22922             this.expandChildNodes(true);
22923         }
22924     },
22925
22926     isHiddenRoot : function(){
22927         return this.isRoot && !this.getOwnerTree().rootVisible;
22928     },
22929
22930     
22931     collapse : function(deep, anim){
22932         if(this.expanded && !this.isHiddenRoot()){
22933             if(this.fireEvent("beforecollapse", this, deep, anim) === false){
22934                 return;
22935             }
22936             this.expanded = false;
22937             if((this.getOwnerTree().animate && anim !== false) || anim){
22938                 this.ui.animCollapse(function(){
22939                     this.fireEvent("collapse", this);
22940                     if(deep === true){
22941                         this.collapseChildNodes(true);
22942                     }
22943                 }.createDelegate(this));
22944                 return;
22945             }else{
22946                 this.ui.collapse();
22947                 this.fireEvent("collapse", this);
22948             }
22949         }
22950         if(deep === true){
22951             var cs = this.childNodes;
22952             for(var i = 0, len = cs.length; i < len; i++) {
22953                 cs[i].collapse(true, false);
22954             }
22955         }
22956     },
22957
22958     
22959     delayedExpand : function(delay){
22960         if(!this.expandProcId){
22961             this.expandProcId = this.expand.defer(delay, this);
22962         }
22963     },
22964
22965     
22966     cancelExpand : function(){
22967         if(this.expandProcId){
22968             clearTimeout(this.expandProcId);
22969         }
22970         this.expandProcId = false;
22971     },
22972
22973     
22974     toggle : function(){
22975         if(this.expanded){
22976             this.collapse();
22977         }else{
22978             this.expand();
22979         }
22980     },
22981
22982     
22983     ensureVisible : function(callback){
22984         var tree = this.getOwnerTree();
22985         tree.expandPath(this.parentNode.getPath(), false, function(){
22986             var node = tree.getNodeById(this.id);  
22987             tree.getTreeEl().scrollChildIntoView(node.ui.anchor);
22988             Ext.callback(callback);
22989         }.createDelegate(this));
22990     },
22991
22992     
22993     expandChildNodes : function(deep){
22994         var cs = this.childNodes;
22995         for(var i = 0, len = cs.length; i < len; i++) {
22996                 cs[i].expand(deep);
22997         }
22998     },
22999
23000     
23001     collapseChildNodes : function(deep){
23002         var cs = this.childNodes;
23003         for(var i = 0, len = cs.length; i < len; i++) {
23004                 cs[i].collapse(deep);
23005         }
23006     },
23007
23008     
23009     disable : function(){
23010         this.disabled = true;
23011         this.unselect();
23012         if(this.rendered && this.ui.onDisableChange){ 
23013             this.ui.onDisableChange(this, true);
23014         }
23015         this.fireEvent("disabledchange", this, true);
23016     },
23017
23018     
23019     enable : function(){
23020         this.disabled = false;
23021         if(this.rendered && this.ui.onDisableChange){ 
23022             this.ui.onDisableChange(this, false);
23023         }
23024         this.fireEvent("disabledchange", this, false);
23025     },
23026
23027     
23028     renderChildren : function(suppressEvent){
23029         if(suppressEvent !== false){
23030             this.fireEvent("beforechildrenrendered", this);
23031         }
23032         var cs = this.childNodes;
23033         for(var i = 0, len = cs.length; i < len; i++){
23034             cs[i].render(true);
23035         }
23036         this.childrenRendered = true;
23037     },
23038
23039     
23040     sort : function(fn, scope){
23041         Ext.tree.TreeNode.superclass.sort.apply(this, arguments);
23042         if(this.childrenRendered){
23043             var cs = this.childNodes;
23044             for(var i = 0, len = cs.length; i < len; i++){
23045                 cs[i].render(true);
23046             }
23047         }
23048     },
23049
23050     
23051     render : function(bulkRender){
23052         this.ui.render(bulkRender);
23053         if(!this.rendered){
23054             
23055             this.getOwnerTree().registerNode(this);
23056             this.rendered = true;
23057             if(this.expanded){
23058                 this.expanded = false;
23059                 this.expand(false, false);
23060             }
23061         }
23062     },
23063
23064     
23065     renderIndent : function(deep, refresh){
23066         if(refresh){
23067             this.ui.childIndent = null;
23068         }
23069         this.ui.renderIndent();
23070         if(deep === true && this.childrenRendered){
23071             var cs = this.childNodes;
23072             for(var i = 0, len = cs.length; i < len; i++){
23073                 cs[i].renderIndent(true, refresh);
23074             }
23075         }
23076     },
23077
23078     beginUpdate : function(){
23079         this.childrenRendered = false;
23080     },
23081
23082     endUpdate : function(){
23083         if(this.expanded){
23084             this.renderChildren();
23085         }
23086     },
23087
23088     destroy : function(){
23089         for(var i = 0,l = this.childNodes.length; i < l; i++){
23090             this.childNodes[i].destroy();
23091         }
23092         this.childNodes = null;
23093         if(this.ui.destroy){
23094             this.ui.destroy();
23095         }
23096     }
23097 });
23098
23099  Ext.tree.AsyncTreeNode = function(config){
23100     this.loaded = false;
23101     this.loading = false;
23102     Ext.tree.AsyncTreeNode.superclass.constructor.apply(this, arguments);
23103     
23104     this.addEvents('beforeload', 'load');
23105     
23106     
23107 };
23108 Ext.extend(Ext.tree.AsyncTreeNode, Ext.tree.TreeNode, {
23109     expand : function(deep, anim, callback){
23110         if(this.loading){ 
23111             var timer;
23112             var f = function(){
23113                 if(!this.loading){ 
23114                     clearInterval(timer);
23115                     this.expand(deep, anim, callback);
23116                 }
23117             }.createDelegate(this);
23118             timer = setInterval(f, 200);
23119             return;
23120         }
23121         if(!this.loaded){
23122             if(this.fireEvent("beforeload", this) === false){
23123                 return;
23124             }
23125             this.loading = true;
23126             this.ui.beforeLoad(this);
23127             var loader = this.loader || this.attributes.loader || this.getOwnerTree().getLoader();
23128             if(loader){
23129                 loader.load(this, this.loadComplete.createDelegate(this, [deep, anim, callback]));
23130                 return;
23131             }
23132         }
23133         Ext.tree.AsyncTreeNode.superclass.expand.call(this, deep, anim, callback);
23134     },
23135     
23136     
23137     isLoading : function(){
23138         return this.loading;  
23139     },
23140     
23141     loadComplete : function(deep, anim, callback){
23142         this.loading = false;
23143         this.loaded = true;
23144         this.ui.afterLoad(this);
23145         this.fireEvent("load", this);
23146         this.expand(deep, anim, callback);
23147     },
23148     
23149     
23150     isLoaded : function(){
23151         return this.loaded;
23152     },
23153     
23154     hasChildNodes : function(){
23155         if(!this.isLeaf() && !this.loaded){
23156             return true;
23157         }else{
23158             return Ext.tree.AsyncTreeNode.superclass.hasChildNodes.call(this);
23159         }
23160     },
23161
23162     
23163     reload : function(callback){
23164         this.collapse(false, false);
23165         while(this.firstChild){
23166             this.removeChild(this.firstChild);
23167         }
23168         this.childrenRendered = false;
23169         this.loaded = false;
23170         if(this.isHiddenRoot()){
23171             this.expanded = false;
23172         }
23173         this.expand(false, false, callback);
23174     }
23175 });
23176
23177 Ext.tree.TreeNodeUI = function(node){
23178     this.node = node;
23179     this.rendered = false;
23180     this.animating = false;
23181     this.wasLeaf = true;
23182     this.ecc = 'x-tree-ec-icon x-tree-elbow';
23183     this.emptyIcon = Ext.BLANK_IMAGE_URL;
23184 };
23185
23186 Ext.tree.TreeNodeUI.prototype = {
23187     
23188     removeChild : function(node){
23189         if(this.rendered){
23190             this.ctNode.removeChild(node.ui.getEl());
23191         } 
23192     },
23193
23194     
23195     beforeLoad : function(){
23196          this.addClass("x-tree-node-loading");
23197     },
23198
23199     
23200     afterLoad : function(){
23201          this.removeClass("x-tree-node-loading");
23202     },
23203
23204     
23205     onTextChange : function(node, text, oldText){
23206         if(this.rendered){
23207             this.textNode.innerHTML = text;
23208         }
23209     },
23210
23211     
23212     onDisableChange : function(node, state){
23213         this.disabled = state;
23214                 if (this.checkbox) {
23215                         this.checkbox.disabled = state;
23216                 }        
23217         if(state){
23218             this.addClass("x-tree-node-disabled");
23219         }else{
23220             this.removeClass("x-tree-node-disabled");
23221         } 
23222     },
23223
23224     
23225     onSelectedChange : function(state){
23226         if(state){
23227             this.focus();
23228             this.addClass("x-tree-selected");
23229         }else{
23230             
23231             this.removeClass("x-tree-selected");
23232         }
23233     },
23234
23235     
23236     onMove : function(tree, node, oldParent, newParent, index, refNode){
23237         this.childIndent = null;
23238         if(this.rendered){
23239             var targetNode = newParent.ui.getContainer();
23240             if(!targetNode){
23241                 this.holder = document.createElement("div");
23242                 this.holder.appendChild(this.wrap);
23243                 return;
23244             }
23245             var insertBefore = refNode ? refNode.ui.getEl() : null;
23246             if(insertBefore){
23247                 targetNode.insertBefore(this.wrap, insertBefore);
23248             }else{
23249                 targetNode.appendChild(this.wrap);
23250             }
23251             this.node.renderIndent(true);
23252         }
23253     },
23254
23255
23256     addClass : function(cls){
23257         if(this.elNode){
23258             Ext.fly(this.elNode).addClass(cls);
23259         }
23260     },
23261
23262
23263     removeClass : function(cls){
23264         if(this.elNode){
23265             Ext.fly(this.elNode).removeClass(cls);  
23266         }
23267     },
23268
23269     
23270     remove : function(){
23271         if(this.rendered){
23272             this.holder = document.createElement("div");
23273             this.holder.appendChild(this.wrap);
23274         }  
23275     },
23276
23277     
23278     fireEvent : function(){
23279         return this.node.fireEvent.apply(this.node, arguments);  
23280     },
23281
23282     
23283     initEvents : function(){
23284         this.node.on("move", this.onMove, this);
23285
23286         if(this.node.disabled){
23287             this.addClass("x-tree-node-disabled");
23288                         if (this.checkbox) {
23289                                 this.checkbox.disabled = true;
23290                         }            
23291         }
23292         if(this.node.hidden){
23293             this.hide();
23294         }
23295         var ot = this.node.getOwnerTree();
23296         var dd = ot.enableDD || ot.enableDrag || ot.enableDrop;
23297         if(dd && (!this.node.isRoot || ot.rootVisible)){
23298             Ext.dd.Registry.register(this.elNode, {
23299                 node: this.node,
23300                 handles: this.getDDHandles(),
23301                 isHandle: false
23302             });
23303         }
23304     },
23305
23306     
23307     getDDHandles : function(){
23308         return [this.iconNode, this.textNode, this.elNode];
23309     },
23310
23311
23312     hide : function(){
23313         this.node.hidden = true;
23314         if(this.wrap){
23315             this.wrap.style.display = "none";
23316         }
23317     },
23318
23319
23320     show : function(){
23321         this.node.hidden = false;
23322         if(this.wrap){
23323             this.wrap.style.display = "";
23324         } 
23325     },
23326
23327     
23328     onContextMenu : function(e){
23329         if (this.node.hasListener("contextmenu") || this.node.getOwnerTree().hasListener("contextmenu")) {
23330             e.preventDefault();
23331             this.focus();
23332             this.fireEvent("contextmenu", this.node, e);
23333         }
23334     },
23335
23336     
23337     onClick : function(e){
23338         if(this.dropping){
23339             e.stopEvent();
23340             return;
23341         }
23342         if(this.fireEvent("beforeclick", this.node, e) !== false){
23343             var a = e.getTarget('a');
23344             if(!this.disabled && this.node.attributes.href && a){
23345                 this.fireEvent("click", this.node, e);
23346                 return;
23347             }else if(a && e.ctrlKey){
23348                 e.stopEvent();
23349             }
23350             e.preventDefault();
23351             if(this.disabled){
23352                 return;
23353             }
23354
23355             if(this.node.attributes.singleClickExpand && !this.animating && this.node.hasChildNodes()){
23356                 this.node.toggle();
23357             }
23358
23359             this.fireEvent("click", this.node, e);
23360         }else{
23361             e.stopEvent();
23362         }
23363     },
23364
23365     
23366     onDblClick : function(e){
23367         e.preventDefault();
23368         if(this.disabled){
23369             return;
23370         }
23371         if(this.checkbox){
23372             this.toggleCheck();
23373         }
23374         if(!this.animating && this.node.hasChildNodes()){
23375             this.node.toggle();
23376         }
23377         this.fireEvent("dblclick", this.node, e);
23378     },
23379
23380     onOver : function(e){
23381         this.addClass('x-tree-node-over');
23382     },
23383
23384     onOut : function(e){
23385         this.removeClass('x-tree-node-over');
23386     },
23387
23388     
23389     onCheckChange : function(){
23390         var checked = this.checkbox.checked;
23391         this.node.attributes.checked = checked;
23392         this.fireEvent('checkchange', this.node, checked);
23393     },
23394
23395     
23396     ecClick : function(e){
23397         if(!this.animating && (this.node.hasChildNodes() || this.node.attributes.expandable)){
23398             this.node.toggle();
23399         }
23400     },
23401
23402     
23403     startDrop : function(){
23404         this.dropping = true;
23405     },
23406     
23407     
23408     endDrop : function(){ 
23409        setTimeout(function(){
23410            this.dropping = false;
23411        }.createDelegate(this), 50); 
23412     },
23413
23414     
23415     expand : function(){
23416         this.updateExpandIcon();
23417         this.ctNode.style.display = "";
23418     },
23419
23420     
23421     focus : function(){
23422         if(!this.node.preventHScroll){
23423             try{this.anchor.focus();
23424             }catch(e){}
23425         }else if(!Ext.isIE){
23426             try{
23427                 var noscroll = this.node.getOwnerTree().getTreeEl().dom;
23428                 var l = noscroll.scrollLeft;
23429                 this.anchor.focus();
23430                 noscroll.scrollLeft = l;
23431             }catch(e){}
23432         }
23433     },
23434
23435
23436     toggleCheck : function(value){
23437         var cb = this.checkbox;
23438         if(cb){
23439             cb.checked = (value === undefined ? !cb.checked : value);
23440         }
23441     },
23442
23443     
23444     blur : function(){
23445         try{
23446             this.anchor.blur();
23447         }catch(e){} 
23448     },
23449
23450     
23451     animExpand : function(callback){
23452         var ct = Ext.get(this.ctNode);
23453         ct.stopFx();
23454         if(!this.node.hasChildNodes()){
23455             this.updateExpandIcon();
23456             this.ctNode.style.display = "";
23457             Ext.callback(callback);
23458             return;
23459         }
23460         this.animating = true;
23461         this.updateExpandIcon();
23462         
23463         ct.slideIn('t', {
23464            callback : function(){
23465                this.animating = false;
23466                Ext.callback(callback);
23467             },
23468             scope: this,
23469             duration: this.node.ownerTree.duration || .25
23470         });
23471     },
23472
23473     
23474     highlight : function(){
23475         var tree = this.node.getOwnerTree();
23476         Ext.fly(this.wrap).highlight(
23477             tree.hlColor || "C3DAF9",
23478             {endColor: tree.hlBaseColor}
23479         );
23480     },
23481
23482     
23483     collapse : function(){
23484         this.updateExpandIcon();
23485         this.ctNode.style.display = "none";
23486     },
23487
23488     
23489     animCollapse : function(callback){
23490         var ct = Ext.get(this.ctNode);
23491         ct.enableDisplayMode('block');
23492         ct.stopFx();
23493
23494         this.animating = true;
23495         this.updateExpandIcon();
23496
23497         ct.slideOut('t', {
23498             callback : function(){
23499                this.animating = false;
23500                Ext.callback(callback);
23501             },
23502             scope: this,
23503             duration: this.node.ownerTree.duration || .25
23504         });
23505     },
23506
23507     
23508     getContainer : function(){
23509         return this.ctNode;  
23510     },
23511
23512     
23513     getEl : function(){
23514         return this.wrap;  
23515     },
23516
23517     
23518     appendDDGhost : function(ghostNode){
23519         ghostNode.appendChild(this.elNode.cloneNode(true));
23520     },
23521
23522     
23523     getDDRepairXY : function(){
23524         return Ext.lib.Dom.getXY(this.iconNode);
23525     },
23526
23527     
23528     onRender : function(){
23529         this.render();    
23530     },
23531
23532     
23533     render : function(bulkRender){
23534         var n = this.node, a = n.attributes;
23535         var targetNode = n.parentNode ? 
23536               n.parentNode.ui.getContainer() : n.ownerTree.innerCt.dom;
23537         
23538         if(!this.rendered){
23539             this.rendered = true;
23540
23541             this.renderElements(n, a, targetNode, bulkRender);
23542
23543             if(a.qtip){
23544                if(this.textNode.setAttributeNS){
23545                    this.textNode.setAttributeNS("ext", "qtip", a.qtip);
23546                    if(a.qtipTitle){
23547                        this.textNode.setAttributeNS("ext", "qtitle", a.qtipTitle);
23548                    }
23549                }else{
23550                    this.textNode.setAttribute("ext:qtip", a.qtip);
23551                    if(a.qtipTitle){
23552                        this.textNode.setAttribute("ext:qtitle", a.qtipTitle);
23553                    }
23554                } 
23555             }else if(a.qtipCfg){
23556                 a.qtipCfg.target = Ext.id(this.textNode);
23557                 Ext.QuickTips.register(a.qtipCfg);
23558             }
23559             this.initEvents();
23560             if(!this.node.expanded){
23561                 this.updateExpandIcon(true);
23562             }
23563         }else{
23564             if(bulkRender === true) {
23565                 targetNode.appendChild(this.wrap);
23566             }
23567         }
23568     },
23569
23570     
23571     renderElements : function(n, a, targetNode, bulkRender){
23572         
23573         this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';
23574
23575         var cb = typeof a.checked == 'boolean';
23576
23577         var href = a.href ? a.href : Ext.isGecko ? "" : "#";
23578         var 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">',
23579             '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",
23580             '<img src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow" />',
23581             '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on" />',
23582             cb ? ('<input class="x-tree-node-cb" type="checkbox" ' + (a.checked ? 'checked="checked" />' : '/>')) : '',
23583             '<a hidefocus="on" class="x-tree-node-anchor" href="',href,'" tabIndex="1" ',
23584              a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", '><span unselectable="on">',n.text,"</span></a></div>",
23585             '<ul class="x-tree-node-ct" style="display:none;"></ul>',
23586             "</li>"].join('');
23587
23588         var nel;
23589         if(bulkRender !== true && n.nextSibling && (nel = n.nextSibling.ui.getEl())){
23590             this.wrap = Ext.DomHelper.insertHtml("beforeBegin", nel, buf);
23591         }else{
23592             this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf);
23593         }
23594         
23595         this.elNode = this.wrap.childNodes[0];
23596         this.ctNode = this.wrap.childNodes[1];
23597         var cs = this.elNode.childNodes;
23598         this.indentNode = cs[0];
23599         this.ecNode = cs[1];
23600         this.iconNode = cs[2];
23601         var index = 3;
23602         if(cb){
23603             this.checkbox = cs[3];
23604             index++;
23605         }
23606         this.anchor = cs[index];
23607         this.textNode = cs[index].firstChild;
23608     },
23609
23610
23611     getAnchor : function(){
23612         return this.anchor;
23613     },
23614     
23615
23616     getTextEl : function(){
23617         return this.textNode;
23618     },
23619     
23620
23621     getIconEl : function(){
23622         return this.iconNode;
23623     },
23624
23625
23626     isChecked : function(){
23627         return this.checkbox ? this.checkbox.checked : false; 
23628     },
23629
23630     
23631     updateExpandIcon : function(){
23632         if(this.rendered){
23633             var n = this.node, c1, c2;
23634             var cls = n.isLast() ? "x-tree-elbow-end" : "x-tree-elbow";
23635             var hasChild = n.hasChildNodes();
23636             if(hasChild || n.attributes.expandable){
23637                 if(n.expanded){
23638                     cls += "-minus";
23639                     c1 = "x-tree-node-collapsed";
23640                     c2 = "x-tree-node-expanded";
23641                 }else{
23642                     cls += "-plus";
23643                     c1 = "x-tree-node-expanded";
23644                     c2 = "x-tree-node-collapsed";
23645                 }
23646                 if(this.wasLeaf){
23647                     this.removeClass("x-tree-node-leaf");
23648                     this.wasLeaf = false;
23649                 }
23650                 if(this.c1 != c1 || this.c2 != c2){
23651                     Ext.fly(this.elNode).replaceClass(c1, c2);
23652                     this.c1 = c1; this.c2 = c2;
23653                 }
23654             }else{
23655                 if(!this.wasLeaf){
23656                     Ext.fly(this.elNode).replaceClass("x-tree-node-expanded", "x-tree-node-leaf");
23657                     delete this.c1;
23658                     delete this.c2;
23659                     this.wasLeaf = true;
23660                 }
23661             }
23662             var ecc = "x-tree-ec-icon "+cls;
23663             if(this.ecc != ecc){
23664                 this.ecNode.className = ecc;
23665                 this.ecc = ecc;
23666             }
23667         }
23668     },
23669
23670     
23671     getChildIndent : function(){
23672         if(!this.childIndent){
23673             var buf = [];
23674             var p = this.node;
23675             while(p){
23676                 if(!p.isRoot || (p.isRoot && p.ownerTree.rootVisible)){
23677                     if(!p.isLast()) {
23678                         buf.unshift('<img src="'+this.emptyIcon+'" class="x-tree-elbow-line" />');
23679                     } else {
23680                         buf.unshift('<img src="'+this.emptyIcon+'" class="x-tree-icon" />');
23681                     }
23682                 }
23683                 p = p.parentNode;
23684             }
23685             this.childIndent = buf.join("");
23686         }
23687         return this.childIndent;
23688     },
23689
23690     
23691     renderIndent : function(){
23692         if(this.rendered){
23693             var indent = "";
23694             var p = this.node.parentNode;
23695             if(p){
23696                 indent = p.ui.getChildIndent();
23697             }
23698             if(this.indentMarkup != indent){ 
23699                 this.indentNode.innerHTML = indent;
23700                 this.indentMarkup = indent;
23701             }
23702             this.updateExpandIcon();
23703         }
23704     },
23705
23706     destroy : function(){
23707         if(this.elNode){
23708             Ext.dd.Registry.unregister(this.elNode.id);
23709         }
23710         delete this.elNode;
23711         delete this.ctNode;
23712         delete this.indentNode;
23713         delete this.ecNode;
23714         delete this.iconNode;
23715         delete this.checkbox;
23716         delete this.anchor;
23717         delete this.textNode;
23718         Ext.removeNode(this.ctNode);
23719     }
23720 };
23721
23722
23723 Ext.tree.RootTreeNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
23724     
23725     render : function(){
23726         if(!this.rendered){
23727             var targetNode = this.node.ownerTree.innerCt.dom;
23728             this.node.expanded = true;
23729             targetNode.innerHTML = '<div class="x-tree-root-node"></div>';
23730             this.wrap = this.ctNode = targetNode.firstChild;
23731         }
23732     },
23733     collapse : Ext.emptyFn,
23734     expand : Ext.emptyFn
23735 });
23736
23737 Ext.tree.TreeLoader = function(config){
23738     this.baseParams = {};
23739     this.requestMethod = "POST";
23740     Ext.apply(this, config);
23741
23742     this.addEvents(
23743         
23744         "beforeload",
23745         
23746         "load",
23747         
23748         "loadexception"
23749     );
23750
23751     Ext.tree.TreeLoader.superclass.constructor.call(this);
23752 };
23753
23754 Ext.extend(Ext.tree.TreeLoader, Ext.util.Observable, {
23755     
23756     
23757     
23758     
23759     
23760     
23761     
23762     uiProviders : {},
23763
23764     
23765     clearOnLoad : true,
23766
23767     
23768     load : function(node, callback){
23769         if(this.clearOnLoad){
23770             while(node.firstChild){
23771                 node.removeChild(node.firstChild);
23772             }
23773         }
23774         if(this.doPreload(node)){ 
23775             if(typeof callback == "function"){
23776                 callback();
23777             }
23778         }else if(this.dataUrl||this.url){
23779             this.requestData(node, callback);
23780         }
23781     },
23782
23783     doPreload : function(node){
23784         if(node.attributes.children){
23785             if(node.childNodes.length < 1){ 
23786                 var cs = node.attributes.children;
23787                 node.beginUpdate();
23788                 for(var i = 0, len = cs.length; i < len; i++){
23789                     var cn = node.appendChild(this.createNode(cs[i]));
23790                     if(this.preloadChildren){
23791                         this.doPreload(cn);
23792                     }
23793                 }
23794                 node.endUpdate();
23795             }
23796             return true;
23797         }else {
23798             return false;
23799         }
23800     },
23801
23802     getParams: function(node){
23803         var buf = [], bp = this.baseParams;
23804         for(var key in bp){
23805             if(typeof bp[key] != "function"){
23806                 buf.push(encodeURIComponent(key), "=", encodeURIComponent(bp[key]), "&");
23807             }
23808         }
23809         buf.push("node=", encodeURIComponent(node.id));
23810         return buf.join("");
23811     },
23812
23813     requestData : function(node, callback){
23814         if(this.fireEvent("beforeload", this, node, callback) !== false){
23815             this.transId = Ext.Ajax.request({
23816                 method:this.requestMethod,
23817                 url: this.dataUrl||this.url,
23818                 success: this.handleResponse,
23819                 failure: this.handleFailure,
23820                 scope: this,
23821                 argument: {callback: callback, node: node},
23822                 params: this.getParams(node)
23823             });
23824         }else{
23825             
23826             
23827             if(typeof callback == "function"){
23828                 callback();
23829             }
23830         }
23831     },
23832
23833     isLoading : function(){
23834         return this.transId ? true : false;
23835     },
23836
23837     abort : function(){
23838         if(this.isLoading()){
23839             Ext.Ajax.abort(this.transId);
23840         }
23841     },
23842
23843     
23844     createNode : function(attr){
23845         
23846         if(this.baseAttrs){
23847             Ext.applyIf(attr, this.baseAttrs);
23848         }
23849         if(this.applyLoader !== false){
23850             attr.loader = this;
23851         }
23852         if(typeof attr.uiProvider == 'string'){
23853            attr.uiProvider = this.uiProviders[attr.uiProvider] || eval(attr.uiProvider);
23854         }
23855         return(attr.leaf ?
23856                         new Ext.tree.TreeNode(attr) :
23857                         new Ext.tree.AsyncTreeNode(attr));
23858     },
23859
23860     processResponse : function(response, node, callback){
23861         var json = response.responseText;
23862         try {
23863             var o = eval("("+json+")");
23864             node.beginUpdate();
23865             for(var i = 0, len = o.length; i < len; i++){
23866                 var n = this.createNode(o[i]);
23867                 if(n){
23868                     node.appendChild(n);
23869                 }
23870             }
23871             node.endUpdate();
23872             if(typeof callback == "function"){
23873                 callback(this, node);
23874             }
23875         }catch(e){
23876             this.handleFailure(response);
23877         }
23878     },
23879
23880     handleResponse : function(response){
23881         this.transId = false;
23882         var a = response.argument;
23883         this.processResponse(response, a.node, a.callback);
23884         this.fireEvent("load", this, a.node, response);
23885     },
23886
23887     handleFailure : function(response){
23888         this.transId = false;
23889         var a = response.argument;
23890         this.fireEvent("loadexception", this, a.node, response);
23891         if(typeof a.callback == "function"){
23892             a.callback(this, a.node);
23893         }
23894     }
23895 });
23896
23897 Ext.tree.TreeFilter = function(tree, config){
23898     this.tree = tree;
23899     this.filtered = {};
23900     Ext.apply(this, config);
23901 };
23902
23903 Ext.tree.TreeFilter.prototype = {
23904     clearBlank:false,
23905     reverse:false,
23906     autoClear:false,
23907     remove:false,
23908
23909      
23910     filter : function(value, attr, startNode){
23911         attr = attr || "text";
23912         var f;
23913         if(typeof value == "string"){
23914             var vlen = value.length;
23915             
23916             if(vlen == 0 && this.clearBlank){
23917                 this.clear();
23918                 return;
23919             }
23920             value = value.toLowerCase();
23921             f = function(n){
23922                 return n.attributes[attr].substr(0, vlen).toLowerCase() == value;
23923             };
23924         }else if(value.exec){ 
23925             f = function(n){
23926                 return value.test(n.attributes[attr]);
23927             };
23928         }else{
23929             throw 'Illegal filter type, must be string or regex';
23930         }
23931         this.filterBy(f, null, startNode);
23932         },
23933     
23934     
23935     filterBy : function(fn, scope, startNode){
23936         startNode = startNode || this.tree.root;
23937         if(this.autoClear){
23938             this.clear();
23939         }
23940         var af = this.filtered, rv = this.reverse;
23941         var f = function(n){
23942             if(n == startNode){
23943                 return true;
23944             }
23945             if(af[n.id]){
23946                 return false;
23947             }
23948             var m = fn.call(scope || n, n);
23949             if(!m || rv){
23950                 af[n.id] = n;
23951                 n.ui.hide();
23952                 return false;
23953             }
23954             return true;
23955         };
23956         startNode.cascade(f);
23957         if(this.remove){
23958            for(var id in af){
23959                if(typeof id != "function"){
23960                    var n = af[id];
23961                    if(n && n.parentNode){
23962                        n.parentNode.removeChild(n);
23963                    }
23964                }
23965            } 
23966         }
23967     },
23968     
23969     
23970     clear : function(){
23971         var t = this.tree;
23972         var af = this.filtered;
23973         for(var id in af){
23974             if(typeof id != "function"){
23975                 var n = af[id];
23976                 if(n){
23977                     n.ui.show();
23978                 }
23979             }
23980         }
23981         this.filtered = {}; 
23982     }
23983 };
23984
23985
23986 Ext.tree.TreeSorter = function(tree, config){
23987     Ext.apply(this, config);
23988     tree.on("beforechildrenrendered", this.doSort, this);
23989     tree.on("append", this.updateSort, this);
23990     tree.on("insert", this.updateSort, this);
23991     tree.on("textchange", this.updateSortParent, this);
23992     
23993     var dsc = this.dir && this.dir.toLowerCase() == "desc";
23994     var p = this.property || "text";
23995     var sortType = this.sortType;
23996     var fs = this.folderSort;
23997     var cs = this.caseSensitive === true;
23998     var leafAttr = this.leafAttr || 'leaf';
23999
24000     this.sortFn = function(n1, n2){
24001         if(fs){
24002             if(n1.attributes[leafAttr] && !n2.attributes[leafAttr]){
24003                 return 1;
24004             }
24005             if(!n1.attributes[leafAttr] && n2.attributes[leafAttr]){
24006                 return -1;
24007             }
24008         }
24009         var v1 = sortType ? sortType(n1) : (cs ? n1.attributes[p] : n1.attributes[p].toUpperCase());
24010         var v2 = sortType ? sortType(n2) : (cs ? n2.attributes[p] : n2.attributes[p].toUpperCase());
24011         if(v1 < v2){
24012                         return dsc ? +1 : -1;
24013                 }else if(v1 > v2){
24014                         return dsc ? -1 : +1;
24015         }else{
24016                 return 0;
24017         }
24018     };
24019 };
24020
24021 Ext.tree.TreeSorter.prototype = {
24022     doSort : function(node){
24023         node.sort(this.sortFn);
24024     },
24025     
24026     compareNodes : function(n1, n2){
24027         return (n1.text.toUpperCase() > n2.text.toUpperCase() ? 1 : -1);
24028     },
24029     
24030     updateSort : function(tree, node){
24031         if(node.childrenRendered){
24032             this.doSort.defer(1, this, [node]);
24033         }
24034     },
24035     
24036     updateSortParent : function(node){
24037                 var p = node.parentNode;
24038                 if(p && p.childrenRendered){
24039             this.doSort.defer(1, this, [p]);
24040         }
24041     }
24042 };
24043
24044 if(Ext.dd.DropZone){
24045     
24046 Ext.tree.TreeDropZone = function(tree, config){
24047     
24048     this.allowParentInsert = false;
24049     
24050     this.allowContainerDrop = false;
24051     
24052     this.appendOnly = false;
24053     Ext.tree.TreeDropZone.superclass.constructor.call(this, tree.innerCt, config);
24054     
24055     this.tree = tree;
24056     
24057     this.dragOverData = {};
24058     
24059     this.lastInsertClass = "x-tree-no-status";
24060 };
24061
24062 Ext.extend(Ext.tree.TreeDropZone, Ext.dd.DropZone, {
24063     
24064     ddGroup : "TreeDD",
24065
24066     
24067     expandDelay : 1000,
24068
24069     
24070     expandNode : function(node){
24071         if(node.hasChildNodes() && !node.isExpanded()){
24072             node.expand(false, null, this.triggerCacheRefresh.createDelegate(this));
24073         }
24074     },
24075
24076     
24077     queueExpand : function(node){
24078         this.expandProcId = this.expandNode.defer(this.expandDelay, this, [node]);
24079     },
24080
24081     
24082     cancelExpand : function(){
24083         if(this.expandProcId){
24084             clearTimeout(this.expandProcId);
24085             this.expandProcId = false;
24086         }
24087     },
24088
24089     
24090     isValidDropPoint : function(n, pt, dd, e, data){
24091         if(!n || !data){ return false; }
24092         var targetNode = n.node;
24093         var dropNode = data.node;
24094         
24095         if(!(targetNode && targetNode.isTarget && pt)){
24096             return false;
24097         }
24098         if(pt == "append" && targetNode.allowChildren === false){
24099             return false;
24100         }
24101         if((pt == "above" || pt == "below") && (targetNode.parentNode && targetNode.parentNode.allowChildren === false)){
24102             return false;
24103         }
24104         if(dropNode && (targetNode == dropNode || dropNode.contains(targetNode))){
24105             return false;
24106         }
24107         
24108         var overEvent = this.dragOverData;
24109         overEvent.tree = this.tree;
24110         overEvent.target = targetNode;
24111         overEvent.data = data;
24112         overEvent.point = pt;
24113         overEvent.source = dd;
24114         overEvent.rawEvent = e;
24115         overEvent.dropNode = dropNode;
24116         overEvent.cancel = false;  
24117         var result = this.tree.fireEvent("nodedragover", overEvent);
24118         return overEvent.cancel === false && result !== false;
24119     },
24120
24121     
24122     getDropPoint : function(e, n, dd){
24123         var tn = n.node;
24124         if(tn.isRoot){
24125             return tn.allowChildren !== false ? "append" : false; 
24126         }
24127         var dragEl = n.ddel;
24128         var t = Ext.lib.Dom.getY(dragEl), b = t + dragEl.offsetHeight;
24129         var y = Ext.lib.Event.getPageY(e);
24130         var noAppend = tn.allowChildren === false || tn.isLeaf();
24131         if(this.appendOnly || tn.parentNode.allowChildren === false){
24132             return noAppend ? false : "append";
24133         }
24134         var noBelow = false;
24135         if(!this.allowParentInsert){
24136             noBelow = tn.hasChildNodes() && tn.isExpanded();
24137         }
24138         var q = (b - t) / (noAppend ? 2 : 3);
24139         if(y >= t && y < (t + q)){
24140             return "above";
24141         }else if(!noBelow && (noAppend || y >= b-q && y <= b)){
24142             return "below";
24143         }else{
24144             return "append";
24145         }
24146     },
24147
24148     
24149     onNodeEnter : function(n, dd, e, data){
24150         this.cancelExpand();
24151     },
24152
24153     
24154     onNodeOver : function(n, dd, e, data){
24155         var pt = this.getDropPoint(e, n, dd);
24156         var node = n.node;
24157         
24158         
24159         if(!this.expandProcId && pt == "append" && node.hasChildNodes() && !n.node.isExpanded()){
24160             this.queueExpand(node);
24161         }else if(pt != "append"){
24162             this.cancelExpand();
24163         }
24164         
24165         
24166         var returnCls = this.dropNotAllowed;
24167         if(this.isValidDropPoint(n, pt, dd, e, data)){
24168            if(pt){
24169                var el = n.ddel;
24170                var cls;
24171                if(pt == "above"){
24172                    returnCls = n.node.isFirst() ? "x-tree-drop-ok-above" : "x-tree-drop-ok-between";
24173                    cls = "x-tree-drag-insert-above";
24174                }else if(pt == "below"){
24175                    returnCls = n.node.isLast() ? "x-tree-drop-ok-below" : "x-tree-drop-ok-between";
24176                    cls = "x-tree-drag-insert-below";
24177                }else{
24178                    returnCls = "x-tree-drop-ok-append";
24179                    cls = "x-tree-drag-append";
24180                }
24181                if(this.lastInsertClass != cls){
24182                    Ext.fly(el).replaceClass(this.lastInsertClass, cls);
24183                    this.lastInsertClass = cls;
24184                }
24185            }
24186        }
24187        return returnCls;
24188     },
24189
24190     
24191     onNodeOut : function(n, dd, e, data){
24192         this.cancelExpand();
24193         this.removeDropIndicators(n);
24194     },
24195
24196     
24197     onNodeDrop : function(n, dd, e, data){
24198         var point = this.getDropPoint(e, n, dd);
24199         var targetNode = n.node;
24200         targetNode.ui.startDrop();
24201         if(!this.isValidDropPoint(n, point, dd, e, data)){
24202             targetNode.ui.endDrop();
24203             return false;
24204         }
24205         
24206         var dropNode = data.node || (dd.getTreeNode ? dd.getTreeNode(data, targetNode, point, e) : null);
24207         var dropEvent = {
24208             tree : this.tree,
24209             target: targetNode,
24210             data: data,
24211             point: point,
24212             source: dd,
24213             rawEvent: e,
24214             dropNode: dropNode,
24215             cancel: !dropNode,
24216             dropStatus: false
24217         };
24218         var retval = this.tree.fireEvent("beforenodedrop", dropEvent);
24219         if(retval === false || dropEvent.cancel === true || !dropEvent.dropNode){
24220             targetNode.ui.endDrop();
24221             return dropEvent.dropStatus;
24222         }
24223         
24224         targetNode = dropEvent.target;
24225         if(point == "append" && !targetNode.isExpanded()){
24226             targetNode.expand(false, null, function(){
24227                 this.completeDrop(dropEvent);
24228             }.createDelegate(this));
24229         }else{
24230             this.completeDrop(dropEvent);
24231         }
24232         return true;
24233     },
24234
24235     
24236     completeDrop : function(de){
24237         var ns = de.dropNode, p = de.point, t = de.target;
24238         if(!Ext.isArray(ns)){
24239             ns = [ns];
24240         }
24241         var n;
24242         for(var i = 0, len = ns.length; i < len; i++){
24243             n = ns[i];
24244             if(p == "above"){
24245                 t.parentNode.insertBefore(n, t);
24246             }else if(p == "below"){
24247                 t.parentNode.insertBefore(n, t.nextSibling);
24248             }else{
24249                 t.appendChild(n);
24250             }
24251         }
24252         n.ui.focus();
24253         if(this.tree.hlDrop){
24254             n.ui.highlight();
24255         }
24256         t.ui.endDrop();
24257         this.tree.fireEvent("nodedrop", de);
24258     },
24259
24260     
24261     afterNodeMoved : function(dd, data, e, targetNode, dropNode){
24262         if(this.tree.hlDrop){
24263             dropNode.ui.focus();
24264             dropNode.ui.highlight();
24265         }
24266         this.tree.fireEvent("nodedrop", this.tree, targetNode, data, dd, e);
24267     },
24268
24269     
24270     getTree : function(){
24271         return this.tree;
24272     },
24273
24274     
24275     removeDropIndicators : function(n){
24276         if(n && n.ddel){
24277             var el = n.ddel;
24278             Ext.fly(el).removeClass([
24279                     "x-tree-drag-insert-above",
24280                     "x-tree-drag-insert-below",
24281                     "x-tree-drag-append"]);
24282             this.lastInsertClass = "_noclass";
24283         }
24284     },
24285
24286     
24287     beforeDragDrop : function(target, e, id){
24288         this.cancelExpand();
24289         return true;
24290     },
24291
24292     
24293     afterRepair : function(data){
24294         if(data && Ext.enableFx){
24295             data.node.ui.highlight();
24296         }
24297         this.hideProxy();
24298     }    
24299 });
24300
24301 }
24302
24303 if(Ext.dd.DragZone){
24304 Ext.tree.TreeDragZone = function(tree, config){
24305     Ext.tree.TreeDragZone.superclass.constructor.call(this, tree.getTreeEl(), config);
24306     
24307     this.tree = tree;
24308 };
24309
24310 Ext.extend(Ext.tree.TreeDragZone, Ext.dd.DragZone, {
24311     
24312     ddGroup : "TreeDD",
24313
24314     
24315     onBeforeDrag : function(data, e){
24316         var n = data.node;
24317         return n && n.draggable && !n.disabled;
24318     },
24319
24320     
24321     onInitDrag : function(e){
24322         var data = this.dragData;
24323         this.tree.getSelectionModel().select(data.node);
24324         this.tree.eventModel.disable();
24325         this.proxy.update("");
24326         data.node.ui.appendDDGhost(this.proxy.ghost.dom);
24327         this.tree.fireEvent("startdrag", this.tree, data.node, e);
24328     },
24329
24330     
24331     getRepairXY : function(e, data){
24332         return data.node.ui.getDDRepairXY();
24333     },
24334
24335     
24336     onEndDrag : function(data, e){
24337         this.tree.eventModel.enable.defer(100, this.tree.eventModel);
24338         this.tree.fireEvent("enddrag", this.tree, data.node, e);
24339     },
24340
24341     
24342     onValidDrop : function(dd, e, id){
24343         this.tree.fireEvent("dragdrop", this.tree, this.dragData.node, dd, e);
24344         this.hideProxy();
24345     },
24346
24347     
24348     beforeInvalidDrop : function(e, id){
24349         
24350         var sm = this.tree.getSelectionModel();
24351         sm.clearSelections();
24352         sm.select(this.dragData.node);
24353     }
24354 });
24355 }
24356
24357 Ext.tree.TreeEditor = function(tree, config){
24358     config = config || {};
24359     var field = config.events ? config : new Ext.form.TextField(config);
24360     Ext.tree.TreeEditor.superclass.constructor.call(this, field);
24361
24362     this.tree = tree;
24363
24364     if(!tree.rendered){
24365         tree.on('render', this.initEditor, this);
24366     }else{
24367         this.initEditor(tree);
24368     }
24369 };
24370
24371 Ext.extend(Ext.tree.TreeEditor, Ext.Editor, {
24372     
24373     alignment: "l-l",
24374         autoSize: false,
24375     
24376     hideEl : false,
24377     
24378     cls: "x-small-editor x-tree-editor",
24379     
24380     shim:false,
24381         shadow:"frame",
24382     
24383     maxWidth: 250,
24384     
24385     editDelay : 350,
24386
24387     initEditor : function(tree){
24388         tree.on('beforeclick', this.beforeNodeClick, this);
24389         tree.on('dblclick', this.onNodeDblClick, this);
24390         this.on('complete', this.updateNode, this);
24391         this.on('beforestartedit', this.fitToTree, this);
24392         this.on('startedit', this.bindScroll, this, {delay:10});
24393         this.on('specialkey', this.onSpecialKey, this);
24394     },
24395
24396         fitToTree : function(ed, el){
24397         var td = this.tree.getTreeEl().dom, nd = el.dom;
24398         if(td.scrollLeft >  nd.offsetLeft){             td.scrollLeft = nd.offsetLeft;
24399         }
24400         var w = Math.min(
24401                 this.maxWidth,
24402                 (td.clientWidth > 20 ? td.clientWidth : td.offsetWidth) - Math.max(0, nd.offsetLeft-td.scrollLeft) - 5);
24403         this.setSize(w, '');
24404     },
24405
24406         triggerEdit : function(node, defer){
24407         this.completeEdit();
24408                 if(node.attributes.editable !== false){
24409                         this.editNode = node;
24410             this.autoEditTimer = this.startEdit.defer(this.editDelay, this, [node.ui.textNode, node.text]);
24411             return false;
24412         }
24413     },
24414
24415         bindScroll : function(){
24416         this.tree.getTreeEl().on('scroll', this.cancelEdit, this);
24417     },
24418
24419         beforeNodeClick : function(node, e){
24420         clearTimeout(this.autoEditTimer);
24421         if(this.tree.getSelectionModel().isSelected(node)){
24422             e.stopEvent();
24423             return this.triggerEdit(node);
24424         }
24425     },
24426
24427     onNodeDblClick : function(node, e){
24428         clearTimeout(this.autoEditTimer);
24429     },
24430
24431         updateNode : function(ed, value){
24432         this.tree.getTreeEl().un('scroll', this.cancelEdit, this);
24433         this.editNode.setText(value);
24434     },
24435
24436         onHide : function(){
24437         Ext.tree.TreeEditor.superclass.onHide.call(this);
24438         if(this.editNode){
24439             this.editNode.ui.focus.defer(50, this.editNode.ui);
24440         }
24441     },
24442
24443         onSpecialKey : function(field, e){
24444         var k = e.getKey();
24445         if(k == e.ESC){
24446             e.stopEvent();
24447             this.cancelEdit();
24448         }else if(k == e.ENTER && !e.hasModifier()){
24449             e.stopEvent();
24450             this.completeEdit();
24451         }
24452     }
24453 });
24454
24455 Ext.menu.Menu = function(config){
24456     if(Ext.isArray(config)){
24457         config = {items:config};
24458     }
24459     Ext.apply(this, config);
24460     this.id = this.id || Ext.id();
24461     this.addEvents(
24462         
24463         'beforeshow',
24464         
24465         'beforehide',
24466         
24467         'show',
24468         
24469         'hide',
24470         
24471         'click',
24472         
24473         'mouseover',
24474         
24475         'mouseout',
24476         
24477         'itemclick'
24478     );
24479     Ext.menu.MenuMgr.register(this);
24480     Ext.menu.Menu.superclass.constructor.call(this);
24481     var mis = this.items;
24482     
24483
24484     this.items = new Ext.util.MixedCollection();
24485     if(mis){
24486         this.add.apply(this, mis);
24487     }
24488 };
24489
24490 Ext.extend(Ext.menu.Menu, Ext.util.Observable, {
24491     
24492     
24493     
24494     minWidth : 120,
24495     
24496     shadow : "sides",
24497     
24498     subMenuAlign : "tl-tr?",
24499     
24500     defaultAlign : "tl-bl?",
24501     
24502     allowOtherMenus : false,
24503
24504     hidden:true,
24505
24506     createEl : function(){
24507         return new Ext.Layer({
24508             cls: "x-menu",
24509             shadow:this.shadow,
24510             constrain: false,
24511             parentEl: this.parentEl || document.body,
24512             zindex:15000
24513         });
24514     },
24515
24516         render : function(){
24517         if(this.el){
24518             return;
24519         }
24520         var el = this.el = this.createEl();
24521
24522         if(!this.keyNav){
24523             this.keyNav = new Ext.menu.MenuNav(this);
24524         }
24525         if(this.plain){
24526             el.addClass("x-menu-plain");
24527         }
24528         if(this.cls){
24529             el.addClass(this.cls);
24530         }
24531                 this.focusEl = el.createChild({
24532             tag: "a", cls: "x-menu-focus", href: "#", onclick: "return false;", tabIndex:"-1"
24533         });
24534         var ul = el.createChild({tag: "ul", cls: "x-menu-list"});
24535         ul.on("click", this.onClick, this);
24536         ul.on("mouseover", this.onMouseOver, this);
24537         ul.on("mouseout", this.onMouseOut, this);
24538         this.items.each(function(item){
24539             var li = document.createElement("li");
24540             li.className = "x-menu-list-item";
24541             ul.dom.appendChild(li);
24542             item.render(li, this);
24543         }, this);
24544         this.ul = ul;
24545         this.autoWidth();
24546     },
24547
24548         autoWidth : function(){
24549         var el = this.el, ul = this.ul;
24550         if(!el){
24551             return;
24552         }
24553         var w = this.width;
24554         if(w){
24555             el.setWidth(w);
24556         }else if(Ext.isIE){
24557             el.setWidth(this.minWidth);
24558             var t = el.dom.offsetWidth;             el.setWidth(ul.getWidth()+el.getFrameWidth("lr"));
24559         }
24560     },
24561
24562         delayAutoWidth : function(){
24563         if(this.el){
24564             if(!this.awTask){
24565                 this.awTask = new Ext.util.DelayedTask(this.autoWidth, this);
24566             }
24567             this.awTask.delay(20);
24568         }
24569     },
24570
24571         findTargetItem : function(e){
24572         var t = e.getTarget(".x-menu-list-item", this.ul,  true);
24573         if(t && t.menuItemId){
24574             return this.items.get(t.menuItemId);
24575         }
24576     },
24577
24578         onClick : function(e){
24579         var t;
24580         if(t = this.findTargetItem(e)){
24581             t.onClick(e);
24582             this.fireEvent("click", this, t, e);
24583         }
24584     },
24585
24586         setActiveItem : function(item, autoExpand){
24587         if(item != this.activeItem){
24588             if(this.activeItem){
24589                 this.activeItem.deactivate();
24590             }
24591             this.activeItem = item;
24592             item.activate(autoExpand);
24593         }else if(autoExpand){
24594             item.expandMenu();
24595         }
24596     },
24597
24598         tryActivate : function(start, step){
24599         var items = this.items;
24600         for(var i = start, len = items.length; i >= 0 && i < len; i+= step){
24601             var item = items.get(i);
24602             if(!item.disabled && item.canActivate){
24603                 this.setActiveItem(item, false);
24604                 return item;
24605             }
24606         }
24607         return false;
24608     },
24609
24610         onMouseOver : function(e){
24611         var t;
24612         if(t = this.findTargetItem(e)){
24613             if(t.canActivate && !t.disabled){
24614                 this.setActiveItem(t, true);
24615             }
24616         }
24617         this.fireEvent("mouseover", this, e, t);
24618     },
24619
24620         onMouseOut : function(e){
24621         var t;
24622         if(t = this.findTargetItem(e)){
24623             if(t == this.activeItem && t.shouldDeactivate(e)){
24624                 this.activeItem.deactivate();
24625                 delete this.activeItem;
24626             }
24627         }
24628         this.fireEvent("mouseout", this, e, t);
24629     },
24630
24631     
24632     isVisible : function(){
24633         return this.el && !this.hidden;
24634     },
24635
24636     
24637     show : function(el, pos, parentMenu){
24638         this.parentMenu = parentMenu;
24639         if(!this.el){
24640             this.render();
24641         }
24642         this.fireEvent("beforeshow", this);
24643         this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign), parentMenu, false);
24644     },
24645
24646     
24647     showAt : function(xy, parentMenu, _e){
24648         this.parentMenu = parentMenu;
24649         if(!this.el){
24650             this.render();
24651         }
24652         if(_e !== false){
24653             this.fireEvent("beforeshow", this);
24654             xy = this.el.adjustForConstraints(xy);
24655         }
24656         this.el.setXY(xy);
24657         this.el.show();
24658         this.hidden = false;
24659         this.focus();
24660         this.fireEvent("show", this);
24661     },
24662
24663     
24664
24665     focus : function(){
24666         if(!this.hidden){
24667             this.doFocus.defer(50, this);
24668         }
24669     },
24670
24671     doFocus : function(){
24672         if(!this.hidden){
24673             this.focusEl.focus();
24674         }
24675     },
24676
24677     
24678     hide : function(deep){
24679         if(this.el && this.isVisible()){
24680             this.fireEvent("beforehide", this);
24681             if(this.activeItem){
24682                 this.activeItem.deactivate();
24683                 this.activeItem = null;
24684             }
24685             this.el.hide();
24686             this.hidden = true;
24687             this.fireEvent("hide", this);
24688         }
24689         if(deep === true && this.parentMenu){
24690             this.parentMenu.hide(true);
24691         }
24692     },
24693
24694     
24695     add : function(){
24696         var a = arguments, l = a.length, item;
24697         for(var i = 0; i < l; i++){
24698             var el = a[i];
24699             if(el.render){                 item = this.addItem(el);
24700             }else if(typeof el == "string"){                 if(el == "separator" || el == "-"){
24701                     item = this.addSeparator();
24702                 }else{
24703                     item = this.addText(el);
24704                 }
24705             }else if(el.tagName || el.el){                 item = this.addElement(el);
24706             }else if(typeof el == "object"){                 Ext.applyIf(el, this.defaults);
24707                 item = this.addMenuItem(el);
24708             }
24709         }
24710         return item;
24711     },
24712
24713     
24714     getEl : function(){
24715         if(!this.el){
24716             this.render();
24717         }
24718         return this.el;
24719     },
24720
24721     
24722     addSeparator : function(){
24723         return this.addItem(new Ext.menu.Separator());
24724     },
24725
24726     
24727     addElement : function(el){
24728         return this.addItem(new Ext.menu.BaseItem(el));
24729     },
24730
24731     
24732     addItem : function(item){
24733         this.items.add(item);
24734         if(this.ul){
24735             var li = document.createElement("li");
24736             li.className = "x-menu-list-item";
24737             this.ul.dom.appendChild(li);
24738             item.render(li, this);
24739             this.delayAutoWidth();
24740         }
24741         return item;
24742     },
24743
24744     
24745     addMenuItem : function(config){
24746         if(!(config instanceof Ext.menu.Item)){
24747             if(typeof config.checked == "boolean"){                 config = new Ext.menu.CheckItem(config);
24748             }else{
24749                 config = new Ext.menu.Item(config);
24750             }
24751         }
24752         return this.addItem(config);
24753     },
24754
24755     
24756     addText : function(text){
24757         return this.addItem(new Ext.menu.TextItem(text));
24758     },
24759
24760     
24761     insert : function(index, item){
24762         this.items.insert(index, item);
24763         if(this.ul){
24764             var li = document.createElement("li");
24765             li.className = "x-menu-list-item";
24766             this.ul.dom.insertBefore(li, this.ul.dom.childNodes[index]);
24767             item.render(li, this);
24768             this.delayAutoWidth();
24769         }
24770         return item;
24771     },
24772
24773     
24774     remove : function(item){
24775         this.items.removeKey(item.id);
24776         item.destroy();
24777     },
24778
24779     
24780     removeAll : function(){
24781         var f;
24782         while(f = this.items.first()){
24783             this.remove(f);
24784         }
24785     },
24786
24787     
24788     destroy : function(){
24789         this.beforeDestroy();
24790         Ext.menu.MenuMgr.unregister(this);
24791         if (this.keyNav) {
24792                 this.keyNav.disable();  
24793         }
24794         this.removeAll();
24795         if (this.ul) {
24796                 this.ul.removeAllListeners();   
24797         }
24798         if (this.el) {
24799                 this.el.destroy();      
24800         }
24801     },
24802
24803             beforeDestroy : Ext.emptyFn
24804
24805 });
24806
24807 Ext.menu.MenuNav = function(menu){
24808     Ext.menu.MenuNav.superclass.constructor.call(this, menu.el);
24809     this.scope = this.menu = menu;
24810 };
24811
24812 Ext.extend(Ext.menu.MenuNav, Ext.KeyNav, {
24813     doRelay : function(e, h){
24814         var k = e.getKey();
24815         if(!this.menu.activeItem && e.isNavKeyPress() && k != e.SPACE && k != e.RETURN){
24816             this.menu.tryActivate(0, 1);
24817             return false;
24818         }
24819         return h.call(this.scope || this, e, this.menu);
24820     },
24821
24822     up : function(e, m){
24823         if(!m.tryActivate(m.items.indexOf(m.activeItem)-1, -1)){
24824             m.tryActivate(m.items.length-1, -1);
24825         }
24826     },
24827
24828     down : function(e, m){
24829         if(!m.tryActivate(m.items.indexOf(m.activeItem)+1, 1)){
24830             m.tryActivate(0, 1);
24831         }
24832     },
24833
24834     right : function(e, m){
24835         if(m.activeItem){
24836             m.activeItem.expandMenu(true);
24837         }
24838     },
24839
24840     left : function(e, m){
24841         m.hide();
24842         if(m.parentMenu && m.parentMenu.activeItem){
24843             m.parentMenu.activeItem.activate();
24844         }
24845     },
24846
24847     enter : function(e, m){
24848         if(m.activeItem){
24849             e.stopPropagation();
24850             m.activeItem.onClick(e);
24851             m.fireEvent("click", this, m.activeItem);
24852             return true;
24853         }
24854     }
24855 });
24856
24857 Ext.menu.MenuMgr = function(){
24858    var menus, active, groups = {}, attached = false, lastShow = new Date();
24859
24860       function init(){
24861        menus = {};
24862        active = new Ext.util.MixedCollection();
24863        Ext.getDoc().addKeyListener(27, function(){
24864            if(active.length > 0){
24865                hideAll();
24866            }
24867        });
24868    }
24869
24870       function hideAll(){
24871        if(active && active.length > 0){
24872            var c = active.clone();
24873            c.each(function(m){
24874                m.hide();
24875            });
24876        }
24877    }
24878
24879       function onHide(m){
24880        active.remove(m);
24881        if(active.length < 1){
24882            Ext.getDoc().un("mousedown", onMouseDown);
24883            attached = false;
24884        }
24885    }
24886
24887       function onShow(m){
24888        var last = active.last();
24889        lastShow = new Date();
24890        active.add(m);
24891        if(!attached){
24892            Ext.getDoc().on("mousedown", onMouseDown);
24893            attached = true;
24894        }
24895        if(m.parentMenu){
24896           m.getEl().setZIndex(parseInt(m.parentMenu.getEl().getStyle("z-index"), 10) + 3);
24897           m.parentMenu.activeChild = m;
24898        }else if(last && last.isVisible()){
24899           m.getEl().setZIndex(parseInt(last.getEl().getStyle("z-index"), 10) + 3);
24900        }
24901    }
24902
24903       function onBeforeHide(m){
24904        if(m.activeChild){
24905            m.activeChild.hide();
24906        }
24907        if(m.autoHideTimer){
24908            clearTimeout(m.autoHideTimer);
24909            delete m.autoHideTimer;
24910        }
24911    }
24912
24913       function onBeforeShow(m){
24914        var pm = m.parentMenu;
24915        if(!pm && !m.allowOtherMenus){
24916            hideAll();
24917        }else if(pm && pm.activeChild){
24918            pm.activeChild.hide();
24919        }
24920    }
24921
24922       function onMouseDown(e){
24923        if(lastShow.getElapsed() > 50 && active.length > 0 && !e.getTarget(".x-menu")){
24924            hideAll();
24925        }
24926    }
24927
24928       function onBeforeCheck(mi, state){
24929        if(state){
24930            var g = groups[mi.group];
24931            for(var i = 0, l = g.length; i < l; i++){
24932                if(g[i] != mi){
24933                    g[i].setChecked(false);
24934                }
24935            }
24936        }
24937    }
24938
24939    return {
24940
24941        
24942        hideAll : function(){
24943             hideAll();  
24944        },
24945
24946               register : function(menu){
24947            if(!menus){
24948                init();
24949            }
24950            menus[menu.id] = menu;
24951            menu.on("beforehide", onBeforeHide);
24952            menu.on("hide", onHide);
24953            menu.on("beforeshow", onBeforeShow);
24954            menu.on("show", onShow);
24955            var g = menu.group;
24956            if(g && menu.events["checkchange"]){
24957                if(!groups[g]){
24958                    groups[g] = [];
24959                }
24960                groups[g].push(menu);
24961                menu.on("checkchange", onCheck);
24962            }
24963        },
24964
24965         
24966        get : function(menu){
24967            if(typeof menu == "string"){                if(!menus){                     return null;
24968                }
24969                return menus[menu];
24970            }else if(menu.events){                 return menu;
24971            }else if(typeof menu.length == 'number'){                return new Ext.menu.Menu({items:menu});
24972            }else{                return new Ext.menu.Menu(menu);
24973            }
24974        },
24975
24976               unregister : function(menu){
24977            delete menus[menu.id];
24978            menu.un("beforehide", onBeforeHide);
24979            menu.un("hide", onHide);
24980            menu.un("beforeshow", onBeforeShow);
24981            menu.un("show", onShow);
24982            var g = menu.group;
24983            if(g && menu.events["checkchange"]){
24984                groups[g].remove(menu);
24985                menu.un("checkchange", onCheck);
24986            }
24987        },
24988
24989               registerCheckable : function(menuItem){
24990            var g = menuItem.group;
24991            if(g){
24992                if(!groups[g]){
24993                    groups[g] = [];
24994                }
24995                groups[g].push(menuItem);
24996                menuItem.on("beforecheckchange", onBeforeCheck);
24997            }
24998        },
24999
25000               unregisterCheckable : function(menuItem){
25001            var g = menuItem.group;
25002            if(g){
25003                groups[g].remove(menuItem);
25004                menuItem.un("beforecheckchange", onBeforeCheck);
25005            }
25006        },
25007
25008        getCheckedItem : function(groupId){
25009            var g = groups[groupId];
25010            if(g){
25011                for(var i = 0, l = g.length; i < l; i++){
25012                    if(g[i].checked){
25013                        return g[i];
25014                    }
25015                }
25016            }
25017            return null;
25018        },
25019
25020        setCheckedItem : function(groupId, itemId){
25021            var g = groups[groupId];
25022            if(g){
25023                for(var i = 0, l = g.length; i < l; i++){
25024                    if(g[i].id == itemId){
25025                        g[i].setChecked(true);
25026                    }
25027                }
25028            }
25029            return null;
25030        }
25031    };
25032 }();
25033
25034
25035 Ext.menu.BaseItem = function(config){
25036     Ext.menu.BaseItem.superclass.constructor.call(this, config);
25037
25038     this.addEvents(
25039         
25040         'click',
25041         
25042         'activate',
25043         
25044         'deactivate'
25045     );
25046
25047     if(this.handler){
25048         this.on("click", this.handler, this.scope);
25049     }
25050 };
25051
25052 Ext.extend(Ext.menu.BaseItem, Ext.Component, {
25053     
25054     
25055     
25056     canActivate : false,
25057     
25058     activeClass : "x-menu-item-active",
25059     
25060     hideOnClick : true,
25061     
25062     hideDelay : 100,
25063
25064         ctype: "Ext.menu.BaseItem",
25065
25066         actionMode : "container",
25067
25068         render : function(container, parentMenu){
25069         this.parentMenu = parentMenu;
25070         Ext.menu.BaseItem.superclass.render.call(this, container);
25071         this.container.menuItemId = this.id;
25072     },
25073
25074         onRender : function(container, position){
25075         this.el = Ext.get(this.el);
25076         container.dom.appendChild(this.el.dom);
25077     },
25078
25079     
25080     setHandler : function(handler, scope){
25081         if(this.handler){
25082             this.un("click", this.handler, this.scope);
25083         }
25084         this.on("click", this.handler = handler, this.scope = scope);
25085     },
25086
25087         onClick : function(e){
25088         if(!this.disabled && this.fireEvent("click", this, e) !== false
25089                 && this.parentMenu.fireEvent("itemclick", this, e) !== false){
25090             this.handleClick(e);
25091         }else{
25092             e.stopEvent();
25093         }
25094     },
25095
25096         activate : function(){
25097         if(this.disabled){
25098             return false;
25099         }
25100         var li = this.container;
25101         li.addClass(this.activeClass);
25102         this.region = li.getRegion().adjust(2, 2, -2, -2);
25103         this.fireEvent("activate", this);
25104         return true;
25105     },
25106
25107         deactivate : function(){
25108         this.container.removeClass(this.activeClass);
25109         this.fireEvent("deactivate", this);
25110     },
25111
25112         shouldDeactivate : function(e){
25113         return !this.region || !this.region.contains(e.getPoint());
25114     },
25115
25116         handleClick : function(e){
25117         if(this.hideOnClick){
25118             this.parentMenu.hide.defer(this.hideDelay, this.parentMenu, [true]);
25119         }
25120     },
25121
25122         expandMenu : function(autoActivate){
25123             },
25124
25125         hideMenu : function(){
25126             }
25127 });
25128
25129 Ext.menu.TextItem = function(text){
25130     this.text = text;
25131     Ext.menu.TextItem.superclass.constructor.call(this);
25132 };
25133
25134 Ext.extend(Ext.menu.TextItem, Ext.menu.BaseItem, {
25135     
25136     
25137     hideOnClick : false,
25138     
25139     itemCls : "x-menu-text",
25140
25141         onRender : function(){
25142         var s = document.createElement("span");
25143         s.className = this.itemCls;
25144         s.innerHTML = this.text;
25145         this.el = s;
25146         Ext.menu.TextItem.superclass.onRender.apply(this, arguments);
25147     }
25148 });
25149
25150 Ext.menu.Separator = function(config){
25151     Ext.menu.Separator.superclass.constructor.call(this, config);
25152 };
25153
25154 Ext.extend(Ext.menu.Separator, Ext.menu.BaseItem, {
25155     
25156     itemCls : "x-menu-sep",
25157     
25158     hideOnClick : false,
25159
25160         onRender : function(li){
25161         var s = document.createElement("span");
25162         s.className = this.itemCls;
25163         s.innerHTML = "&#160;";
25164         this.el = s;
25165         li.addClass("x-menu-sep-li");
25166         Ext.menu.Separator.superclass.onRender.apply(this, arguments);
25167     }
25168 });
25169
25170 Ext.menu.Item = function(config){
25171     Ext.menu.Item.superclass.constructor.call(this, config);
25172     if(this.menu){
25173         this.menu = Ext.menu.MenuMgr.get(this.menu);
25174     }
25175 };
25176 Ext.extend(Ext.menu.Item, Ext.menu.BaseItem, {
25177     
25178     
25179     
25180     
25181     
25182     
25183     itemCls : "x-menu-item",
25184     
25185     canActivate : true,
25186     
25187     showDelay: 200,
25188         hideDelay: 200,
25189
25190         ctype: "Ext.menu.Item",
25191
25192         onRender : function(container, position){
25193         var el = document.createElement("a");
25194         el.hideFocus = true;
25195         el.unselectable = "on";
25196         el.href = this.href || "#";
25197         if(this.hrefTarget){
25198             el.target = this.hrefTarget;
25199         }
25200         el.className = this.itemCls + (this.menu ?  " x-menu-item-arrow" : "") + (this.cls ?  " " + this.cls : "");
25201         el.innerHTML = String.format(
25202                 '<img src="{0}" class="x-menu-item-icon {2}" />{1}',
25203                 this.icon || Ext.BLANK_IMAGE_URL, this.itemText||this.text, this.iconCls || '');
25204         this.el = el;
25205         Ext.menu.Item.superclass.onRender.call(this, container, position);
25206     },
25207
25208     
25209     setText : function(text){
25210         this.text = text;
25211         if(this.rendered){
25212             this.el.update(String.format(
25213                 '<img src="{0}" class="x-menu-item-icon {2}">{1}',
25214                 this.icon || Ext.BLANK_IMAGE_URL, this.text, this.iconCls || ''));
25215             this.parentMenu.autoWidth();
25216         }
25217     },
25218
25219     
25220     setIconClass : function(cls){
25221         var oldCls = this.iconCls;
25222         this.iconCls = cls;
25223         if(this.rendered){
25224             this.el.child('img.x-menu-item-icon').replaceClass(oldCls, this.iconCls);
25225         }
25226     },
25227
25228         handleClick : function(e){
25229         if(!this.href){             e.stopEvent();
25230         }
25231         Ext.menu.Item.superclass.handleClick.apply(this, arguments);
25232     },
25233
25234         activate : function(autoExpand){
25235         if(Ext.menu.Item.superclass.activate.apply(this, arguments)){
25236             this.focus();
25237             if(autoExpand){
25238                 this.expandMenu();
25239             }
25240         }
25241         return true;
25242     },
25243
25244         shouldDeactivate : function(e){
25245         if(Ext.menu.Item.superclass.shouldDeactivate.call(this, e)){
25246             if(this.menu && this.menu.isVisible()){
25247                 return !this.menu.getEl().getRegion().contains(e.getPoint());
25248             }
25249             return true;
25250         }
25251         return false;
25252     },
25253
25254         deactivate : function(){
25255         Ext.menu.Item.superclass.deactivate.apply(this, arguments);
25256         this.hideMenu();
25257     },
25258
25259         expandMenu : function(autoActivate){
25260         if(!this.disabled && this.menu){
25261             clearTimeout(this.hideTimer);
25262             delete this.hideTimer;
25263             if(!this.menu.isVisible() && !this.showTimer){
25264                 this.showTimer = this.deferExpand.defer(this.showDelay, this, [autoActivate]);
25265             }else if (this.menu.isVisible() && autoActivate){
25266                 this.menu.tryActivate(0, 1);
25267             }
25268         }
25269     },
25270
25271         deferExpand : function(autoActivate){
25272         delete this.showTimer;
25273         this.menu.show(this.container, this.parentMenu.subMenuAlign || "tl-tr?", this.parentMenu);
25274         if(autoActivate){
25275             this.menu.tryActivate(0, 1);
25276         }
25277     },
25278
25279         hideMenu : function(){
25280         clearTimeout(this.showTimer);
25281         delete this.showTimer;
25282         if(!this.hideTimer && this.menu && this.menu.isVisible()){
25283             this.hideTimer = this.deferHide.defer(this.hideDelay, this);
25284         }
25285     },
25286
25287         deferHide : function(){
25288         delete this.hideTimer;
25289         this.menu.hide();
25290     }
25291 });
25292
25293 Ext.menu.CheckItem = function(config){
25294     Ext.menu.CheckItem.superclass.constructor.call(this, config);
25295     this.addEvents(
25296         
25297         "beforecheckchange" ,
25298         
25299         "checkchange"
25300     );
25301     
25302     if(this.checkHandler){
25303         this.on('checkchange', this.checkHandler, this.scope);
25304     }
25305     Ext.menu.MenuMgr.registerCheckable(this);
25306 };
25307 Ext.extend(Ext.menu.CheckItem, Ext.menu.Item, {
25308     
25309     
25310     itemCls : "x-menu-item x-menu-check-item",
25311     
25312     groupClass : "x-menu-group-item",
25313
25314     
25315     checked: false,
25316
25317         ctype: "Ext.menu.CheckItem",
25318
25319         onRender : function(c){
25320         Ext.menu.CheckItem.superclass.onRender.apply(this, arguments);
25321         if(this.group){
25322             this.el.addClass(this.groupClass);
25323         }
25324         if(this.checked){
25325             this.checked = false;
25326             this.setChecked(true, true);
25327         }
25328     },
25329
25330         destroy : function(){
25331         Ext.menu.MenuMgr.unregisterCheckable(this);
25332         Ext.menu.CheckItem.superclass.destroy.apply(this, arguments);
25333     },
25334
25335     
25336     setChecked : function(state, suppressEvent){
25337         if(this.checked != state && this.fireEvent("beforecheckchange", this, state) !== false){
25338             if(this.container){
25339                 this.container[state ? "addClass" : "removeClass"]("x-menu-item-checked");
25340             }
25341             this.checked = state;
25342             if(suppressEvent !== true){
25343                 this.fireEvent("checkchange", this, state);
25344             }
25345         }
25346     },
25347
25348         handleClick : function(e){
25349        if(!this.disabled && !(this.checked && this.group)){           this.setChecked(!this.checked);
25350        }
25351        Ext.menu.CheckItem.superclass.handleClick.apply(this, arguments);
25352     }
25353 });
25354
25355 Ext.menu.Adapter = function(component, config){
25356     Ext.menu.Adapter.superclass.constructor.call(this, config);
25357     this.component = component;
25358 };
25359 Ext.extend(Ext.menu.Adapter, Ext.menu.BaseItem, {
25360         canActivate : true,
25361
25362         onRender : function(container, position){
25363         this.component.render(container);
25364         this.el = this.component.getEl();
25365     },
25366
25367         activate : function(){
25368         if(this.disabled){
25369             return false;
25370         }
25371         this.component.focus();
25372         this.fireEvent("activate", this);
25373         return true;
25374     },
25375
25376         deactivate : function(){
25377         this.fireEvent("deactivate", this);
25378     },
25379
25380         disable : function(){
25381         this.component.disable();
25382         Ext.menu.Adapter.superclass.disable.call(this);
25383     },
25384
25385         enable : function(){
25386         this.component.enable();
25387         Ext.menu.Adapter.superclass.enable.call(this);
25388     }
25389 });
25390
25391 Ext.menu.DateItem = function(config){
25392     Ext.menu.DateItem.superclass.constructor.call(this, new Ext.DatePicker(config), config);
25393     
25394     this.picker = this.component;
25395     this.addEvents('select');
25396     
25397     this.picker.on("render", function(picker){
25398         picker.getEl().swallowEvent("click");
25399         picker.container.addClass("x-menu-date-item");
25400     });
25401
25402     this.picker.on("select", this.onSelect, this);
25403 };
25404
25405 Ext.extend(Ext.menu.DateItem, Ext.menu.Adapter, {
25406         onSelect : function(picker, date){
25407         this.fireEvent("select", this, date, picker);
25408         Ext.menu.DateItem.superclass.handleClick.call(this);
25409     }
25410 });
25411
25412 Ext.menu.ColorItem = function(config){
25413     Ext.menu.ColorItem.superclass.constructor.call(this, new Ext.ColorPalette(config), config);
25414     
25415     this.palette = this.component;
25416     this.relayEvents(this.palette, ["select"]);
25417     if(this.selectHandler){
25418         this.on('select', this.selectHandler, this.scope);
25419     }
25420 };
25421 Ext.extend(Ext.menu.ColorItem, Ext.menu.Adapter);
25422
25423 Ext.menu.DateMenu = function(config){
25424     Ext.menu.DateMenu.superclass.constructor.call(this, config);
25425     this.plain = true;
25426     var di = new Ext.menu.DateItem(config);
25427     this.add(di);
25428     
25429     this.picker = di.picker;
25430     
25431     this.relayEvents(di, ["select"]);
25432
25433     this.on('beforeshow', function(){
25434         if(this.picker){
25435             this.picker.hideMonthPicker(true);
25436         }
25437     }, this);
25438 };
25439 Ext.extend(Ext.menu.DateMenu, Ext.menu.Menu, {
25440     cls:'x-date-menu',
25441
25442         beforeDestroy : function() {
25443         this.picker.destroy();
25444     }
25445 });
25446
25447 Ext.menu.ColorMenu = function(config){
25448     Ext.menu.ColorMenu.superclass.constructor.call(this, config);
25449     this.plain = true;
25450     var ci = new Ext.menu.ColorItem(config);
25451     this.add(ci);
25452     
25453     this.palette = ci.palette;
25454     
25455     this.relayEvents(ci, ["select"]);
25456 };
25457 Ext.extend(Ext.menu.ColorMenu, Ext.menu.Menu);
25458
25459 Ext.form.Field = Ext.extend(Ext.BoxComponent,  {
25460     
25461     
25462     
25463     
25464     
25465     
25466
25467     
25468     invalidClass : "x-form-invalid",
25469     
25470     invalidText : "The value in this field is invalid",
25471     
25472     focusClass : "x-form-focus",
25473     
25474     validationEvent : "keyup",
25475     
25476     validateOnBlur : true,
25477     
25478     validationDelay : 250,
25479     
25480     defaultAutoCreate : {tag: "input", type: "text", size: "20", autocomplete: "off"},
25481     
25482     fieldClass : "x-form-field",
25483     
25484     msgTarget : 'qtip',
25485     
25486     msgFx : 'normal',
25487     
25488     
25489     readOnly : false,
25490
25491     
25492     disabled : false,
25493
25494     
25495
25496     
25497
25498         isFormField : true,
25499
25500         hasFocus : false,
25501
25502     
25503     
25504     
25505     
25506
25507                 initComponent : function(){
25508         Ext.form.Field.superclass.initComponent.call(this);
25509         this.addEvents(
25510             
25511             'focus',
25512             
25513             'blur',
25514             
25515             'specialkey',
25516             
25517             'change',
25518             
25519             'invalid',
25520             
25521             'valid'
25522         );
25523     },
25524
25525     
25526     getName: function(){
25527          return this.rendered && this.el.dom.name ? this.el.dom.name : (this.hiddenName || '');
25528     },
25529
25530         onRender : function(ct, position){
25531         Ext.form.Field.superclass.onRender.call(this, ct, position);
25532         if(!this.el){
25533             var cfg = this.getAutoCreate();
25534             if(!cfg.name){
25535                 cfg.name = this.name || this.id;
25536             }
25537             if(this.inputType){
25538                 cfg.type = this.inputType;
25539             }
25540             this.el = ct.createChild(cfg, position);
25541         }
25542         var type = this.el.dom.type;
25543         if(type){
25544             if(type == 'password'){
25545                 type = 'text';
25546             }
25547             this.el.addClass('x-form-'+type);
25548         }
25549         if(this.readOnly){
25550             this.el.dom.readOnly = true;
25551         }
25552         if(this.tabIndex !== undefined){
25553             this.el.dom.setAttribute('tabIndex', this.tabIndex);
25554         }
25555
25556         this.el.addClass([this.fieldClass, this.cls]);
25557         this.initValue();
25558     },
25559
25560         initValue : function(){
25561         if(this.value !== undefined){
25562             this.setValue(this.value);
25563         }else if(this.el.dom.value.length > 0){
25564             this.setValue(this.el.dom.value);
25565         }
25566     },
25567
25568     
25569     isDirty : function() {
25570         if(this.disabled) {
25571             return false;
25572         }
25573         return String(this.getValue()) !== String(this.originalValue);
25574     },
25575
25576         afterRender : function(){
25577         Ext.form.Field.superclass.afterRender.call(this);
25578         this.initEvents();
25579     },
25580
25581         fireKey : function(e){
25582         if(e.isSpecialKey()){
25583             this.fireEvent("specialkey", this, e);
25584         }
25585     },
25586
25587     
25588     reset : function(){
25589         this.setValue(this.originalValue);
25590         this.clearInvalid();
25591     },
25592
25593         initEvents : function(){
25594         this.el.on(Ext.isIE ? "keydown" : "keypress", this.fireKey,  this);
25595         this.el.on("focus", this.onFocus,  this);
25596         this.el.on("blur", this.onBlur,  this);
25597
25598                 this.originalValue = this.getValue();
25599     },
25600
25601         onFocus : function(){
25602         if(!Ext.isOpera && this.focusClass){             this.el.addClass(this.focusClass);
25603         }
25604         if(!this.hasFocus){
25605             this.hasFocus = true;
25606             this.startValue = this.getValue();
25607             this.fireEvent("focus", this);
25608         }
25609     },
25610
25611     beforeBlur : Ext.emptyFn,
25612
25613         onBlur : function(){
25614         this.beforeBlur();
25615         if(!Ext.isOpera && this.focusClass){             this.el.removeClass(this.focusClass);
25616         }
25617         this.hasFocus = false;
25618         if(this.validationEvent !== false && this.validateOnBlur && this.validationEvent != "blur"){
25619             this.validate();
25620         }
25621         var v = this.getValue();
25622         if(String(v) !== String(this.startValue)){
25623             this.fireEvent('change', this, v, this.startValue);
25624         }
25625         this.fireEvent("blur", this);
25626     },
25627
25628     
25629     isValid : function(preventMark){
25630         if(this.disabled){
25631             return true;
25632         }
25633         var restore = this.preventMark;
25634         this.preventMark = preventMark === true;
25635         var v = this.validateValue(this.processValue(this.getRawValue()));
25636         this.preventMark = restore;
25637         return v;
25638     },
25639
25640     
25641     validate : function(){
25642         if(this.disabled || this.validateValue(this.processValue(this.getRawValue()))){
25643             this.clearInvalid();
25644             return true;
25645         }
25646         return false;
25647     },
25648
25649     processValue : function(value){
25650         return value;
25651     },
25652
25653             validateValue : function(value){
25654         return true;
25655     },
25656
25657     
25658     markInvalid : function(msg){
25659         if(!this.rendered || this.preventMark){             return;
25660         }
25661         this.el.addClass(this.invalidClass);
25662         msg = msg || this.invalidText;
25663         switch(this.msgTarget){
25664             case 'qtip':
25665                 this.el.dom.qtip = msg;
25666                 this.el.dom.qclass = 'x-form-invalid-tip';
25667                 if(Ext.QuickTips){                     Ext.QuickTips.enable();
25668                 }
25669                 break;
25670             case 'title':
25671                 this.el.dom.title = msg;
25672                 break;
25673             case 'under':
25674                 if(!this.errorEl){
25675                     var elp = this.el.findParent('.x-form-element', 5, true);
25676                     this.errorEl = elp.createChild({cls:'x-form-invalid-msg'});
25677                     this.errorEl.setWidth(elp.getWidth(true)-20);
25678                 }
25679                 this.errorEl.update(msg);
25680                 Ext.form.Field.msgFx[this.msgFx].show(this.errorEl, this);
25681                 break;
25682             case 'side':
25683                 if(!this.errorIcon){
25684                     var elp = this.el.findParent('.x-form-element', 5, true);
25685                     this.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});
25686                 }
25687                 this.alignErrorIcon();
25688                 this.errorIcon.dom.qtip = msg;
25689                 this.errorIcon.dom.qclass = 'x-form-invalid-tip';
25690                 this.errorIcon.show();
25691                 this.on('resize', this.alignErrorIcon, this);
25692                 break;
25693             default:
25694                 var t = Ext.getDom(this.msgTarget);
25695                 t.innerHTML = msg;
25696                 t.style.display = this.msgDisplay;
25697                 break;
25698         }
25699         this.fireEvent('invalid', this, msg);
25700     },
25701
25702         alignErrorIcon : function(){
25703         this.errorIcon.alignTo(this.el, 'tl-tr', [2, 0]);
25704     },
25705
25706     
25707     clearInvalid : function(){
25708         if(!this.rendered || this.preventMark){             return;
25709         }
25710         this.el.removeClass(this.invalidClass);
25711         switch(this.msgTarget){
25712             case 'qtip':
25713                 this.el.dom.qtip = '';
25714                 break;
25715             case 'title':
25716                 this.el.dom.title = '';
25717                 break;
25718             case 'under':
25719                 if(this.errorEl){
25720                     Ext.form.Field.msgFx[this.msgFx].hide(this.errorEl, this);
25721                 }
25722                 break;
25723             case 'side':
25724                 if(this.errorIcon){
25725                     this.errorIcon.dom.qtip = '';
25726                     this.errorIcon.hide();
25727                     this.un('resize', this.alignErrorIcon, this);
25728                 }
25729                 break;
25730             default:
25731                 var t = Ext.getDom(this.msgTarget);
25732                 t.innerHTML = '';
25733                 t.style.display = 'none';
25734                 break;
25735         }
25736         this.fireEvent('valid', this);
25737     },
25738
25739     
25740     getRawValue : function(){
25741         var v = this.rendered ? this.el.getValue() : Ext.value(this.value, '');
25742         if(v === this.emptyText){
25743             v = '';
25744         }
25745         return v;
25746     },
25747
25748     
25749     getValue : function(){
25750         if(!this.rendered) {
25751             return this.value;
25752         }
25753         var v = this.el.getValue();
25754         if(v === this.emptyText || v === undefined){
25755             v = '';
25756         }
25757         return v;
25758     },
25759
25760     
25761     setRawValue : function(v){
25762         return this.el.dom.value = (v === null || v === undefined ? '' : v);
25763     },
25764
25765     
25766     setValue : function(v){
25767         this.value = v;
25768         if(this.rendered){
25769             this.el.dom.value = (v === null || v === undefined ? '' : v);
25770             this.validate();
25771         }
25772     },
25773
25774     adjustSize : function(w, h){
25775         var s = Ext.form.Field.superclass.adjustSize.call(this, w, h);
25776         s.width = this.adjustWidth(this.el.dom.tagName, s.width);
25777         return s;
25778     },
25779
25780     adjustWidth : function(tag, w){
25781         tag = tag.toLowerCase();
25782         if(typeof w == 'number' && !Ext.isSafari){
25783             if(Ext.isIE && (tag == 'input' || tag == 'textarea')){
25784                 if(tag == 'input' && !Ext.isStrict){
25785                     return this.inEditor ? w : w - 3;
25786                 }
25787                 if(tag == 'input' && Ext.isStrict){
25788                     return w - (Ext.isIE6 ? 4 : 1);
25789                 }
25790                 if(tag = 'textarea' && Ext.isStrict){
25791                     return w-2;
25792                 }
25793             }else if(Ext.isOpera && Ext.isStrict){
25794                 if(tag == 'input'){
25795                     return w + 2;
25796                 }
25797                 if(tag = 'textarea'){
25798                     return w-2;
25799                 }
25800             }
25801         }
25802         return w;
25803     }
25804
25805     
25806     
25807
25808     
25809 });
25810
25811
25812 Ext.form.Field.msgFx = {
25813     normal : {
25814         show: function(msgEl, f){
25815             msgEl.setDisplayed('block');
25816         },
25817
25818         hide : function(msgEl, f){
25819             msgEl.setDisplayed(false).update('');
25820         }
25821     },
25822
25823     slide : {
25824         show: function(msgEl, f){
25825             msgEl.slideIn('t', {stopFx:true});
25826         },
25827
25828         hide : function(msgEl, f){
25829             msgEl.slideOut('t', {stopFx:true,useDisplay:true});
25830         }
25831     },
25832
25833     slideRight : {
25834         show: function(msgEl, f){
25835             msgEl.fixDisplay();
25836             msgEl.alignTo(f.el, 'tl-tr');
25837             msgEl.slideIn('l', {stopFx:true});
25838         },
25839
25840         hide : function(msgEl, f){
25841             msgEl.slideOut('l', {stopFx:true,useDisplay:true});
25842         }
25843     }
25844 };
25845 Ext.reg('field', Ext.form.Field);
25846
25847
25848 Ext.form.TextField = Ext.extend(Ext.form.Field,  {
25849     
25850     
25851     grow : false,
25852     
25853     growMin : 30,
25854     
25855     growMax : 800,
25856     
25857     vtype : null,
25858     
25859     maskRe : null,
25860     
25861     disableKeyFilter : false,
25862     
25863     allowBlank : true,
25864     
25865     minLength : 0,
25866     
25867     maxLength : Number.MAX_VALUE,
25868     
25869     minLengthText : "The minimum length for this field is {0}",
25870     
25871     maxLengthText : "The maximum length for this field is {0}",
25872     
25873     selectOnFocus : false,
25874     
25875     blankText : "This field is required",
25876     
25877     validator : null,
25878     
25879     regex : null,
25880     
25881     regexText : "",
25882     
25883     emptyText : null,
25884     
25885     emptyClass : 'x-form-empty-field',
25886
25887     initComponent : function(){
25888         Ext.form.TextField.superclass.initComponent.call(this);
25889         this.addEvents(
25890             
25891             'autosize'
25892         );
25893     },
25894
25895         initEvents : function(){
25896         Ext.form.TextField.superclass.initEvents.call(this);
25897         if(this.validationEvent == 'keyup'){
25898             this.validationTask = new Ext.util.DelayedTask(this.validate, this);
25899             this.el.on('keyup', this.filterValidation, this);
25900         }
25901         else if(this.validationEvent !== false){
25902             this.el.on(this.validationEvent, this.validate, this, {buffer: this.validationDelay});
25903         }
25904         if(this.selectOnFocus || this.emptyText){
25905             this.on("focus", this.preFocus, this);
25906             if(this.emptyText){
25907                 this.on('blur', this.postBlur, this);
25908                 this.applyEmptyText();
25909             }
25910         }
25911         if(this.maskRe || (this.vtype && this.disableKeyFilter !== true && (this.maskRe = Ext.form.VTypes[this.vtype+'Mask']))){
25912             this.el.on("keypress", this.filterKeys, this);
25913         }
25914         if(this.grow){
25915             this.el.on("keyup", this.onKeyUp,  this, {buffer:50});
25916             this.el.on("click", this.autoSize,  this);
25917         }
25918     },
25919
25920     processValue : function(value){
25921         if(this.stripCharsRe){
25922             var newValue = value.replace(this.stripCharsRe, '');
25923             if(newValue !== value){
25924                 this.setRawValue(newValue);
25925                 return newValue;
25926             }
25927         }
25928         return value;
25929     },
25930
25931     filterValidation : function(e){
25932         if(!e.isNavKeyPress()){
25933             this.validationTask.delay(this.validationDelay);
25934         }
25935     },
25936
25937         onKeyUp : function(e){
25938         if(!e.isNavKeyPress()){
25939             this.autoSize();
25940         }
25941     },
25942
25943     
25944     reset : function(){
25945         Ext.form.TextField.superclass.reset.call(this);
25946         this.applyEmptyText();
25947     },
25948
25949     applyEmptyText : function(){
25950         if(this.rendered && this.emptyText && this.getRawValue().length < 1){
25951             this.setRawValue(this.emptyText);
25952             this.el.addClass(this.emptyClass);
25953         }
25954     },
25955
25956         preFocus : function(){
25957         if(this.emptyText){
25958             if(this.el.dom.value == this.emptyText){
25959                 this.setRawValue('');
25960             }
25961             this.el.removeClass(this.emptyClass);
25962         }
25963         if(this.selectOnFocus){
25964             this.el.dom.select();
25965         }
25966     },
25967
25968         postBlur : function(){
25969         this.applyEmptyText();
25970     },
25971
25972         filterKeys : function(e){
25973         var k = e.getKey();
25974         if(!Ext.isIE && (e.isNavKeyPress() || k == e.BACKSPACE || (k == e.DELETE && e.button == -1))){
25975             return;
25976         }
25977         var c = e.getCharCode(), cc = String.fromCharCode(c);
25978         if(Ext.isIE && (e.isSpecialKey() || !cc)){
25979             return;
25980         }
25981         if(!this.maskRe.test(cc)){
25982             e.stopEvent();
25983         }
25984     },
25985
25986     setValue : function(v){
25987         if(this.emptyText && this.el && v !== undefined && v !== null && v !== ''){
25988             this.el.removeClass(this.emptyClass);
25989         }
25990         Ext.form.TextField.superclass.setValue.apply(this, arguments);
25991         this.applyEmptyText();
25992         this.autoSize();
25993     },
25994
25995     
25996     validateValue : function(value){
25997         if(value.length < 1 || value === this.emptyText){              if(this.allowBlank){
25998                  this.clearInvalid();
25999                  return true;
26000              }else{
26001                  this.markInvalid(this.blankText);
26002                  return false;
26003              }
26004         }
26005         if(value.length < this.minLength){
26006             this.markInvalid(String.format(this.minLengthText, this.minLength));
26007             return false;
26008         }
26009         if(value.length > this.maxLength){
26010             this.markInvalid(String.format(this.maxLengthText, this.maxLength));
26011             return false;
26012         }
26013         if(this.vtype){
26014             var vt = Ext.form.VTypes;
26015             if(!vt[this.vtype](value, this)){
26016                 this.markInvalid(this.vtypeText || vt[this.vtype +'Text']);
26017                 return false;
26018             }
26019         }
26020         if(typeof this.validator == "function"){
26021             var msg = this.validator(value);
26022             if(msg !== true){
26023                 this.markInvalid(msg);
26024                 return false;
26025             }
26026         }
26027         if(this.regex && !this.regex.test(value)){
26028             this.markInvalid(this.regexText);
26029             return false;
26030         }
26031         return true;
26032     },
26033
26034     
26035     selectText : function(start, end){
26036         var v = this.getRawValue();
26037         if(v.length > 0){
26038             start = start === undefined ? 0 : start;
26039             end = end === undefined ? v.length : end;
26040             var d = this.el.dom;
26041             if(d.setSelectionRange){
26042                 d.setSelectionRange(start, end);
26043             }else if(d.createTextRange){
26044                 var range = d.createTextRange();
26045                 range.moveStart("character", start);
26046                 range.moveEnd("character", end-v.length);
26047                 range.select();
26048             }
26049         }
26050     },
26051
26052     
26053     autoSize : function(){
26054         if(!this.grow || !this.rendered){
26055             return;
26056         }
26057         if(!this.metrics){
26058             this.metrics = Ext.util.TextMetrics.createInstance(this.el);
26059         }
26060         var el = this.el;
26061         var v = el.dom.value;
26062         var d = document.createElement('div');
26063         d.appendChild(document.createTextNode(v));
26064         v = d.innerHTML;
26065         d = null;
26066         v += "&#160;";
26067         var w = Math.min(this.growMax, Math.max(this.metrics.getWidth(v) +  10, this.growMin));
26068         this.el.setWidth(w);
26069         this.fireEvent("autosize", this, w);
26070     }
26071 });
26072 Ext.reg('textfield', Ext.form.TextField);
26073
26074
26075 Ext.form.TriggerField = Ext.extend(Ext.form.TextField,  {
26076     
26077     
26078     defaultAutoCreate : {tag: "input", type: "text", size: "16", autocomplete: "off"},
26079     
26080     hideTrigger:false,
26081
26082     
26083     autoSize: Ext.emptyFn,
26084         monitorTab : true,
26085         deferHeight : true,
26086         mimicing : false,
26087
26088         onResize : function(w, h){
26089         Ext.form.TriggerField.superclass.onResize.call(this, w, h);
26090         if(typeof w == 'number'){
26091             this.el.setWidth(this.adjustWidth('input', w - this.trigger.getWidth()));
26092         }
26093         this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth());
26094     },
26095
26096         adjustSize : Ext.BoxComponent.prototype.adjustSize,
26097
26098         getResizeEl : function(){
26099         return this.wrap;
26100     },
26101
26102         getPositionEl : function(){
26103         return this.wrap;
26104     },
26105
26106         alignErrorIcon : function(){
26107         this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);
26108     },
26109
26110         onRender : function(ct, position){
26111         Ext.form.TriggerField.superclass.onRender.call(this, ct, position);
26112         this.wrap = this.el.wrap({cls: "x-form-field-wrap"});
26113         this.trigger = this.wrap.createChild(this.triggerConfig ||
26114                 {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.triggerClass});
26115         if(this.hideTrigger){
26116             this.trigger.setDisplayed(false);
26117         }
26118         this.initTrigger();
26119         if(!this.width){
26120             this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth());
26121         }
26122     },
26123
26124         initTrigger : function(){
26125         this.trigger.on("click", this.onTriggerClick, this, {preventDefault:true});
26126         this.trigger.addClassOnOver('x-form-trigger-over');
26127         this.trigger.addClassOnClick('x-form-trigger-click');
26128     },
26129
26130         onDestroy : function(){
26131         if(this.trigger){
26132             this.trigger.removeAllListeners();
26133             this.trigger.remove();
26134         }
26135         if(this.wrap){
26136             this.wrap.remove();
26137         }
26138         Ext.form.TriggerField.superclass.onDestroy.call(this);
26139     },
26140
26141         onFocus : function(){
26142         Ext.form.TriggerField.superclass.onFocus.call(this);
26143         if(!this.mimicing){
26144             this.wrap.addClass('x-trigger-wrap-focus');
26145             this.mimicing = true;
26146             Ext.get(Ext.isIE ? document.body : document).on("mousedown", this.mimicBlur, this, {delay: 10});
26147             if(this.monitorTab){
26148                 this.el.on("keydown", this.checkTab, this);
26149             }
26150         }
26151     },
26152
26153         checkTab : function(e){
26154         if(e.getKey() == e.TAB){
26155             this.triggerBlur();
26156         }
26157     },
26158
26159         onBlur : function(){
26160             },
26161
26162         mimicBlur : function(e){
26163         if(!this.wrap.contains(e.target) && this.validateBlur(e)){
26164             this.triggerBlur();
26165         }
26166     },
26167
26168         triggerBlur : function(){
26169         this.mimicing = false;
26170         Ext.get(Ext.isIE ? document.body : document).un("mousedown", this.mimicBlur);
26171         if(this.monitorTab){
26172             this.el.un("keydown", this.checkTab, this);
26173         }
26174         this.beforeBlur();
26175         this.wrap.removeClass('x-trigger-wrap-focus');
26176         Ext.form.TriggerField.superclass.onBlur.call(this);
26177     },
26178
26179     beforeBlur : Ext.emptyFn, 
26180
26181             validateBlur : function(e){
26182         return true;
26183     },
26184
26185         onDisable : function(){
26186         Ext.form.TriggerField.superclass.onDisable.call(this);
26187         if(this.wrap){
26188             this.wrap.addClass('x-item-disabled');
26189         }
26190     },
26191
26192         onEnable : function(){
26193         Ext.form.TriggerField.superclass.onEnable.call(this);
26194         if(this.wrap){
26195             this.wrap.removeClass('x-item-disabled');
26196         }
26197     },
26198
26199
26200         onShow : function(){
26201         if(this.wrap){
26202             this.wrap.dom.style.display = '';
26203             this.wrap.dom.style.visibility = 'visible';
26204         }
26205     },
26206
26207         onHide : function(){
26208         this.wrap.dom.style.display = 'none';
26209     },
26210
26211     
26212     onTriggerClick : Ext.emptyFn
26213
26214     
26215     
26216     
26217 });
26218
26219 Ext.form.TwinTriggerField = Ext.extend(Ext.form.TriggerField, {
26220     initComponent : function(){
26221         Ext.form.TwinTriggerField.superclass.initComponent.call(this);
26222
26223         this.triggerConfig = {
26224             tag:'span', cls:'x-form-twin-triggers', cn:[
26225             {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger1Class},
26226             {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger2Class}
26227         ]};
26228     },
26229
26230     getTrigger : function(index){
26231         return this.triggers[index];
26232     },
26233
26234     initTrigger : function(){
26235         var ts = this.trigger.select('.x-form-trigger', true);
26236         this.wrap.setStyle('overflow', 'hidden');
26237         var triggerField = this;
26238         ts.each(function(t, all, index){
26239             t.hide = function(){
26240                 var w = triggerField.wrap.getWidth();
26241                 this.dom.style.display = 'none';
26242                 triggerField.el.setWidth(w-triggerField.trigger.getWidth());
26243             };
26244             t.show = function(){
26245                 var w = triggerField.wrap.getWidth();
26246                 this.dom.style.display = '';
26247                 triggerField.el.setWidth(w-triggerField.trigger.getWidth());
26248             };
26249             var triggerIndex = 'Trigger'+(index+1);
26250
26251             if(this['hide'+triggerIndex]){
26252                 t.dom.style.display = 'none';
26253             }
26254             t.on("click", this['on'+triggerIndex+'Click'], this, {preventDefault:true});
26255             t.addClassOnOver('x-form-trigger-over');
26256             t.addClassOnClick('x-form-trigger-click');
26257         }, this);
26258         this.triggers = ts.elements;
26259     },
26260
26261     onTrigger1Click : Ext.emptyFn,
26262     onTrigger2Click : Ext.emptyFn
26263 });
26264 Ext.reg('trigger', Ext.form.TriggerField);
26265
26266 Ext.form.TextArea = Ext.extend(Ext.form.TextField,  {
26267     
26268     growMin : 60,
26269     
26270     growMax: 1000,
26271     growAppend : '&#160;\n&#160;',
26272     growPad : 0,
26273
26274     enterIsSpecial : false,
26275
26276     
26277     preventScrollbars: false,
26278     
26279
26280         onRender : function(ct, position){
26281         if(!this.el){
26282             this.defaultAutoCreate = {
26283                 tag: "textarea",
26284                 style:"width:100px;height:60px;",
26285                 autocomplete: "off"
26286             };
26287         }
26288         Ext.form.TextArea.superclass.onRender.call(this, ct, position);
26289         if(this.grow){
26290             this.textSizeEl = Ext.DomHelper.append(document.body, {
26291                 tag: "pre", cls: "x-form-grow-sizer"
26292             });
26293             if(this.preventScrollbars){
26294                 this.el.setStyle("overflow", "hidden");
26295             }
26296             this.el.setHeight(this.growMin);
26297         }
26298     },
26299
26300     onDestroy : function(){
26301         if(this.textSizeEl){
26302             Ext.removeNode(this.textSizeEl);
26303         }
26304         Ext.form.TextArea.superclass.onDestroy.call(this);
26305     },
26306
26307     fireKey : function(e){
26308         if(e.isSpecialKey() && (this.enterIsSpecial || (e.getKey() != e.ENTER || e.hasModifier()))){
26309             this.fireEvent("specialkey", this, e);
26310         }
26311     },
26312
26313         onKeyUp : function(e){
26314         if(!e.isNavKeyPress() || e.getKey() == e.ENTER){
26315             this.autoSize();
26316         }
26317     },
26318
26319     
26320     autoSize : function(){
26321         if(!this.grow || !this.textSizeEl){
26322             return;
26323         }
26324         var el = this.el;
26325         var v = el.dom.value;
26326         var ts = this.textSizeEl;
26327         ts.innerHTML = '';
26328         ts.appendChild(document.createTextNode(v));
26329         v = ts.innerHTML;
26330
26331         Ext.fly(ts).setWidth(this.el.getWidth());
26332         if(v.length < 1){
26333             v = "&#160;&#160;";
26334         }else{
26335             if(Ext.isIE){
26336                 v = v.replace(/\n/g, '<p>&#160;</p>');
26337             }
26338             v += this.growAppend;
26339         }
26340         ts.innerHTML = v;
26341         var h = Math.min(this.growMax, Math.max(ts.offsetHeight, this.growMin)+this.growPad);
26342         if(h != this.lastHeight){
26343             this.lastHeight = h;
26344             this.el.setHeight(h);
26345             this.fireEvent("autosize", this, h);
26346         }
26347     }
26348 });
26349 Ext.reg('textarea', Ext.form.TextArea);
26350
26351 Ext.form.NumberField = Ext.extend(Ext.form.TextField,  {
26352     
26353     fieldClass: "x-form-field x-form-num-field",
26354     
26355     allowDecimals : true,
26356     
26357     decimalSeparator : ".",
26358     
26359     decimalPrecision : 2,
26360     
26361     allowNegative : true,
26362     
26363     minValue : Number.NEGATIVE_INFINITY,
26364     
26365     maxValue : Number.MAX_VALUE,
26366     
26367     minText : "The minimum value for this field is {0}",
26368     
26369     maxText : "The maximum value for this field is {0}",
26370     
26371     nanText : "{0} is not a valid number",
26372     
26373     baseChars : "0123456789",
26374
26375         initEvents : function(){
26376         Ext.form.NumberField.superclass.initEvents.call(this);
26377         var allowed = this.baseChars+'';
26378         if(this.allowDecimals){
26379             allowed += this.decimalSeparator;
26380         }
26381         if(this.allowNegative){
26382             allowed += "-";
26383         }
26384         this.stripCharsRe = new RegExp('[^'+allowed+']', 'gi');
26385         var keyPress = function(e){
26386             var k = e.getKey();
26387             if(!Ext.isIE && (e.isSpecialKey() || k == e.BACKSPACE || k == e.DELETE)){
26388                 return;
26389             }
26390             var c = e.getCharCode();
26391             if(allowed.indexOf(String.fromCharCode(c)) === -1){
26392                 e.stopEvent();
26393             }
26394         };
26395         this.el.on("keypress", keyPress, this);
26396     },
26397
26398         validateValue : function(value){
26399         if(!Ext.form.NumberField.superclass.validateValue.call(this, value)){
26400             return false;
26401         }
26402         if(value.length < 1){              return true;
26403         }
26404         value = String(value).replace(this.decimalSeparator, ".");
26405         if(isNaN(value)){
26406             this.markInvalid(String.format(this.nanText, value));
26407             return false;
26408         }
26409         var num = this.parseValue(value);
26410         if(num < this.minValue){
26411             this.markInvalid(String.format(this.minText, this.minValue));
26412             return false;
26413         }
26414         if(num > this.maxValue){
26415             this.markInvalid(String.format(this.maxText, this.maxValue));
26416             return false;
26417         }
26418         return true;
26419     },
26420
26421     getValue : function(){
26422         return this.fixPrecision(this.parseValue(Ext.form.NumberField.superclass.getValue.call(this)));
26423     },
26424
26425     setValue : function(v){
26426         v = parseFloat(v);
26427         v = isNaN(v) ? '' : String(v).replace(".", this.decimalSeparator);
26428         Ext.form.NumberField.superclass.setValue.call(this, v);
26429     },
26430
26431         parseValue : function(value){
26432         value = parseFloat(String(value).replace(this.decimalSeparator, "."));
26433         return isNaN(value) ? '' : value;
26434     },
26435
26436         fixPrecision : function(value){
26437         var nan = isNaN(value);
26438         if(!this.allowDecimals || this.decimalPrecision == -1 || nan || !value){
26439            return nan ? '' : value;
26440         }
26441         return parseFloat(parseFloat(value).toFixed(this.decimalPrecision));
26442     },
26443
26444     beforeBlur : function(){
26445         var v = this.parseValue(this.getRawValue());
26446         if(v){
26447             this.setValue(this.fixPrecision(v));
26448         }
26449     }
26450 });
26451 Ext.reg('numberfield', Ext.form.NumberField);
26452
26453 Ext.form.DateField = Ext.extend(Ext.form.TriggerField,  {
26454     
26455     format : "m/d/y",
26456     
26457     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",
26458     
26459     disabledDays : null,
26460     
26461     disabledDaysText : "Disabled",
26462     
26463     disabledDates : null,
26464     
26465     disabledDatesText : "Disabled",
26466     
26467     minValue : null,
26468     
26469     maxValue : null,
26470     
26471     minText : "The date in this field must be equal to or after {0}",
26472     
26473     maxText : "The date in this field must be equal to or before {0}",
26474     
26475     invalidText : "{0} is not a valid date - it must be in the format {1}",
26476     
26477     triggerClass : 'x-form-date-trigger',
26478     
26479
26480         defaultAutoCreate : {tag: "input", type: "text", size: "10", autocomplete: "off"},
26481
26482     initComponent : function(){
26483         Ext.form.DateField.superclass.initComponent.call(this);
26484         if(typeof this.minValue == "string"){
26485             this.minValue = this.parseDate(this.minValue);
26486         }
26487         if(typeof this.maxValue == "string"){
26488             this.maxValue = this.parseDate(this.maxValue);
26489         }
26490         this.ddMatch = null;
26491         if(this.disabledDates){
26492             var dd = this.disabledDates;
26493             var re = "(?:";
26494             for(var i = 0; i < dd.length; i++){
26495                 re += dd[i];
26496                 if(i != dd.length-1) re += "|";
26497             }
26498             this.ddMatch = new RegExp(re + ")");
26499         }
26500     },
26501
26502         validateValue : function(value){
26503         value = this.formatDate(value);
26504         if(!Ext.form.DateField.superclass.validateValue.call(this, value)){
26505             return false;
26506         }
26507         if(value.length < 1){              return true;
26508         }
26509         var svalue = value;
26510         value = this.parseDate(value);
26511         if(!value){
26512             this.markInvalid(String.format(this.invalidText, svalue, this.format));
26513             return false;
26514         }
26515         var time = value.getTime();
26516         if(this.minValue && time < this.minValue.getTime()){
26517             this.markInvalid(String.format(this.minText, this.formatDate(this.minValue)));
26518             return false;
26519         }
26520         if(this.maxValue && time > this.maxValue.getTime()){
26521             this.markInvalid(String.format(this.maxText, this.formatDate(this.maxValue)));
26522             return false;
26523         }
26524         if(this.disabledDays){
26525             var day = value.getDay();
26526             for(var i = 0; i < this.disabledDays.length; i++) {
26527                 if(day === this.disabledDays[i]){
26528                     this.markInvalid(this.disabledDaysText);
26529                     return false;
26530                 }
26531             }
26532         }
26533         var fvalue = this.formatDate(value);
26534         if(this.ddMatch && this.ddMatch.test(fvalue)){
26535             this.markInvalid(String.format(this.disabledDatesText, fvalue));
26536             return false;
26537         }
26538         return true;
26539     },
26540
26541             validateBlur : function(){
26542         return !this.menu || !this.menu.isVisible();
26543     },
26544
26545     
26546     getValue : function(){
26547         return this.parseDate(Ext.form.DateField.superclass.getValue.call(this)) || "";
26548     },
26549
26550     
26551     setValue : function(date){
26552         Ext.form.DateField.superclass.setValue.call(this, this.formatDate(this.parseDate(date)));
26553     },
26554
26555         parseDate : function(value){
26556         if(!value || Ext.isDate(value)){
26557             return value;
26558         }
26559         var v = Date.parseDate(value, this.format);
26560         if(!v && this.altFormats){
26561             if(!this.altFormatsArray){
26562                 this.altFormatsArray = this.altFormats.split("|");
26563             }
26564             for(var i = 0, len = this.altFormatsArray.length; i < len && !v; i++){
26565                 v = Date.parseDate(value, this.altFormatsArray[i]);
26566             }
26567         }
26568         return v;
26569     },
26570
26571         onDestroy : function(){
26572         if(this.menu) {
26573             this.menu.destroy();
26574         }
26575         if(this.wrap){
26576             this.wrap.remove();
26577         }
26578         Ext.form.DateField.superclass.onDestroy.call(this);
26579     },
26580
26581         formatDate : function(date){
26582         return Ext.isDate(date) ? date.dateFormat(this.format) : date;
26583     },
26584
26585         menuListeners : {
26586         select: function(m, d){
26587             this.setValue(d);
26588         },
26589         show : function(){             this.onFocus();
26590         },
26591         hide : function(){
26592             this.focus.defer(10, this);
26593             var ml = this.menuListeners;
26594             this.menu.un("select", ml.select,  this);
26595             this.menu.un("show", ml.show,  this);
26596             this.menu.un("hide", ml.hide,  this);
26597         }
26598     },
26599
26600             onTriggerClick : function(){
26601         if(this.disabled){
26602             return;
26603         }
26604         if(this.menu == null){
26605             this.menu = new Ext.menu.DateMenu();
26606         }
26607         Ext.apply(this.menu.picker,  {
26608             minDate : this.minValue,
26609             maxDate : this.maxValue,
26610             disabledDatesRE : this.ddMatch,
26611             disabledDatesText : this.disabledDatesText,
26612             disabledDays : this.disabledDays,
26613             disabledDaysText : this.disabledDaysText,
26614             format : this.format,
26615             minText : String.format(this.minText, this.formatDate(this.minValue)),
26616             maxText : String.format(this.maxText, this.formatDate(this.maxValue))
26617         });
26618         this.menu.on(Ext.apply({}, this.menuListeners, {
26619             scope:this
26620         }));
26621         this.menu.picker.setValue(this.getValue() || new Date());
26622         this.menu.show(this.el, "tl-bl?");
26623     },
26624
26625     beforeBlur : function(){
26626         var v = this.parseDate(this.getRawValue());
26627         if(v){
26628             this.setValue(v);
26629         }
26630     }
26631
26632     
26633     
26634     
26635     
26636 });
26637 Ext.reg('datefield', Ext.form.DateField);
26638
26639 Ext.form.ComboBox = Ext.extend(Ext.form.TriggerField, {
26640     
26641     
26642     
26643     
26644     
26645
26646         defaultAutoCreate : {tag: "input", type: "text", size: "24", autocomplete: "off"},
26647     
26648     
26649     
26650     
26651     
26652     
26653     listClass: '',
26654     
26655     selectedClass: 'x-combo-selected',
26656     
26657     triggerClass : 'x-form-arrow-trigger',
26658     
26659     shadow:'sides',
26660     
26661     listAlign: 'tl-bl?',
26662     
26663     maxHeight: 300,
26664     
26665     minHeight: 90,
26666     
26667     triggerAction: 'query',
26668     
26669     minChars : 4,
26670     
26671     typeAhead: false,
26672     
26673     queryDelay: 500,
26674     
26675     pageSize: 0,
26676     
26677     selectOnFocus:false,
26678     
26679     queryParam: 'query',
26680     
26681     loadingText: 'Loading...',
26682     
26683     resizable: false,
26684     
26685     handleHeight : 8,
26686     
26687     editable: true,
26688     
26689     allQuery: '',
26690     
26691     mode: 'remote',
26692     
26693     minListWidth : 70,
26694     
26695     forceSelection:false,
26696     
26697     typeAheadDelay : 250,
26698     
26699
26700     
26701     lazyInit : true,
26702
26703     initComponent : function(){
26704         Ext.form.ComboBox.superclass.initComponent.call(this);
26705         this.addEvents(
26706             
26707             'expand',
26708             
26709             'collapse',
26710             
26711             'beforeselect',
26712             
26713             'select',
26714             
26715             'beforequery'
26716         );
26717         if(this.transform){
26718             this.allowDomMove = false;
26719             var s = Ext.getDom(this.transform);
26720             if(!this.hiddenName){
26721                 this.hiddenName = s.name;
26722             }
26723             if(!this.store){
26724                 this.mode = 'local';
26725                 var d = [], opts = s.options;
26726                 for(var i = 0, len = opts.length;i < len; i++){
26727                     var o = opts[i];
26728                     var value = (Ext.isIE ? o.getAttributeNode('value').specified : o.hasAttribute('value')) ? o.value : o.text;
26729                     if(o.selected) {
26730                         this.value = value;
26731                     }
26732                     d.push([value, o.text]);
26733                 }
26734                 this.store = new Ext.data.SimpleStore({
26735                     'id': 0,
26736                     fields: ['value', 'text'],
26737                     data : d
26738                 });
26739                 this.valueField = 'value';
26740                 this.displayField = 'text';
26741             }
26742             s.name = Ext.id();             if(!this.lazyRender){
26743                 this.target = true;
26744                 this.el = Ext.DomHelper.insertBefore(s, this.autoCreate || this.defaultAutoCreate);
26745                 Ext.removeNode(s);                 this.render(this.el.parentNode);
26746             }else{
26747                 Ext.removeNode(s);             }
26748
26749         }
26750         this.selectedIndex = -1;
26751         if(this.mode == 'local'){
26752             if(this.initialConfig.queryDelay === undefined){
26753                 this.queryDelay = 10;
26754             }
26755             if(this.initialConfig.minChars === undefined){
26756                 this.minChars = 0;
26757             }
26758         }
26759     },
26760
26761         onRender : function(ct, position){
26762         Ext.form.ComboBox.superclass.onRender.call(this, ct, position);
26763         if(this.hiddenName){
26764             this.hiddenField = this.el.insertSibling({tag:'input', type:'hidden', name: this.hiddenName, id: (this.hiddenId||this.hiddenName)},
26765                     'before', true);
26766             this.hiddenField.value =
26767                 this.hiddenValue !== undefined ? this.hiddenValue :
26768                 this.value !== undefined ? this.value : '';
26769
26770                         this.el.dom.removeAttribute('name');
26771         }
26772         if(Ext.isGecko){
26773             this.el.dom.setAttribute('autocomplete', 'off');
26774         }
26775
26776         if(!this.lazyInit){
26777             this.initList();
26778         }else{
26779             this.on('focus', this.initList, this, {single: true});
26780         }
26781
26782         if(!this.editable){
26783             this.editable = true;
26784             this.setEditable(false);
26785         }
26786     },
26787
26788     initList : function(){
26789         if(!this.list){
26790             var cls = 'x-combo-list';
26791
26792             this.list = new Ext.Layer({
26793                 shadow: this.shadow, cls: [cls, this.listClass].join(' '), constrain:false
26794             });
26795
26796             var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);
26797             this.list.setWidth(lw);
26798             this.list.swallowEvent('mousewheel');
26799             this.assetHeight = 0;
26800
26801             if(this.title){
26802                 this.header = this.list.createChild({cls:cls+'-hd', html: this.title});
26803                 this.assetHeight += this.header.getHeight();
26804             }
26805
26806             this.innerList = this.list.createChild({cls:cls+'-inner'});
26807             this.innerList.on('mouseover', this.onViewOver, this);
26808             this.innerList.on('mousemove', this.onViewMove, this);
26809             this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
26810
26811             if(this.pageSize){
26812                 this.footer = this.list.createChild({cls:cls+'-ft'});
26813                 this.pageTb = new Ext.PagingToolbar({
26814                     store:this.store,
26815                     pageSize: this.pageSize,
26816                     renderTo:this.footer
26817                 });
26818                 this.assetHeight += this.footer.getHeight();
26819             }
26820
26821             if(!this.tpl){
26822                             
26823                 this.tpl = '<tpl for="."><div class="'+cls+'-item">{' + this.displayField + '}</div></tpl>';
26824             }
26825
26826                     
26827             this.view = new Ext.DataView({
26828                 applyTo: this.innerList,
26829                 tpl: this.tpl,
26830                 singleSelect: true,
26831                 selectedClass: this.selectedClass,
26832                 itemSelector: this.itemSelector || '.' + cls + '-item'
26833             });
26834
26835             this.view.on('click', this.onViewClick, this);
26836
26837             this.bindStore(this.store, true);
26838
26839             if(this.resizable){
26840                 this.resizer = new Ext.Resizable(this.list,  {
26841                    pinned:true, handles:'se'
26842                 });
26843                 this.resizer.on('resize', function(r, w, h){
26844                     this.maxHeight = h-this.handleHeight-this.list.getFrameWidth('tb')-this.assetHeight;
26845                     this.listWidth = w;
26846                     this.innerList.setWidth(w - this.list.getFrameWidth('lr'));
26847                     this.restrictHeight();
26848                 }, this);
26849                 this[this.pageSize?'footer':'innerList'].setStyle('margin-bottom', this.handleHeight+'px');
26850             }
26851         }
26852     },
26853
26854
26855         bindStore : function(store, initial){
26856         if(this.store && !initial){
26857             this.store.un('beforeload', this.onBeforeLoad, this);
26858             this.store.un('load', this.onLoad, this);
26859             this.store.un('loadexception', this.collapse, this);
26860             if(!store){
26861                 this.store = null;
26862                 if(this.view){
26863                     this.view.setStore(null);
26864                 }
26865             }
26866         }
26867         if(store){
26868             this.store = Ext.StoreMgr.lookup(store);
26869
26870             this.store.on('beforeload', this.onBeforeLoad, this);
26871             this.store.on('load', this.onLoad, this);
26872             this.store.on('loadexception', this.collapse, this);
26873
26874             if(this.view){
26875                 this.view.setStore(store);
26876             }
26877         }
26878     },
26879
26880         initEvents : function(){
26881         Ext.form.ComboBox.superclass.initEvents.call(this);
26882
26883         this.keyNav = new Ext.KeyNav(this.el, {
26884             "up" : function(e){
26885                 this.inKeyMode = true;
26886                 this.selectPrev();
26887             },
26888
26889             "down" : function(e){
26890                 if(!this.isExpanded()){
26891                     this.onTriggerClick();
26892                 }else{
26893                     this.inKeyMode = true;
26894                     this.selectNext();
26895                 }
26896             },
26897
26898             "enter" : function(e){
26899                 this.onViewClick();
26900                 this.delayedCheck = true;
26901                                 this.unsetDelayCheck.defer(10, this);
26902             },
26903
26904             "esc" : function(e){
26905                 this.collapse();
26906             },
26907
26908             "tab" : function(e){
26909                 this.onViewClick(false);
26910                 return true;
26911             },
26912
26913             scope : this,
26914
26915             doRelay : function(foo, bar, hname){
26916                 if(hname == 'down' || this.scope.isExpanded()){
26917                    return Ext.KeyNav.prototype.doRelay.apply(this, arguments);
26918                 }
26919                 return true;
26920             },
26921
26922             forceKeyDown : true
26923         });
26924         this.queryDelay = Math.max(this.queryDelay || 10,
26925                 this.mode == 'local' ? 10 : 250);
26926         this.dqTask = new Ext.util.DelayedTask(this.initQuery, this);
26927         if(this.typeAhead){
26928             this.taTask = new Ext.util.DelayedTask(this.onTypeAhead, this);
26929         }
26930         if(this.editable !== false){
26931             this.el.on("keyup", this.onKeyUp, this);
26932         }
26933         if(this.forceSelection){
26934             this.on('blur', this.doForce, this);
26935         }
26936     },
26937
26938     onDestroy : function(){
26939         if(this.view){
26940             this.view.el.removeAllListeners();
26941             this.view.el.remove();
26942             this.view.purgeListeners();
26943         }
26944         if(this.list){
26945             this.list.destroy();
26946         }
26947         this.bindStore(null);
26948         Ext.form.ComboBox.superclass.onDestroy.call(this);
26949     },
26950
26951         unsetDelayCheck : function(){
26952                 delete this.delayedCheck;
26953         },
26954         fireKey : function(e){
26955         if(e.isNavKeyPress() && !this.isExpanded() && !this.delayedCheck){
26956             this.fireEvent("specialkey", this, e);
26957         }
26958     },
26959
26960         onResize: function(w, h){
26961         Ext.form.ComboBox.superclass.onResize.apply(this, arguments);
26962         if(this.list && this.listWidth === undefined){
26963             var lw = Math.max(w, this.minListWidth);
26964             this.list.setWidth(lw);
26965             this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
26966         }
26967     },
26968
26969         onEnable: function(){
26970         Ext.form.ComboBox.superclass.onEnable.apply(this, arguments);
26971         if(this.hiddenField){
26972             this.hiddenField.disabled = false;
26973         }
26974     },
26975
26976         onDisable: function(){
26977         Ext.form.ComboBox.superclass.onDisable.apply(this, arguments);
26978         if(this.hiddenField){
26979             this.hiddenField.disabled = true;
26980         }
26981     },
26982
26983     
26984     setEditable : function(value){
26985         if(value == this.editable){
26986             return;
26987         }
26988         this.editable = value;
26989         if(!value){
26990             this.el.dom.setAttribute('readOnly', true);
26991             this.el.on('mousedown', this.onTriggerClick,  this);
26992             this.el.addClass('x-combo-noedit');
26993         }else{
26994             this.el.dom.setAttribute('readOnly', false);
26995             this.el.un('mousedown', this.onTriggerClick,  this);
26996             this.el.removeClass('x-combo-noedit');
26997         }
26998     },
26999
27000         onBeforeLoad : function(){
27001         if(!this.hasFocus){
27002             return;
27003         }
27004         this.innerList.update(this.loadingText ?
27005                '<div class="loading-indicator">'+this.loadingText+'</div>' : '');
27006         this.restrictHeight();
27007         this.selectedIndex = -1;
27008     },
27009
27010         onLoad : function(){
27011         if(!this.hasFocus){
27012             return;
27013         }
27014         if(this.store.getCount() > 0){
27015             this.expand();
27016             this.restrictHeight();
27017             if(this.lastQuery == this.allQuery){
27018                 if(this.editable){
27019                     this.el.dom.select();
27020                 }
27021                 if(!this.selectByValue(this.value, true)){
27022                     this.select(0, true);
27023                 }
27024             }else{
27025                 this.selectNext();
27026                 if(this.typeAhead && this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE){
27027                     this.taTask.delay(this.typeAheadDelay);
27028                 }
27029             }
27030         }else{
27031             this.onEmptyResults();
27032         }
27033             },
27034
27035         onTypeAhead : function(){
27036         if(this.store.getCount() > 0){
27037             var r = this.store.getAt(0);
27038             var newValue = r.data[this.displayField];
27039             var len = newValue.length;
27040             var selStart = this.getRawValue().length;
27041             if(selStart != len){
27042                 this.setRawValue(newValue);
27043                 this.selectText(selStart, newValue.length);
27044             }
27045         }
27046     },
27047
27048         onSelect : function(record, index){
27049         if(this.fireEvent('beforeselect', this, record, index) !== false){
27050             this.setValue(record.data[this.valueField || this.displayField]);
27051             this.collapse();
27052             this.fireEvent('select', this, record, index);
27053         }
27054     },
27055
27056     
27057     getValue : function(){
27058         if(this.valueField){
27059             return typeof this.value != 'undefined' ? this.value : '';
27060         }else{
27061             return Ext.form.ComboBox.superclass.getValue.call(this);
27062         }
27063     },
27064
27065     
27066     clearValue : function(){
27067         if(this.hiddenField){
27068             this.hiddenField.value = '';
27069         }
27070         this.setRawValue('');
27071         this.lastSelectionText = '';
27072         this.applyEmptyText();
27073         this.value = '';
27074     },
27075
27076     
27077     setValue : function(v){
27078         var text = v;
27079         if(this.valueField){
27080             var r = this.findRecord(this.valueField, v);
27081             if(r){
27082                 text = r.data[this.displayField];
27083             }else if(this.valueNotFoundText !== undefined){
27084                 text = this.valueNotFoundText;
27085             }
27086         }
27087         this.lastSelectionText = text;
27088         if(this.hiddenField){
27089             this.hiddenField.value = v;
27090         }
27091         Ext.form.ComboBox.superclass.setValue.call(this, text);
27092         this.value = v;
27093     },
27094
27095         findRecord : function(prop, value){
27096         var record;
27097         if(this.store.getCount() > 0){
27098             this.store.each(function(r){
27099                 if(r.data[prop] == value){
27100                     record = r;
27101                     return false;
27102                 }
27103             });
27104         }
27105         return record;
27106     },
27107
27108         onViewMove : function(e, t){
27109         this.inKeyMode = false;
27110     },
27111
27112         onViewOver : function(e, t){
27113         if(this.inKeyMode){             return;
27114         }
27115         var item = this.view.findItemFromChild(t);
27116         if(item){
27117             var index = this.view.indexOf(item);
27118             this.select(index, false);
27119         }
27120     },
27121
27122         onViewClick : function(doFocus){
27123         var index = this.view.getSelectedIndexes()[0];
27124         var r = this.store.getAt(index);
27125         if(r){
27126             this.onSelect(r, index);
27127         }
27128         if(doFocus !== false){
27129             this.el.focus();
27130         }
27131     },
27132
27133         restrictHeight : function(){
27134         this.innerList.dom.style.height = '';
27135         var inner = this.innerList.dom;
27136         var pad = this.list.getFrameWidth('tb')+(this.resizable?this.handleHeight:0)+this.assetHeight;
27137         var h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight);
27138         var ha = this.getPosition()[1]-Ext.getBody().getScroll().top;
27139         var hb = Ext.lib.Dom.getViewHeight()-ha-this.getSize().height;
27140         var space = Math.max(ha, hb, this.minHeight || 0)-this.list.shadow.offset-pad-2;
27141         h = Math.min(h, space, this.maxHeight);
27142         
27143         this.innerList.setHeight(h);
27144         this.list.beginUpdate();
27145         this.list.setHeight(h+pad);
27146         this.list.alignTo(this.el, this.listAlign);
27147         this.list.endUpdate();
27148     },
27149
27150         onEmptyResults : function(){
27151         this.collapse();
27152     },
27153
27154     
27155     isExpanded : function(){
27156         return this.list && this.list.isVisible();
27157     },
27158
27159     
27160     selectByValue : function(v, scrollIntoView){
27161         if(v !== undefined && v !== null){
27162             var r = this.findRecord(this.valueField || this.displayField, v);
27163             if(r){
27164                 this.select(this.store.indexOf(r), scrollIntoView);
27165                 return true;
27166             }
27167         }
27168         return false;
27169     },
27170
27171     
27172     select : function(index, scrollIntoView){
27173         this.selectedIndex = index;
27174         this.view.select(index);
27175         if(scrollIntoView !== false){
27176             var el = this.view.getNode(index);
27177             if(el){
27178                 this.innerList.scrollChildIntoView(el, false);
27179             }
27180         }
27181     },
27182
27183         selectNext : function(){
27184         var ct = this.store.getCount();
27185         if(ct > 0){
27186             if(this.selectedIndex == -1){
27187                 this.select(0);
27188             }else if(this.selectedIndex < ct-1){
27189                 this.select(this.selectedIndex+1);
27190             }
27191         }
27192     },
27193
27194         selectPrev : function(){
27195         var ct = this.store.getCount();
27196         if(ct > 0){
27197             if(this.selectedIndex == -1){
27198                 this.select(0);
27199             }else if(this.selectedIndex != 0){
27200                 this.select(this.selectedIndex-1);
27201             }
27202         }
27203     },
27204
27205         onKeyUp : function(e){
27206         if(this.editable !== false && !e.isSpecialKey()){
27207             this.lastKey = e.getKey();
27208             this.dqTask.delay(this.queryDelay);
27209         }
27210     },
27211
27212         validateBlur : function(){
27213         return !this.list || !this.list.isVisible();
27214     },
27215
27216         initQuery : function(){
27217         this.doQuery(this.getRawValue());
27218     },
27219
27220         doForce : function(){
27221         if(this.el.dom.value.length > 0){
27222             this.el.dom.value =
27223                 this.lastSelectionText === undefined ? '' : this.lastSelectionText;
27224             this.applyEmptyText();
27225         }
27226     },
27227
27228     
27229     doQuery : function(q, forceAll){
27230         if(q === undefined || q === null){
27231             q = '';
27232         }
27233         var qe = {
27234             query: q,
27235             forceAll: forceAll,
27236             combo: this,
27237             cancel:false
27238         };
27239         if(this.fireEvent('beforequery', qe)===false || qe.cancel){
27240             return false;
27241         }
27242         q = qe.query;
27243         forceAll = qe.forceAll;
27244         if(forceAll === true || (q.length >= this.minChars)){
27245             if(this.lastQuery !== q){
27246                 this.lastQuery = q;
27247                 if(this.mode == 'local'){
27248                     this.selectedIndex = -1;
27249                     if(forceAll){
27250                         this.store.clearFilter();
27251                     }else{
27252                         this.store.filter(this.displayField, q);
27253                     }
27254                     this.onLoad();
27255                 }else{
27256                     this.store.baseParams[this.queryParam] = q;
27257                     this.store.load({
27258                         params: this.getParams(q)
27259                     });
27260                     this.expand();
27261                 }
27262             }else{
27263                 this.selectedIndex = -1;
27264                 this.onLoad();
27265             }
27266         }
27267     },
27268
27269         getParams : function(q){
27270         var p = {};
27271                 if(this.pageSize){
27272             p.start = 0;
27273             p.limit = this.pageSize;
27274         }
27275         return p;
27276     },
27277
27278     
27279     collapse : function(){
27280         if(!this.isExpanded()){
27281             return;
27282         }
27283         this.list.hide();
27284         Ext.getDoc().un('mousewheel', this.collapseIf, this);
27285         Ext.getDoc().un('mousedown', this.collapseIf, this);
27286         this.fireEvent('collapse', this);
27287     },
27288
27289         collapseIf : function(e){
27290         if(!e.within(this.wrap) && !e.within(this.list)){
27291             this.collapse();
27292         }
27293     },
27294
27295     
27296     expand : function(){
27297         if(this.isExpanded() || !this.hasFocus){
27298             return;
27299         }
27300         this.list.alignTo(this.wrap, this.listAlign);
27301         this.list.show();
27302         this.innerList.setOverflow('auto');         Ext.getDoc().on('mousewheel', this.collapseIf, this);
27303         Ext.getDoc().on('mousedown', this.collapseIf, this);
27304         this.fireEvent('expand', this);
27305     },
27306
27307             onTriggerClick : function(){
27308         if(this.disabled){
27309             return;
27310         }
27311         if(this.isExpanded()){
27312             this.collapse();
27313             this.el.focus();
27314         }else {
27315             this.onFocus({});
27316             if(this.triggerAction == 'all') {
27317                 this.doQuery(this.allQuery, true);
27318             } else {
27319                 this.doQuery(this.getRawValue());
27320             }
27321             this.el.focus();
27322         }
27323     }
27324
27325     
27326     
27327     
27328     
27329
27330 });
27331 Ext.reg('combo', Ext.form.ComboBox);
27332
27333 Ext.form.Checkbox = Ext.extend(Ext.form.Field,  {
27334     
27335     focusClass : undefined,
27336     
27337     fieldClass: "x-form-field",
27338     
27339     checked: false,
27340     
27341     defaultAutoCreate : { tag: "input", type: 'checkbox', autocomplete: "off"},
27342     
27343     
27344
27345             initComponent : function(){
27346         Ext.form.Checkbox.superclass.initComponent.call(this);
27347         this.addEvents(
27348             
27349             'check'
27350         );
27351     },
27352
27353         onResize : function(){
27354         Ext.form.Checkbox.superclass.onResize.apply(this, arguments);
27355         if(!this.boxLabel){
27356             this.el.alignTo(this.wrap, 'c-c');
27357         }
27358     },
27359     
27360         initEvents : function(){
27361         Ext.form.Checkbox.superclass.initEvents.call(this);
27362         this.el.on("click", this.onClick,  this);
27363         this.el.on("change", this.onClick,  this);
27364     },
27365
27366             getResizeEl : function(){
27367         return this.wrap;
27368     },
27369
27370         getPositionEl : function(){
27371         return this.wrap;
27372     },
27373
27374     
27375     markInvalid : Ext.emptyFn,
27376     
27377     clearInvalid : Ext.emptyFn,
27378
27379         onRender : function(ct, position){
27380         Ext.form.Checkbox.superclass.onRender.call(this, ct, position);
27381         if(this.inputValue !== undefined){
27382             this.el.dom.value = this.inputValue;
27383         }
27384         this.wrap = this.el.wrap({cls: "x-form-check-wrap"});
27385         if(this.boxLabel){
27386             this.wrap.createChild({tag: 'label', htmlFor: this.el.id, cls: 'x-form-cb-label', html: this.boxLabel});
27387         }
27388         if(this.checked){
27389             this.setValue(true);
27390         }else{
27391             this.checked = this.el.dom.checked;
27392         }
27393     },
27394     
27395         onDestroy : function(){
27396         if(this.wrap){
27397             this.wrap.remove();
27398         }
27399         Ext.form.Checkbox.superclass.onDestroy.call(this);
27400     },
27401
27402         initValue : Ext.emptyFn,
27403
27404     
27405     getValue : function(){
27406         if(this.rendered){
27407             return this.el.dom.checked;
27408         }
27409         return false;
27410     },
27411
27412             onClick : function(){
27413         if(this.el.dom.checked != this.checked){
27414             this.setValue(this.el.dom.checked);
27415         }
27416     },
27417
27418     
27419     setValue : function(v){
27420         this.checked = (v === true || v === 'true' || v == '1' || String(v).toLowerCase() == 'on');
27421         if(this.el && this.el.dom){
27422             this.el.dom.checked = this.checked;
27423             this.el.dom.defaultChecked = this.checked;
27424         }
27425         this.fireEvent("check", this, this.checked);
27426     }
27427 });
27428 Ext.reg('checkbox', Ext.form.Checkbox);
27429
27430 Ext.form.Radio = Ext.extend(Ext.form.Checkbox, {
27431     inputType: 'radio',
27432
27433     
27434     markInvalid : Ext.emptyFn,
27435     
27436     clearInvalid : Ext.emptyFn,
27437
27438     
27439     getGroupValue : function(){
27440         var p = this.el.up('form') || Ext.getBody();
27441         var c = p.child('input[name='+this.el.dom.name+']:checked', true);
27442         return c ? c.value : null;
27443     },
27444     
27445         onClick : function(){
27446         if(this.el.dom.checked != this.checked){
27447                 var p = this.el.up('form') || Ext.getBody();
27448                         var els = p.select('input[name='+this.el.dom.name+']');
27449                         els.each(function(el){
27450                                 if(el.dom.id == this.id){
27451                                         this.setValue(true);
27452                                 }else{
27453                                         Ext.getCmp(el.dom.id).setValue(false);
27454                                 }
27455                         }, this);
27456                 }
27457     },
27458
27459     
27460     setValue : function(v){
27461         if (typeof v == 'boolean') {
27462             Ext.form.Radio.superclass.setValue.call(this, v);
27463         } else {
27464             var r = this.el.up('form').child('input[name='+this.el.dom.name+'][value='+v+']', true);
27465             if (r){
27466                 r.checked = true;
27467             };
27468         }
27469     }
27470 });
27471 Ext.reg('radio', Ext.form.Radio);
27472
27473 Ext.form.Hidden = Ext.extend(Ext.form.Field, {
27474     
27475     inputType : 'hidden',
27476
27477     
27478     onRender : function(){
27479         Ext.form.Hidden.superclass.onRender.apply(this, arguments);
27480     },
27481
27482     
27483     initEvents : function(){
27484         this.originalValue = this.getValue();
27485     },
27486
27487     
27488     setSize : Ext.emptyFn,
27489     setWidth : Ext.emptyFn,
27490     setHeight : Ext.emptyFn,
27491     setPosition : Ext.emptyFn,
27492     setPagePosition : Ext.emptyFn,
27493     markInvalid : Ext.emptyFn,
27494     clearInvalid : Ext.emptyFn
27495 });
27496 Ext.reg('hidden', Ext.form.Hidden);
27497
27498 Ext.form.BasicForm = function(el, config){
27499     Ext.apply(this, config);
27500     
27501     this.items = new Ext.util.MixedCollection(false, function(o){
27502         return o.id || (o.id = Ext.id());
27503     });
27504     this.addEvents(
27505         
27506         'beforeaction',
27507         
27508         'actionfailed',
27509         
27510         'actioncomplete'
27511     );
27512     
27513     if(el){
27514         this.initEl(el);
27515     }
27516     Ext.form.BasicForm.superclass.constructor.call(this);
27517 };
27518
27519 Ext.extend(Ext.form.BasicForm, Ext.util.Observable, {
27520     
27521     
27522     
27523     
27524     
27525     
27526     
27527     timeout: 30,
27528
27529         activeAction : null,
27530
27531     
27532     trackResetOnLoad : false,
27533
27534     
27535     
27536     
27537         initEl : function(el){
27538         this.el = Ext.get(el);
27539         this.id = this.el.id || Ext.id();
27540         if(!this.standardSubmit){
27541             this.el.on('submit', this.onSubmit, this);
27542         }
27543         this.el.addClass('x-form');
27544     },
27545
27546     
27547     getEl: function(){
27548         return this.el;
27549     },
27550
27551         onSubmit : function(e){
27552         e.stopEvent();
27553     },
27554     
27555         destroy: function() {
27556         this.items.each(function(f){
27557             Ext.destroy(f);
27558         });
27559         if(this.el){
27560                         this.el.removeAllListeners();
27561                         this.el.remove();
27562         }
27563                 this.purgeListeners();
27564         },
27565
27566     
27567     isValid : function(){
27568         var valid = true;
27569         this.items.each(function(f){
27570            if(!f.validate()){
27571                valid = false;
27572            }
27573         });
27574         return valid;
27575     },
27576
27577     
27578     isDirty : function(){
27579         var dirty = false;
27580         this.items.each(function(f){
27581            if(f.isDirty()){
27582                dirty = true;
27583                return false;
27584            }
27585         });
27586         return dirty;
27587     },
27588
27589     
27590     doAction : function(action, options){
27591         if(typeof action == 'string'){
27592             action = new Ext.form.Action.ACTION_TYPES[action](this, options);
27593         }
27594         if(this.fireEvent('beforeaction', this, action) !== false){
27595             this.beforeAction(action);
27596             action.run.defer(100, action);
27597         }
27598         return this;
27599     },
27600
27601     
27602     submit : function(options){
27603         if(this.standardSubmit){
27604             var v = this.isValid();
27605             if(v){
27606                 this.el.dom.submit();
27607             }
27608             return v;
27609         }
27610         this.doAction('submit', options);
27611         return this;
27612     },
27613
27614     
27615     load : function(options){
27616         this.doAction('load', options);
27617         return this;
27618     },
27619
27620     
27621     updateRecord : function(record){
27622         record.beginEdit();
27623         var fs = record.fields;
27624         fs.each(function(f){
27625             var field = this.findField(f.name);
27626             if(field){
27627                 record.set(f.name, field.getValue());
27628             }
27629         }, this);
27630         record.endEdit();
27631         return this;
27632     },
27633
27634     
27635     loadRecord : function(record){
27636         this.setValues(record.data);
27637         return this;
27638     },
27639
27640         beforeAction : function(action){
27641         var o = action.options;
27642         if(o.waitMsg){
27643             if(this.waitMsgTarget === true){
27644                 this.el.mask(o.waitMsg, 'x-mask-loading');
27645             }else if(this.waitMsgTarget){
27646                 this.waitMsgTarget = Ext.get(this.waitMsgTarget);
27647                 this.waitMsgTarget.mask(o.waitMsg, 'x-mask-loading');
27648             }else{
27649                 Ext.MessageBox.wait(o.waitMsg, o.waitTitle || this.waitTitle || 'Please Wait...');
27650             }
27651         }
27652     },
27653
27654         afterAction : function(action, success){
27655         this.activeAction = null;
27656         var o = action.options;
27657         if(o.waitMsg){
27658             if(this.waitMsgTarget === true){
27659                 this.el.unmask();
27660             }else if(this.waitMsgTarget){
27661                 this.waitMsgTarget.unmask();
27662             }else{
27663                 Ext.MessageBox.updateProgress(1);
27664                 Ext.MessageBox.hide();
27665             }
27666         }
27667         if(success){
27668             if(o.reset){
27669                 this.reset();
27670             }
27671             Ext.callback(o.success, o.scope, [this, action]);
27672             this.fireEvent('actioncomplete', this, action);
27673         }else{
27674             Ext.callback(o.failure, o.scope, [this, action]);
27675             this.fireEvent('actionfailed', this, action);
27676         }
27677     },
27678
27679     
27680     findField : function(id){
27681         var field = this.items.get(id);
27682         if(!field){
27683             this.items.each(function(f){
27684                 if(f.isFormField && (f.dataIndex == id || f.id == id || f.getName() == id)){
27685                     field = f;
27686                     return false;
27687                 }
27688             });
27689         }
27690         return field || null;
27691     },
27692
27693
27694     
27695     markInvalid : function(errors){
27696         if(Ext.isArray(errors)){
27697             for(var i = 0, len = errors.length; i < len; i++){
27698                 var fieldError = errors[i];
27699                 var f = this.findField(fieldError.id);
27700                 if(f){
27701                     f.markInvalid(fieldError.msg);
27702                 }
27703             }
27704         }else{
27705             var field, id;
27706             for(id in errors){
27707                 if(typeof errors[id] != 'function' && (field = this.findField(id))){
27708                     field.markInvalid(errors[id]);
27709                 }
27710             }
27711         }
27712         return this;
27713     },
27714
27715     
27716     setValues : function(values){
27717         if(Ext.isArray(values)){             for(var i = 0, len = values.length; i < len; i++){
27718                 var v = values[i];
27719                 var f = this.findField(v.id);
27720                 if(f){
27721                     f.setValue(v.value);
27722                     if(this.trackResetOnLoad){
27723                         f.originalValue = f.getValue();
27724                     }
27725                 }
27726             }
27727         }else{             var field, id;
27728             for(id in values){
27729                 if(typeof values[id] != 'function' && (field = this.findField(id))){
27730                     field.setValue(values[id]);
27731                     if(this.trackResetOnLoad){
27732                         field.originalValue = field.getValue();
27733                     }
27734                 }
27735             }
27736         }
27737         return this;
27738     },
27739
27740     
27741     getValues : function(asString){
27742         var fs = Ext.lib.Ajax.serializeForm(this.el.dom);
27743         if(asString === true){
27744             return fs;
27745         }
27746         return Ext.urlDecode(fs);
27747     },
27748
27749     
27750     clearInvalid : function(){
27751         this.items.each(function(f){
27752            f.clearInvalid();
27753         });
27754         return this;
27755     },
27756
27757     
27758     reset : function(){
27759         this.items.each(function(f){
27760             f.reset();
27761         });
27762         return this;
27763     },
27764
27765     
27766     add : function(){
27767         this.items.addAll(Array.prototype.slice.call(arguments, 0));
27768         return this;
27769     },
27770
27771
27772     
27773     remove : function(field){
27774         this.items.remove(field);
27775         return this;
27776     },
27777
27778     
27779     render : function(){
27780         this.items.each(function(f){
27781             if(f.isFormField && !f.rendered && document.getElementById(f.id)){                 f.applyToMarkup(f.id);
27782             }
27783         });
27784         return this;
27785     },
27786
27787     
27788     applyToFields : function(o){
27789         this.items.each(function(f){
27790            Ext.apply(f, o);
27791         });
27792         return this;
27793     },
27794
27795     
27796     applyIfToFields : function(o){
27797         this.items.each(function(f){
27798            Ext.applyIf(f, o);
27799         });
27800         return this;
27801     }
27802 });
27803
27804 Ext.BasicForm = Ext.form.BasicForm;
27805
27806 Ext.FormPanel = Ext.extend(Ext.Panel, {
27807         
27808     
27809     
27810     
27811     buttonAlign:'center',
27812
27813     
27814     minButtonWidth:75,
27815
27816     
27817     labelAlign:'left',
27818
27819     
27820     monitorValid : false,
27821
27822     
27823     monitorPoll : 200,
27824
27825     
27826     layout: 'form',
27827
27828         initComponent :function(){
27829         this.form = this.createForm();
27830         
27831         Ext.FormPanel.superclass.initComponent.call(this);
27832
27833         this.addEvents(
27834             
27835             'clientvalidation'
27836         );
27837
27838         this.relayEvents(this.form, ['beforeaction', 'actionfailed', 'actioncomplete']);
27839     },
27840
27841         createForm: function(){
27842         delete this.initialConfig.listeners;
27843         return new Ext.form.BasicForm(null, this.initialConfig);
27844     },
27845
27846         initFields : function(){
27847         var f = this.form;
27848         var formPanel = this;
27849         var fn = function(c){
27850             if(c.doLayout && c != formPanel){
27851                 Ext.applyIf(c, {
27852                     labelAlign: c.ownerCt.labelAlign,
27853                     labelWidth: c.ownerCt.labelWidth,
27854                     itemCls: c.ownerCt.itemCls
27855                 });
27856                 if(c.items){
27857                     c.items.each(fn);
27858                 }
27859             }else if(c.isFormField){
27860                 f.add(c);
27861             }
27862         }
27863         this.items.each(fn);
27864     },
27865
27866         getLayoutTarget : function(){
27867         return this.form.el;
27868     },
27869
27870     
27871     getForm : function(){
27872         return this.form;
27873     },
27874
27875         onRender : function(ct, position){
27876         this.initFields();
27877
27878         Ext.FormPanel.superclass.onRender.call(this, ct, position);
27879         var o = {
27880             tag: 'form',
27881             method : this.method || 'POST',
27882             id : this.formId || Ext.id()
27883         };
27884         if(this.fileUpload) {
27885             o.enctype = 'multipart/form-data';
27886         }
27887         this.form.initEl(this.body.createChild(o));
27888     },
27889     
27890         beforeDestroy: function(){
27891         Ext.FormPanel.superclass.beforeDestroy.call(this);
27892         Ext.destroy(this.form);
27893     },
27894
27895         initEvents : function(){
27896         Ext.FormPanel.superclass.initEvents.call(this);
27897                 this.items.on('remove', this.onRemove, this);
27898                 this.items.on('add', this.onAdd, this);
27899         if(this.monitorValid){             this.startMonitoring();
27900         }
27901     },
27902     
27903         onAdd : function(ct, c) {
27904                 if (c.isFormField) {
27905                         this.form.add(c);
27906                 }
27907         },
27908         
27909                 onRemove : function(c) {
27910                 if (c.isFormField) {
27911                         Ext.destroy(c.container.up('.x-form-item'));
27912                         this.form.remove(c);
27913                 }
27914         },
27915
27916     
27917     startMonitoring : function(){
27918         if(!this.bound){
27919             this.bound = true;
27920             Ext.TaskMgr.start({
27921                 run : this.bindHandler,
27922                 interval : this.monitorPoll || 200,
27923                 scope: this
27924             });
27925         }
27926     },
27927
27928     
27929     stopMonitoring : function(){
27930         this.bound = false;
27931     },
27932
27933     
27934     load : function(){
27935         this.form.load.apply(this.form, arguments);  
27936     },
27937
27938         onDisable : function(){
27939         Ext.FormPanel.superclass.onDisable.call(this);
27940         if(this.form){
27941             this.form.items.each(function(){
27942                  this.disable();
27943             });
27944         }
27945     },
27946
27947         onEnable : function(){
27948         Ext.FormPanel.superclass.onEnable.call(this);
27949         if(this.form){
27950             this.form.items.each(function(){
27951                  this.enable();
27952             });
27953         }
27954     },
27955
27956         bindHandler : function(){
27957         if(!this.bound){
27958             return false;         }
27959         var valid = true;
27960         this.form.items.each(function(f){
27961             if(!f.isValid(true)){
27962                 valid = false;
27963                 return false;
27964             }
27965         });
27966         if(this.buttons){
27967             for(var i = 0, len = this.buttons.length; i < len; i++){
27968                 var btn = this.buttons[i];
27969                 if(btn.formBind === true && btn.disabled === valid){
27970                     btn.setDisabled(!valid);
27971                 }
27972             }
27973         }
27974         this.fireEvent('clientvalidation', this, valid);
27975     }
27976 });
27977 Ext.reg('form', Ext.FormPanel);
27978
27979 Ext.form.FormPanel = Ext.FormPanel;
27980
27981
27982
27983 Ext.form.FieldSet = Ext.extend(Ext.Panel, {
27984     
27985     
27986     
27987     
27988     
27989     baseCls:'x-fieldset',
27990     
27991     layout: 'form',
27992
27993     
27994     onRender : function(ct, position){
27995         if(!this.el){
27996             this.el = document.createElement('fieldset');
27997             this.el.id = this.id;
27998             if (this.title || this.header || this.checkboxToggle) {
27999                 this.el.appendChild(document.createElement('legend')).className = 'x-fieldset-header';
28000             }
28001         }
28002
28003         Ext.form.FieldSet.superclass.onRender.call(this, ct, position);
28004
28005         if(this.checkboxToggle){
28006             var o = typeof this.checkboxToggle == 'object' ?
28007                     this.checkboxToggle :
28008                     {tag: 'input', type: 'checkbox', name: this.checkboxName || this.id+'-checkbox'};
28009             this.checkbox = this.header.insertFirst(o);
28010             this.checkbox.dom.checked = !this.collapsed;
28011             this.checkbox.on('click', this.onCheckClick, this);
28012         }
28013     },
28014
28015     
28016     onCollapse : function(doAnim, animArg){
28017         if(this.checkbox){
28018             this.checkbox.dom.checked = false;
28019         }
28020         this.afterCollapse();
28021
28022     },
28023
28024     
28025     onExpand : function(doAnim, animArg){
28026         if(this.checkbox){
28027             this.checkbox.dom.checked = true;
28028         }
28029         this.afterExpand();
28030     },
28031
28032     
28033     onCheckClick : function(){
28034         this[this.checkbox.dom.checked ? 'expand' : 'collapse']();
28035     }
28036
28037     
28038     
28039     
28040     
28041     
28042     
28043     
28044     
28045     
28046     
28047     
28048     
28049     
28050     
28051     
28052     
28053     
28054     
28055     
28056     
28057     
28058     
28059     
28060     
28061     
28062     
28063     
28064     
28065     
28066     
28067     
28068     
28069     
28070     
28071     
28072     
28073     
28074 });
28075 Ext.reg('fieldset', Ext.form.FieldSet);
28076
28077
28078
28079
28080 Ext.form.HtmlEditor = Ext.extend(Ext.form.Field, {
28081     
28082     enableFormat : true,
28083     
28084     enableFontSize : true,
28085     
28086     enableColors : true,
28087     
28088     enableAlignments : true,
28089     
28090     enableLists : true,
28091     
28092     enableSourceEdit : true,
28093     
28094     enableLinks : true,
28095     
28096     enableFont : true,
28097     
28098     createLinkText : 'Please enter the URL for the link:',
28099     
28100     defaultLinkValue : 'http:/'+'/',
28101     
28102     fontFamilies : [
28103         'Arial',
28104         'Courier New',
28105         'Tahoma',
28106         'Times New Roman',
28107         'Verdana'
28108     ],
28109     defaultFont: 'tahoma',
28110
28111     
28112     validationEvent : false,
28113     deferHeight: true,
28114     initialized : false,
28115     activated : false,
28116     sourceEditMode : false,
28117     onFocus : Ext.emptyFn,
28118     iframePad:3,
28119     hideMode:'offsets',
28120     defaultAutoCreate : {
28121         tag: "textarea",
28122         style:"width:500px;height:300px;",
28123         autocomplete: "off"
28124     },
28125
28126     
28127     initComponent : function(){
28128         this.addEvents(
28129             
28130             'initialize',
28131             
28132             'activate',
28133              
28134             'beforesync',
28135              
28136             'beforepush',
28137              
28138             'sync',
28139              
28140             'push',
28141              
28142             'editmodechange'
28143         )
28144     },
28145
28146     createFontOptions : function(){
28147         var buf = [], fs = this.fontFamilies, ff, lc;
28148         for(var i = 0, len = fs.length; i< len; i++){
28149             ff = fs[i];
28150             lc = ff.toLowerCase();
28151             buf.push(
28152                 '<option value="',lc,'" style="font-family:',ff,';"',
28153                     (this.defaultFont == lc ? ' selected="true">' : '>'),
28154                     ff,
28155                 '</option>'
28156             );
28157         }
28158         return buf.join('');
28159     },
28160     
28161     createToolbar : function(editor){
28162
28163         function btn(id, toggle, handler){
28164             return {
28165                 itemId : id,
28166                 cls : 'x-btn-icon x-edit-'+id,
28167                 enableToggle:toggle !== false,
28168                 scope: editor,
28169                 handler:handler||editor.relayBtnCmd,
28170                 clickEvent:'mousedown',
28171                 tooltip: editor.buttonTips[id] || undefined,
28172                 tabIndex:-1
28173             };
28174         }
28175
28176         
28177         var tb = new Ext.Toolbar({
28178             renderTo:this.wrap.dom.firstChild
28179         });
28180
28181         
28182         tb.el.on('click', function(e){
28183             e.preventDefault();
28184         });
28185
28186         if(this.enableFont && !Ext.isSafari){
28187             this.fontSelect = tb.el.createChild({
28188                 tag:'select',
28189                 cls:'x-font-select',
28190                 html: this.createFontOptions()
28191             });
28192             this.fontSelect.on('change', function(){
28193                 var font = this.fontSelect.dom.value;
28194                 this.relayCmd('fontname', font);
28195                 this.deferFocus();
28196             }, this);
28197             tb.add(
28198                 this.fontSelect.dom,
28199                 '-'
28200             );
28201         };
28202
28203         if(this.enableFormat){
28204             tb.add(
28205                 btn('bold'),
28206                 btn('italic'),
28207                 btn('underline')
28208             );
28209         };
28210
28211         if(this.enableFontSize){
28212             tb.add(
28213                 '-',
28214                 btn('increasefontsize', false, this.adjustFont),
28215                 btn('decreasefontsize', false, this.adjustFont)
28216             );
28217         };
28218
28219         if(this.enableColors){
28220             tb.add(
28221                 '-', {
28222                     itemId:'forecolor',
28223                     cls:'x-btn-icon x-edit-forecolor',
28224                     clickEvent:'mousedown',
28225                     tooltip: editor.buttonTips['forecolor'] || undefined,
28226                     tabIndex:-1,
28227                     menu : new Ext.menu.ColorMenu({
28228                         allowReselect: true,
28229                         focus: Ext.emptyFn,
28230                         value:'000000',
28231                         plain:true,
28232                         selectHandler: function(cp, color){
28233                             this.execCmd('forecolor', Ext.isSafari || Ext.isIE ? '#'+color : color);
28234                             this.deferFocus();
28235                         },
28236                         scope: this,
28237                         clickEvent:'mousedown'
28238                     })
28239                 }, {
28240                     itemId:'backcolor',
28241                     cls:'x-btn-icon x-edit-backcolor',
28242                     clickEvent:'mousedown',
28243                     tooltip: editor.buttonTips['backcolor'] || undefined,
28244                     tabIndex:-1,
28245                     menu : new Ext.menu.ColorMenu({
28246                         focus: Ext.emptyFn,
28247                         value:'FFFFFF',
28248                         plain:true,
28249                         allowReselect: true,
28250                         selectHandler: function(cp, color){
28251                             if(Ext.isGecko){
28252                                 this.execCmd('useCSS', false);
28253                                 this.execCmd('hilitecolor', color);
28254                                 this.execCmd('useCSS', true);
28255                                 this.deferFocus();
28256                             }else{
28257                                 this.execCmd(Ext.isOpera ? 'hilitecolor' : 'backcolor', Ext.isSafari || Ext.isIE ? '#'+color : color);
28258                                 this.deferFocus();
28259                             }
28260                         },
28261                         scope:this,
28262                         clickEvent:'mousedown'
28263                     })
28264                 }
28265             );
28266         };
28267
28268         if(this.enableAlignments){
28269             tb.add(
28270                 '-',
28271                 btn('justifyleft'),
28272                 btn('justifycenter'),
28273                 btn('justifyright')
28274             );
28275         };
28276
28277         if(!Ext.isSafari){
28278             if(this.enableLinks){
28279                 tb.add(
28280                     '-',
28281                     btn('createlink', false, this.createLink)
28282                 );
28283             };
28284
28285             if(this.enableLists){
28286                 tb.add(
28287                     '-',
28288                     btn('insertorderedlist'),
28289                     btn('insertunorderedlist')
28290                 );
28291             }
28292             if(this.enableSourceEdit){
28293                 tb.add(
28294                     '-',
28295                     btn('sourceedit', true, function(btn){
28296                         this.toggleSourceEdit(btn.pressed);
28297                     })
28298                 );
28299             }
28300         }
28301
28302         this.tb = tb;
28303     },
28304
28305     
28306     getDocMarkup : function(){
28307         return '<html><head><style type="text/css">body{border:0;margin:0;padding:3px;height:98%;cursor:text;}</style></head><body></body></html>';
28308     },
28309
28310     getEditorBody : function(){
28311         return this.doc.body || this.doc.documentElement;
28312     },
28313
28314     
28315     onRender : function(ct, position){
28316         Ext.form.HtmlEditor.superclass.onRender.call(this, ct, position);
28317         this.el.dom.style.border = '0 none';
28318         this.el.dom.setAttribute('tabIndex', -1);
28319         this.el.addClass('x-hidden');
28320         if(Ext.isIE){ 
28321             this.el.applyStyles('margin-top:-1px;margin-bottom:-1px;')
28322         }
28323         this.wrap = this.el.wrap({
28324             cls:'x-html-editor-wrap', cn:{cls:'x-html-editor-tb'}
28325         });
28326
28327         this.createToolbar(this);
28328
28329         this.tb.items.each(function(item){
28330            if(item.itemId != 'sourceedit'){
28331                 item.disable();
28332             }
28333         });
28334
28335         var iframe = document.createElement('iframe');
28336         iframe.name = Ext.id();
28337         iframe.frameBorder = 'no';
28338
28339         iframe.src=(Ext.SSL_SECURE_URL || "javascript:false");
28340
28341         this.wrap.dom.appendChild(iframe);
28342
28343         this.iframe = iframe;
28344
28345         if(Ext.isIE){
28346             iframe.contentWindow.document.designMode = 'on';
28347             this.doc = iframe.contentWindow.document;
28348             this.win = iframe.contentWindow;
28349         } else {
28350             this.doc = (iframe.contentDocument || window.frames[iframe.name].document);
28351             this.win = window.frames[iframe.name];
28352             this.doc.designMode = 'on';
28353         }
28354         this.doc.open();
28355         this.doc.write(this.getDocMarkup())
28356         this.doc.close();
28357
28358         var task = { 
28359             run : function(){
28360                 if(this.doc.body || this.doc.readyState == 'complete'){
28361                     Ext.TaskMgr.stop(task);
28362                     this.doc.designMode="on";
28363                     this.initEditor.defer(10, this);
28364                 }
28365             },
28366             interval : 10,
28367             duration:10000,
28368             scope: this
28369         };
28370         Ext.TaskMgr.start(task);
28371
28372         if(!this.width){
28373             this.setSize(this.el.getSize());
28374         }
28375     },
28376
28377     
28378     onResize : function(w, h){
28379         Ext.form.HtmlEditor.superclass.onResize.apply(this, arguments);
28380         if(this.el && this.iframe){
28381             if(typeof w == 'number'){
28382                 var aw = w - this.wrap.getFrameWidth('lr');
28383                 this.el.setWidth(this.adjustWidth('textarea', aw));
28384                 this.iframe.style.width = aw + 'px';
28385             }
28386             if(typeof h == 'number'){
28387                 var ah = h - this.wrap.getFrameWidth('tb') - this.tb.el.getHeight();
28388                 this.el.setHeight(this.adjustWidth('textarea', ah));
28389                 this.iframe.style.height = ah + 'px';
28390                 if(this.doc){
28391                     this.getEditorBody().style.height = (ah - (this.iframePad*2)) + 'px';
28392                 }
28393             }
28394         }
28395     },
28396
28397     
28398     toggleSourceEdit : function(sourceEditMode){
28399         if(sourceEditMode === undefined){
28400             sourceEditMode = !this.sourceEditMode;
28401         }
28402         this.sourceEditMode = sourceEditMode === true;
28403         var btn = this.tb.items.get('sourceedit');
28404         if(btn.pressed !== this.sourceEditMode){
28405             btn.toggle(this.sourceEditMode);
28406             return;
28407         }
28408         if(this.sourceEditMode){
28409             this.tb.items.each(function(item){
28410                 if(item.itemId != 'sourceedit'){
28411                     item.disable();
28412                 }
28413             });
28414             this.syncValue();
28415             this.iframe.className = 'x-hidden';
28416             this.el.removeClass('x-hidden');
28417             this.el.dom.removeAttribute('tabIndex');
28418             this.el.focus();
28419         }else{
28420             if(this.initialized){
28421                 this.tb.items.each(function(item){
28422                     item.enable();
28423                 });
28424             }
28425             this.pushValue();
28426             this.iframe.className = '';
28427             this.el.addClass('x-hidden');
28428             this.el.dom.setAttribute('tabIndex', -1);
28429             this.deferFocus();
28430         }
28431         var lastSize = this.lastSize;
28432         if(lastSize){
28433             delete this.lastSize;
28434             this.setSize(lastSize);
28435         }
28436         this.fireEvent('editmodechange', this, this.sourceEditMode);
28437     },
28438
28439     
28440     createLink : function(){
28441         var url = prompt(this.createLinkText, this.defaultLinkValue);
28442         if(url && url != 'http:/'+'/'){
28443             this.relayCmd('createlink', url);
28444         }
28445     },
28446
28447     
28448     adjustSize : Ext.BoxComponent.prototype.adjustSize,
28449
28450     
28451     getResizeEl : function(){
28452         return this.wrap;
28453     },
28454
28455     
28456     getPositionEl : function(){
28457         return this.wrap;
28458     },
28459
28460     
28461     initEvents : function(){
28462         this.originalValue = this.getValue();
28463     },
28464
28465     
28466     markInvalid : Ext.emptyFn,
28467     
28468     clearInvalid : Ext.emptyFn,
28469
28470     setValue : function(v){
28471         Ext.form.HtmlEditor.superclass.setValue.call(this, v);
28472         this.pushValue();
28473     },
28474
28475     
28476     cleanHtml : function(html){
28477         html = String(html);
28478         if(html.length > 5){
28479             if(Ext.isSafari){ 
28480                 html = html.replace(/\sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi, '');
28481             }
28482         }
28483         if(html == '&nbsp;'){
28484             html = '';
28485         }
28486         return html;
28487     },
28488
28489     
28490     syncValue : function(){
28491         if(this.initialized){
28492             var bd = this.getEditorBody();
28493             var html = bd.innerHTML;
28494             if(Ext.isSafari){
28495                 var bs = bd.getAttribute('style'); 
28496                 var m = bs.match(/text-align:(.*?);/i);
28497                 if(m && m[1]){
28498                     html = '<div style="'+m[0]+'">' + html + '</div>';
28499                 }
28500             }
28501             html = this.cleanHtml(html);
28502             if(this.fireEvent('beforesync', this, html) !== false){
28503                 this.el.dom.value = html;
28504                 this.fireEvent('sync', this, html);
28505             }
28506         }
28507     },
28508
28509     
28510     pushValue : function(){
28511         if(this.initialized){
28512             var v = this.el.dom.value;
28513             if(!this.activated && v.length < 1){
28514                 v = '&nbsp;';
28515             }
28516             if(this.fireEvent('beforepush', this, v) !== false){
28517                 this.getEditorBody().innerHTML = v;
28518                 this.fireEvent('push', this, v);
28519             }
28520         }
28521     },
28522
28523     
28524     deferFocus : function(){
28525         this.focus.defer(10, this);
28526     },
28527
28528     
28529     focus : function(){
28530         if(this.win && !this.sourceEditMode){
28531             this.win.focus();
28532         }else{
28533             this.el.focus();
28534         }
28535     },
28536
28537     
28538     initEditor : function(){
28539         var dbody = this.getEditorBody();
28540         var ss = this.el.getStyles('font-size', 'font-family', 'background-image', 'background-repeat');
28541         ss['background-attachment'] = 'fixed'; 
28542         dbody.bgProperties = 'fixed'; 
28543         Ext.DomHelper.applyStyles(dbody, ss);
28544         Ext.EventManager.on(this.doc, {
28545             'mousedown': this.onEditorEvent,
28546             'dblclick': this.onEditorEvent,
28547             'click': this.onEditorEvent,
28548             'keyup': this.onEditorEvent,
28549             buffer:100,
28550             scope: this
28551         });
28552         if(Ext.isGecko){
28553             Ext.EventManager.on(this.doc, 'keypress', this.applyCommand, this);
28554         }
28555         if(Ext.isIE || Ext.isSafari || Ext.isOpera){
28556             Ext.EventManager.on(this.doc, 'keydown', this.fixKeys, this);
28557         }
28558         this.initialized = true;
28559
28560         this.fireEvent('initialize', this);
28561         this.pushValue();
28562     },
28563
28564     
28565     onDestroy : function(){
28566         if(this.rendered){
28567             this.tb.items.each(function(item){
28568                 if(item.menu){
28569                     item.menu.removeAll();
28570                     if(item.menu.el){
28571                         item.menu.el.destroy();
28572                     }
28573                 }
28574                 item.destroy();
28575             });
28576             this.wrap.dom.innerHTML = '';
28577             this.wrap.remove();
28578         }
28579     },
28580
28581     
28582     onFirstFocus : function(){
28583         this.activated = true;
28584         this.tb.items.each(function(item){
28585            item.enable();
28586         });
28587         if(Ext.isGecko){ 
28588             this.win.focus();
28589             var s = this.win.getSelection();
28590             if(!s.focusNode || s.focusNode.nodeType != 3){
28591                 var r = s.getRangeAt(0);
28592                 r.selectNodeContents(this.getEditorBody());
28593                 r.collapse(true);
28594                 this.deferFocus();
28595             }
28596             try{
28597                 this.execCmd('useCSS', true);
28598                 this.execCmd('styleWithCSS', false);
28599             }catch(e){}
28600         }
28601         this.fireEvent('activate', this);
28602     },
28603
28604     
28605     adjustFont: function(btn){
28606         var adjust = btn.itemId == 'increasefontsize' ? 1 : -1;
28607
28608         var v = parseInt(this.doc.queryCommandValue('FontSize') || 2, 10);
28609         if(Ext.isSafari3 || Ext.isAir){
28610             
28611             
28612             if(v <= 10){
28613                 v = 1 + adjust;
28614             }else if(v <= 13){
28615                 v = 2 + adjust;
28616             }else if(v <= 16){
28617                 v = 3 + adjust;
28618             }else if(v <= 18){
28619                 v = 4 + adjust;
28620             }else if(v <= 24){
28621                 v = 5 + adjust;
28622             }else {
28623                 v = 6 + adjust;
28624             }
28625             v = v.constrain(1, 6);
28626         }else{
28627             if(Ext.isSafari){ 
28628                 adjust *= 2;
28629             }
28630             v = Math.max(1, v+adjust) + (Ext.isSafari ? 'px' : 0);
28631         }
28632         this.execCmd('FontSize', v);
28633     },
28634
28635     onEditorEvent : function(e){
28636         this.updateToolbar();
28637     },
28638
28639
28640     
28641     updateToolbar: function(){
28642
28643         if(!this.activated){
28644             this.onFirstFocus();
28645             return;
28646         }
28647
28648         var btns = this.tb.items.map, doc = this.doc;
28649
28650         if(this.enableFont && !Ext.isSafari){
28651             var name = (this.doc.queryCommandValue('FontName')||this.defaultFont).toLowerCase();
28652             if(name != this.fontSelect.dom.value){
28653                 this.fontSelect.dom.value = name;
28654             }
28655         }
28656         if(this.enableFormat){
28657             btns.bold.toggle(doc.queryCommandState('bold'));
28658             btns.italic.toggle(doc.queryCommandState('italic'));
28659             btns.underline.toggle(doc.queryCommandState('underline'));
28660         }
28661         if(this.enableAlignments){
28662             btns.justifyleft.toggle(doc.queryCommandState('justifyleft'));
28663             btns.justifycenter.toggle(doc.queryCommandState('justifycenter'));
28664             btns.justifyright.toggle(doc.queryCommandState('justifyright'));
28665         }
28666         if(!Ext.isSafari && this.enableLists){
28667             btns.insertorderedlist.toggle(doc.queryCommandState('insertorderedlist'));
28668             btns.insertunorderedlist.toggle(doc.queryCommandState('insertunorderedlist'));
28669         }
28670         
28671         Ext.menu.MenuMgr.hideAll();
28672
28673         this.syncValue();
28674     },
28675
28676     
28677     relayBtnCmd : function(btn){
28678         this.relayCmd(btn.itemId);
28679     },
28680
28681     
28682     relayCmd : function(cmd, value){
28683         this.win.focus();
28684         this.execCmd(cmd, value);
28685         this.updateToolbar();
28686         this.deferFocus();
28687     },
28688
28689     
28690     execCmd : function(cmd, value){
28691         this.doc.execCommand(cmd, false, value === undefined ? null : value);
28692         this.syncValue();
28693     },
28694
28695     
28696     applyCommand : function(e){
28697         if(e.ctrlKey){
28698             var c = e.getCharCode(), cmd;
28699             if(c > 0){
28700                 c = String.fromCharCode(c);
28701                 switch(c){
28702                     case 'b':
28703                         cmd = 'bold';
28704                     break;
28705                     case 'i':
28706                         cmd = 'italic';
28707                     break;
28708                     case 'u':
28709                         cmd = 'underline';
28710                     break;
28711                 }
28712                 if(cmd){
28713                     this.win.focus();
28714                     this.execCmd(cmd);
28715                     this.deferFocus();
28716                     e.preventDefault();
28717                 }
28718             }
28719         }
28720     },
28721
28722     
28723     insertAtCursor : function(text){
28724         if(!this.activated){
28725             return;
28726         }
28727         if(Ext.isIE){
28728             this.win.focus();
28729             var r = this.doc.selection.createRange();
28730             if(r){
28731                 r.collapse(true);
28732                 r.pasteHTML(text);
28733                 this.syncValue();
28734                 this.deferFocus();
28735             }
28736         }else if(Ext.isGecko || Ext.isOpera){
28737             this.win.focus();
28738             this.execCmd('InsertHTML', text);
28739             this.deferFocus();
28740         }else if(Ext.isSafari){
28741             this.execCmd('InsertText', text);
28742             this.deferFocus();
28743         }
28744     },
28745
28746     
28747     fixKeys : function(){ 
28748         if(Ext.isIE){
28749             return function(e){
28750                 var k = e.getKey(), r;
28751                 if(k == e.TAB){
28752                     e.stopEvent();
28753                     r = this.doc.selection.createRange();
28754                     if(r){
28755                         r.collapse(true);
28756                         r.pasteHTML('&nbsp;&nbsp;&nbsp;&nbsp;');
28757                         this.deferFocus();
28758                     }
28759                 }else if(k == e.ENTER){
28760                     r = this.doc.selection.createRange();
28761                     if(r){
28762                         var target = r.parentElement();
28763                         if(!target || target.tagName.toLowerCase() != 'li'){
28764                             e.stopEvent();
28765                             r.pasteHTML('<br />');
28766                             r.collapse(false);
28767                             r.select();
28768                         }
28769                     }
28770                 }
28771             };
28772         }else if(Ext.isOpera){
28773             return function(e){
28774                 var k = e.getKey();
28775                 if(k == e.TAB){
28776                     e.stopEvent();
28777                     this.win.focus();
28778                     this.execCmd('InsertHTML','&nbsp;&nbsp;&nbsp;&nbsp;');
28779                     this.deferFocus();
28780                 }
28781             };
28782         }else if(Ext.isSafari){
28783             return function(e){
28784                 var k = e.getKey();
28785                 if(k == e.TAB){
28786                     e.stopEvent();
28787                     this.execCmd('InsertText','\t');
28788                     this.deferFocus();
28789                 }
28790              };
28791         }
28792     }(),
28793
28794     
28795     getToolbar : function(){
28796         return this.tb;
28797     },
28798
28799     
28800     buttonTips : {
28801         bold : {
28802             title: 'Bold (Ctrl+B)',
28803             text: 'Make the selected text bold.',
28804             cls: 'x-html-editor-tip'
28805         },
28806         italic : {
28807             title: 'Italic (Ctrl+I)',
28808             text: 'Make the selected text italic.',
28809             cls: 'x-html-editor-tip'
28810         },
28811         underline : {
28812             title: 'Underline (Ctrl+U)',
28813             text: 'Underline the selected text.',
28814             cls: 'x-html-editor-tip'
28815         },
28816         increasefontsize : {
28817             title: 'Grow Text',
28818             text: 'Increase the font size.',
28819             cls: 'x-html-editor-tip'
28820         },
28821         decreasefontsize : {
28822             title: 'Shrink Text',
28823             text: 'Decrease the font size.',
28824             cls: 'x-html-editor-tip'
28825         },
28826         backcolor : {
28827             title: 'Text Highlight Color',
28828             text: 'Change the background color of the selected text.',
28829             cls: 'x-html-editor-tip'
28830         },
28831         forecolor : {
28832             title: 'Font Color',
28833             text: 'Change the color of the selected text.',
28834             cls: 'x-html-editor-tip'
28835         },
28836         justifyleft : {
28837             title: 'Align Text Left',
28838             text: 'Align text to the left.',
28839             cls: 'x-html-editor-tip'
28840         },
28841         justifycenter : {
28842             title: 'Center Text',
28843             text: 'Center text in the editor.',
28844             cls: 'x-html-editor-tip'
28845         },
28846         justifyright : {
28847             title: 'Align Text Right',
28848             text: 'Align text to the right.',
28849             cls: 'x-html-editor-tip'
28850         },
28851         insertunorderedlist : {
28852             title: 'Bullet List',
28853             text: 'Start a bulleted list.',
28854             cls: 'x-html-editor-tip'
28855         },
28856         insertorderedlist : {
28857             title: 'Numbered List',
28858             text: 'Start a numbered list.',
28859             cls: 'x-html-editor-tip'
28860         },
28861         createlink : {
28862             title: 'Hyperlink',
28863             text: 'Make the selected text a hyperlink.',
28864             cls: 'x-html-editor-tip'
28865         },
28866         sourceedit : {
28867             title: 'Source Edit',
28868             text: 'Switch to source editing mode.',
28869             cls: 'x-html-editor-tip'
28870         }
28871     }
28872
28873     
28874     
28875     
28876     
28877     
28878     
28879     
28880     
28881     
28882     
28883     
28884     
28885     
28886     
28887     
28888     
28889     
28890     
28891     
28892     
28893     
28894     
28895     
28896     
28897     
28898     
28899     
28900     
28901     
28902     
28903     
28904     
28905     
28906 });
28907 Ext.reg('htmleditor', Ext.form.HtmlEditor);
28908
28909 Ext.form.TimeField = Ext.extend(Ext.form.ComboBox, {
28910     
28911     minValue : null,
28912     
28913     maxValue : null,
28914     
28915     minText : "The time in this field must be equal to or after {0}",
28916     
28917     maxText : "The time in this field must be equal to or before {0}",
28918     
28919     invalidText : "{0} is not a valid time",
28920     
28921     format : "g:i A",
28922     
28923     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",
28924     
28925     increment: 15,
28926
28927     
28928     mode: 'local',
28929     
28930     triggerAction: 'all',
28931     
28932     typeAhead: false,
28933
28934     
28935     initComponent : function(){
28936         Ext.form.TimeField.superclass.initComponent.call(this);
28937
28938         if(typeof this.minValue == "string"){
28939             this.minValue = this.parseDate(this.minValue);
28940         }
28941         if(typeof this.maxValue == "string"){
28942             this.maxValue = this.parseDate(this.maxValue);
28943         }
28944
28945         if(!this.store){
28946             var min = this.parseDate(this.minValue);
28947             if(!min){
28948                 min = new Date().clearTime();
28949             }
28950             var max = this.parseDate(this.maxValue);
28951             if(!max){
28952                 max = new Date().clearTime().add('mi', (24 * 60) - 1);
28953             }
28954             var times = [];
28955             while(min <= max){
28956                 times.push([min.dateFormat(this.format)]);
28957                 min = min.add('mi', this.increment);
28958             }
28959             this.store = new Ext.data.SimpleStore({
28960                 fields: ['text'],
28961                 data : times
28962             });
28963             this.displayField = 'text';
28964         }
28965     },
28966
28967     
28968     getValue : function(){
28969         var v = Ext.form.TimeField.superclass.getValue.call(this);
28970         return this.formatDate(this.parseDate(v)) || '';
28971     },
28972
28973     
28974     setValue : function(value){
28975         Ext.form.TimeField.superclass.setValue.call(this, this.formatDate(this.parseDate(value)));
28976     },
28977
28978     
28979     validateValue : Ext.form.DateField.prototype.validateValue,
28980     parseDate : Ext.form.DateField.prototype.parseDate,
28981     formatDate : Ext.form.DateField.prototype.formatDate,
28982
28983     
28984     beforeBlur : function(){
28985         var v = this.parseDate(this.getRawValue());
28986         if(v){
28987             this.setValue(v.dateFormat(this.format));
28988         }
28989     }
28990
28991     
28992     
28993     
28994     
28995 });
28996 Ext.reg('timefield', Ext.form.TimeField);
28997 Ext.form.Label = Ext.extend(Ext.BoxComponent, {
28998     onRender : function(ct, position){
28999         if(!this.el){
29000             this.el = document.createElement('label');
29001             this.el.innerHTML = this.text ? Ext.util.Format.htmlEncode(this.text) : (this.html || '');
29002             if(this.forId){
29003                 this.el.setAttribute('htmlFor', this.forId);
29004             }
29005         }
29006         Ext.form.Label.superclass.onRender.call(this, ct, position);
29007     }
29008 });
29009
29010 Ext.reg('label', Ext.form.Label);
29011
29012 Ext.form.Action = function(form, options){
29013     this.form = form;
29014     this.options = options || {};
29015 };
29016
29017
29018 Ext.form.Action.CLIENT_INVALID = 'client';
29019
29020 Ext.form.Action.SERVER_INVALID = 'server';
29021
29022 Ext.form.Action.CONNECT_FAILURE = 'connect';
29023
29024 Ext.form.Action.LOAD_FAILURE = 'load';
29025
29026 Ext.form.Action.prototype = {
29027
29028
29029
29030
29031
29032
29033
29034
29035
29036
29037     type : 'default',
29038
29039
29040         run : function(options){
29041
29042     },
29043
29044         success : function(response){
29045
29046     },
29047
29048         handleResponse : function(response){
29049
29050     },
29051
29052         failure : function(response){
29053         this.response = response;
29054         this.failureType = Ext.form.Action.CONNECT_FAILURE;
29055         this.form.afterAction(this, false);
29056     },
29057
29058         processResponse : function(response){
29059         this.response = response;
29060         if(!response.responseText){
29061             return true;
29062         }
29063         this.result = this.handleResponse(response);
29064         return this.result;
29065     },
29066
29067         getUrl : function(appendParams){
29068         var url = this.options.url || this.form.url || this.form.el.dom.action;
29069         if(appendParams){
29070             var p = this.getParams();
29071             if(p){
29072                 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
29073             }
29074         }
29075         return url;
29076     },
29077
29078         getMethod : function(){
29079         return (this.options.method || this.form.method || this.form.el.dom.method || 'POST').toUpperCase();
29080     },
29081
29082         getParams : function(){
29083         var bp = this.form.baseParams;
29084         var p = this.options.params;
29085         if(p){
29086             if(typeof p == "object"){
29087                 p = Ext.urlEncode(Ext.applyIf(p, bp));
29088             }else if(typeof p == 'string' && bp){
29089                 p += '&' + Ext.urlEncode(bp);
29090             }
29091         }else if(bp){
29092             p = Ext.urlEncode(bp);
29093         }
29094         return p;
29095     },
29096
29097         createCallback : function(opts){
29098                 var opts = opts || {};
29099         return {
29100             success: this.success,
29101             failure: this.failure,
29102             scope: this,
29103             timeout: (opts.timeout*1000) || (this.form.timeout*1000),
29104             upload: this.form.fileUpload ? this.success : undefined
29105         };
29106     }
29107 };
29108
29109
29110 Ext.form.Action.Submit = function(form, options){
29111     Ext.form.Action.Submit.superclass.constructor.call(this, form, options);
29112 };
29113
29114 Ext.extend(Ext.form.Action.Submit, Ext.form.Action, {
29115     
29116     type : 'submit',
29117
29118         run : function(){
29119         var o = this.options;
29120         var method = this.getMethod();
29121         var isPost = method == 'POST';
29122         if(o.clientValidation === false || this.form.isValid()){
29123             Ext.Ajax.request(Ext.apply(this.createCallback(o), {
29124                 form:this.form.el.dom,
29125                 url:this.getUrl(!isPost),
29126                 method: method,
29127                 params:isPost ? this.getParams() : null,
29128                 isUpload: this.form.fileUpload
29129             }));
29130
29131         }else if (o.clientValidation !== false){             this.failureType = Ext.form.Action.CLIENT_INVALID;
29132             this.form.afterAction(this, false);
29133         }
29134     },
29135
29136         success : function(response){
29137         var result = this.processResponse(response);
29138         if(result === true || result.success){
29139             this.form.afterAction(this, true);
29140             return;
29141         }
29142         if(result.errors){
29143             this.form.markInvalid(result.errors);
29144             this.failureType = Ext.form.Action.SERVER_INVALID;
29145         }
29146         this.form.afterAction(this, false);
29147     },
29148
29149         handleResponse : function(response){
29150         if(this.form.errorReader){
29151             var rs = this.form.errorReader.read(response);
29152             var errors = [];
29153             if(rs.records){
29154                 for(var i = 0, len = rs.records.length; i < len; i++) {
29155                     var r = rs.records[i];
29156                     errors[i] = r.data;
29157                 }
29158             }
29159             if(errors.length < 1){
29160                 errors = null;
29161             }
29162             return {
29163                 success : rs.success,
29164                 errors : errors
29165             };
29166         }
29167         return Ext.decode(response.responseText);
29168     }
29169 });
29170
29171
29172
29173 Ext.form.Action.Load = function(form, options){
29174     Ext.form.Action.Load.superclass.constructor.call(this, form, options);
29175     this.reader = this.form.reader;
29176 };
29177
29178 Ext.extend(Ext.form.Action.Load, Ext.form.Action, {
29179         type : 'load',
29180
29181         run : function(){
29182         Ext.Ajax.request(Ext.apply(
29183                 this.createCallback(this.options), {
29184                     method:this.getMethod(),
29185                     url:this.getUrl(false),
29186                     params:this.getParams()
29187         }));
29188     },
29189
29190         success : function(response){
29191         var result = this.processResponse(response);
29192         if(result === true || !result.success || !result.data){
29193             this.failureType = Ext.form.Action.LOAD_FAILURE;
29194             this.form.afterAction(this, false);
29195             return;
29196         }
29197         this.form.clearInvalid();
29198         this.form.setValues(result.data);
29199         this.form.afterAction(this, true);
29200     },
29201
29202         handleResponse : function(response){
29203         if(this.form.reader){
29204             var rs = this.form.reader.read(response);
29205             var data = rs.records && rs.records[0] ? rs.records[0].data : null;
29206             return {
29207                 success : rs.success,
29208                 data : data
29209             };
29210         }
29211         return Ext.decode(response.responseText);
29212     }
29213 });
29214
29215 Ext.form.Action.ACTION_TYPES = {
29216     'load' : Ext.form.Action.Load,
29217     'submit' : Ext.form.Action.Submit
29218 };
29219
29220
29221 Ext.form.VTypes = function(){
29222         var alpha = /^[a-zA-Z_]+$/;
29223     var alphanum = /^[a-zA-Z0-9_]+$/;
29224     var email = /^([\w]+)(.[\w]+)*@([\w-]+\.){1,5}([A-Za-z]){2,4}$/;
29225     var url = /(((https?)|(ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
29226
29227         return {
29228         
29229         'email' : function(v){
29230             return email.test(v);
29231         },
29232         
29233         'emailText' : 'This field should be an e-mail address in the format "user@domain.com"',
29234         
29235         'emailMask' : /[a-z0-9_\.\-@]/i,
29236
29237         
29238         'url' : function(v){
29239             return url.test(v);
29240         },
29241         
29242         'urlText' : 'This field should be a URL in the format "http:/'+'/www.domain.com"',
29243         
29244         
29245         'alpha' : function(v){
29246             return alpha.test(v);
29247         },
29248         
29249         'alphaText' : 'This field should only contain letters and _',
29250         
29251         'alphaMask' : /[a-z_]/i,
29252
29253         
29254         'alphanum' : function(v){
29255             return alphanum.test(v);
29256         },
29257         
29258         'alphanumText' : 'This field should only contain letters, numbers and _',
29259         
29260         'alphanumMask' : /[a-z0-9_]/i
29261     };
29262 }();
29263
29264 Ext.grid.GridPanel = Ext.extend(Ext.Panel, {
29265     
29266     
29267     
29268     
29269     
29270     
29271     
29272     
29273     
29274     
29275     
29276
29277     
29278     ddText : "{0} selected row{1}",
29279     
29280     minColumnWidth : 25,
29281     
29282     trackMouseOver : true,
29283     
29284     enableDragDrop : false,
29285     
29286     enableColumnMove : true,
29287     
29288     enableColumnHide : true,
29289     
29290     enableHdMenu : true,
29291     
29292     stripeRows : false,
29293     
29294     autoExpandColumn : false,
29295     
29296     autoExpandMin : 50,
29297     
29298     autoExpandMax : 1000,
29299     
29300     view : null,
29301     
29302     loadMask : false,
29303
29304     
29305     rendered : false,
29306     
29307     viewReady: false,
29308     
29309     stateEvents: ["columnmove", "columnresize", "sortchange"],
29310
29311     
29312     initComponent : function(){
29313         Ext.grid.GridPanel.superclass.initComponent.call(this);
29314
29315         
29316         
29317         this.autoScroll = false;
29318         this.autoWidth = false;
29319
29320         if(Ext.isArray(this.columns)){
29321             this.colModel = new Ext.grid.ColumnModel(this.columns);
29322             delete this.columns;
29323         }
29324
29325         
29326         if(this.ds){
29327             this.store = this.ds;
29328             delete this.ds;
29329         }
29330         if(this.cm){
29331             this.colModel = this.cm;
29332             delete this.cm;
29333         }
29334         if(this.sm){
29335             this.selModel = this.sm;
29336             delete this.sm;
29337         }
29338         this.store = Ext.StoreMgr.lookup(this.store);
29339
29340         this.addEvents(
29341             
29342             
29343             "click",
29344             
29345             "dblclick",
29346             
29347             "contextmenu",
29348             
29349             "mousedown",
29350             
29351             "mouseup",
29352             
29353             "mouseover",
29354             
29355             "mouseout",
29356             
29357             "keypress",
29358             
29359             "keydown",
29360
29361             
29362             
29363             "cellmousedown",
29364             
29365             "rowmousedown",
29366             
29367             "headermousedown",
29368
29369             
29370             "cellclick",
29371             
29372             "celldblclick",
29373             
29374             "rowclick",
29375             
29376             "rowdblclick",
29377             
29378             "headerclick",
29379             
29380             "headerdblclick",
29381             
29382             "rowcontextmenu",
29383             
29384             "cellcontextmenu",
29385             
29386             "headercontextmenu",
29387             
29388             "bodyscroll",
29389             
29390             "columnresize",
29391             
29392             "columnmove",
29393             
29394             "sortchange"
29395         );
29396     },
29397
29398     
29399     onRender : function(ct, position){
29400         Ext.grid.GridPanel.superclass.onRender.apply(this, arguments);
29401
29402         var c = this.body;
29403
29404         this.el.addClass('x-grid-panel');
29405
29406         var view = this.getView();
29407         view.init(this);
29408
29409         c.on("mousedown", this.onMouseDown, this);
29410         c.on("click", this.onClick, this);
29411         c.on("dblclick", this.onDblClick, this);
29412         c.on("contextmenu", this.onContextMenu, this);
29413         c.on("keydown", this.onKeyDown, this);
29414
29415         this.relayEvents(c, ["mousedown","mouseup","mouseover","mouseout","keypress"]);
29416
29417         this.getSelectionModel().init(this);
29418         this.view.render();
29419     },
29420
29421     
29422     initEvents : function(){
29423         Ext.grid.GridPanel.superclass.initEvents.call(this);
29424
29425         if(this.loadMask){
29426             this.loadMask = new Ext.LoadMask(this.bwrap,
29427                     Ext.apply({store:this.store}, this.loadMask));
29428         }
29429     },
29430
29431     initStateEvents : function(){
29432         Ext.grid.GridPanel.superclass.initStateEvents.call(this);
29433         this.colModel.on('hiddenchange', this.saveState, this, {delay: 100});
29434     },
29435
29436     applyState : function(state){
29437         var cm = this.colModel;
29438         var cs = state.columns;
29439         if(cs){
29440             for(var i = 0, len = cs.length; i < len; i++){
29441                 var s = cs[i];
29442                 var c = cm.getColumnById(s.id);
29443                 if(c){
29444                     c.hidden = s.hidden;
29445                     c.width = s.width;
29446                     var oldIndex = cm.getIndexById(s.id);
29447                     if(oldIndex != i){
29448                         cm.moveColumn(oldIndex, i);
29449                     }
29450                 }
29451             }
29452         }
29453         if(state.sort){
29454             this.store[this.store.remoteSort ? 'setDefaultSort' : 'sort'](state.sort.field, state.sort.direction);
29455         }
29456     },
29457
29458     getState : function(){
29459         var o = {columns: []};
29460         for(var i = 0, c; c = this.colModel.config[i]; i++){
29461             o.columns[i] = {
29462                 id: c.id,
29463                 width: c.width
29464             };
29465             if(c.hidden){
29466                 o.columns[i].hidden = true;
29467             }
29468         }
29469         var ss = this.store.getSortState();
29470         if(ss){
29471             o.sort = ss;
29472         }
29473         return o;
29474     },
29475
29476     
29477     afterRender : function(){
29478         Ext.grid.GridPanel.superclass.afterRender.call(this);
29479         this.view.layout();
29480         this.viewReady = true;
29481     },
29482
29483     
29484     reconfigure : function(store, colModel){
29485         if(this.loadMask){
29486             this.loadMask.destroy();
29487             this.loadMask = new Ext.LoadMask(this.bwrap,
29488                     Ext.apply({store:store}, this.initialConfig.loadMask));
29489         }
29490         this.view.bind(store, colModel);
29491         this.store = store;
29492         this.colModel = colModel;
29493         if(this.rendered){
29494             this.view.refresh(true);
29495         }
29496     },
29497
29498     
29499     onKeyDown : function(e){
29500         this.fireEvent("keydown", e);
29501     },
29502
29503     
29504     onDestroy : function(){
29505         if(this.rendered){
29506             if(this.loadMask){
29507                 this.loadMask.destroy();
29508             }
29509             var c = this.body;
29510             c.removeAllListeners();
29511             this.view.destroy();
29512             c.update("");
29513         }
29514         this.colModel.purgeListeners();
29515         Ext.grid.GridPanel.superclass.onDestroy.call(this);
29516     },
29517
29518     
29519     processEvent : function(name, e){
29520         this.fireEvent(name, e);
29521         var t = e.getTarget();
29522         var v = this.view;
29523         var header = v.findHeaderIndex(t);
29524         if(header !== false){
29525             this.fireEvent("header" + name, this, header, e);
29526         }else{
29527             var row = v.findRowIndex(t);
29528             var cell = v.findCellIndex(t);
29529             if(row !== false){
29530                 this.fireEvent("row" + name, this, row, e);
29531                 if(cell !== false){
29532                     this.fireEvent("cell" + name, this, row, cell, e);
29533                 }
29534             }
29535         }
29536     },
29537
29538     
29539     onClick : function(e){
29540         this.processEvent("click", e);
29541     },
29542
29543     
29544     onMouseDown : function(e){
29545         this.processEvent("mousedown", e);
29546     },
29547
29548     
29549     onContextMenu : function(e, t){
29550         this.processEvent("contextmenu", e);
29551     },
29552
29553     
29554     onDblClick : function(e){
29555         this.processEvent("dblclick", e);
29556     },
29557
29558     
29559     walkCells : function(row, col, step, fn, scope){
29560         var cm = this.colModel, clen = cm.getColumnCount();
29561         var ds = this.store, rlen = ds.getCount(), first = true;
29562         if(step < 0){
29563             if(col < 0){
29564                 row--;
29565                 first = false;
29566             }
29567             while(row >= 0){
29568                 if(!first){
29569                     col = clen-1;
29570                 }
29571                 first = false;
29572                 while(col >= 0){
29573                     if(fn.call(scope || this, row, col, cm) === true){
29574                         return [row, col];
29575                     }
29576                     col--;
29577                 }
29578                 row--;
29579             }
29580         } else {
29581             if(col >= clen){
29582                 row++;
29583                 first = false;
29584             }
29585             while(row < rlen){
29586                 if(!first){
29587                     col = 0;
29588                 }
29589                 first = false;
29590                 while(col < clen){
29591                     if(fn.call(scope || this, row, col, cm) === true){
29592                         return [row, col];
29593                     }
29594                     col++;
29595                 }
29596                 row++;
29597             }
29598         }
29599         return null;
29600     },
29601
29602     
29603     getSelections : function(){
29604         return this.selModel.getSelections();
29605     },
29606
29607     
29608     onResize : function(){
29609         Ext.grid.GridPanel.superclass.onResize.apply(this, arguments);
29610         if(this.viewReady){
29611             this.view.layout();
29612         }
29613     },
29614
29615     
29616     getGridEl : function(){
29617         return this.body;
29618     },
29619
29620     
29621     stopEditing : function(){},
29622
29623     
29624     getSelectionModel : function(){
29625         if(!this.selModel){
29626             this.selModel = new Ext.grid.RowSelectionModel(
29627                     this.disableSelection ? {selectRow: Ext.emptyFn} : null);
29628         }
29629         return this.selModel;
29630     },
29631
29632     
29633     getStore : function(){
29634         return this.store;
29635     },
29636
29637     
29638     getColumnModel : function(){
29639         return this.colModel;
29640     },
29641
29642     
29643     getView : function(){
29644         if(!this.view){
29645             this.view = new Ext.grid.GridView(this.viewConfig);
29646         }
29647         return this.view;
29648     },
29649     
29650     getDragDropText : function(){
29651         var count = this.selModel.getCount();
29652         return String.format(this.ddText, count, count == 1 ? '' : 's');
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     
29697     
29698     
29699     
29700     
29701     
29702     
29703     
29704 });
29705 Ext.reg('grid', Ext.grid.GridPanel);
29706
29707 Ext.grid.GridView = function(config){
29708     Ext.apply(this, config);
29709         this.addEvents(
29710       
29711       "beforerowremoved",
29712       
29713       "beforerowsinserted",
29714       
29715       "beforerefresh",
29716       
29717       "rowremoved",
29718       
29719       "rowsinserted",
29720       
29721       "rowupdated",
29722       
29723       "refresh"
29724   );
29725     Ext.grid.GridView.superclass.constructor.call(this);
29726 };
29727
29728 Ext.extend(Ext.grid.GridView, Ext.util.Observable, {
29729     
29730     
29731     
29732     
29733     scrollOffset: 19,
29734     
29735     autoFill: false,
29736     
29737     forceFit: false,
29738     
29739     sortClasses : ["sort-asc", "sort-desc"],
29740     
29741     sortAscText : "Sort Ascending",
29742     
29743     sortDescText : "Sort Descending",
29744     
29745     columnsText : "Columns",
29746
29747         borderWidth: 2,
29748
29749     
29750
29751         initTemplates : function(){
29752         var ts = this.templates || {};
29753         if(!ts.master){
29754             ts.master = new Ext.Template(
29755                     '<div class="x-grid3" hidefocus="true">',
29756                         '<div class="x-grid3-viewport">',
29757                             '<div class="x-grid3-header"><div class="x-grid3-header-inner"><div class="x-grid3-header-offset">{header}</div></div><div class="x-clear"></div></div>',
29758                             '<div class="x-grid3-scroller"><div class="x-grid3-body">{body}</div><a href="#" class="x-grid3-focus" tabIndex="-1"></a></div>',
29759                         "</div>",
29760                         '<div class="x-grid3-resize-marker">&#160;</div>',
29761                         '<div class="x-grid3-resize-proxy">&#160;</div>',
29762                     "</div>"
29763                     );
29764         }
29765
29766         if(!ts.header){
29767             ts.header = new Ext.Template(
29768                     '<table border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',
29769                     '<thead><tr class="x-grid3-hd-row">{cells}</tr></thead>',
29770                     "</table>"
29771                     );
29772         }
29773
29774         if(!ts.hcell){
29775             ts.hcell = new Ext.Template(
29776                     '<td class="x-grid3-hd x-grid3-cell x-grid3-td-{id}" 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>' : '',
29777                     '{value}<img class="x-grid3-sort-icon" src="', Ext.BLANK_IMAGE_URL, '" />',
29778                     "</div></td>"
29779                     );
29780         }
29781
29782         if(!ts.body){
29783             ts.body = new Ext.Template('{rows}');
29784         }
29785
29786         if(!ts.row){
29787             ts.row = new Ext.Template(
29788                     '<div class="x-grid3-row {alt}" style="{tstyle}"><table class="x-grid3-row-table" border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',
29789                     '<tbody><tr>{cells}</tr>',
29790                     (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>' : ''),
29791                     '</tbody></table></div>'
29792                     );
29793         }
29794
29795         if(!ts.cell){
29796             ts.cell = new Ext.Template(
29797                     '<td class="x-grid3-col x-grid3-cell x-grid3-td-{id} {css}" style="{style}" tabIndex="0" {cellAttr}>',
29798                     '<div class="x-grid3-cell-inner x-grid3-col-{id}" unselectable="on" {attr}>{value}</div>',
29799                     "</td>"
29800                     );
29801         }
29802
29803         for(var k in ts){
29804             var t = ts[k];
29805             if(t && typeof t.compile == 'function' && !t.compiled){
29806                 t.disableFormats = true;
29807                 t.compile();
29808             }
29809         }
29810
29811         this.templates = ts;
29812
29813         this.tdClass = 'x-grid3-cell';
29814         this.cellSelector = 'td.x-grid3-cell';
29815         this.hdCls = 'x-grid3-hd';
29816         this.rowSelector = 'div.x-grid3-row';
29817         this.colRe = new RegExp("x-grid3-td-([^\\s]+)", "");
29818     },
29819
29820         fly : function(el){
29821         if(!this._flyweight){
29822             this._flyweight = new Ext.Element.Flyweight(document.body);
29823         }
29824         this._flyweight.dom = el;
29825         return this._flyweight;
29826     },
29827
29828         getEditorParent : function(ed){
29829         return this.scroller.dom;
29830     },
29831
29832         initElements : function(){
29833         var E = Ext.Element;
29834
29835         var el = this.grid.getGridEl().dom.firstChild;
29836         var cs = el.childNodes;
29837
29838         this.el = new E(el);
29839
29840         this.mainWrap = new E(cs[0]);
29841         this.mainHd = new E(this.mainWrap.dom.firstChild);
29842
29843         if(this.grid.hideHeaders){
29844             this.mainHd.setDisplayed(false);
29845         }
29846
29847         this.innerHd = this.mainHd.dom.firstChild;
29848         this.scroller = new E(this.mainWrap.dom.childNodes[1]);
29849         if(this.forceFit){
29850             this.scroller.setStyle('overflow-x', 'hidden');
29851         }
29852         this.mainBody = new E(this.scroller.dom.firstChild);
29853
29854         this.focusEl = new E(this.scroller.dom.childNodes[1]);
29855         this.focusEl.swallowEvent("click", true);
29856
29857         this.resizeMarker = new E(cs[1]);
29858         this.resizeProxy = new E(cs[2]);
29859     },
29860
29861         getRows : function(){
29862         return this.hasRows() ? this.mainBody.dom.childNodes : [];
29863     },
29864
29865     
29866         findCell : function(el){
29867         if(!el){
29868             return false;
29869         }
29870         return this.fly(el).findParent(this.cellSelector, 3);
29871     },
29872
29873         findCellIndex : function(el, requiredCls){
29874         var cell = this.findCell(el);
29875         if(cell && (!requiredCls || this.fly(cell).hasClass(requiredCls))){
29876             return this.getCellIndex(cell);
29877         }
29878         return false;
29879     },
29880
29881         getCellIndex : function(el){
29882         if(el){
29883             var m = el.className.match(this.colRe);
29884             if(m && m[1]){
29885                 return this.cm.getIndexById(m[1]);
29886             }
29887         }
29888         return false;
29889     },
29890
29891         findHeaderCell : function(el){
29892         var cell = this.findCell(el);
29893         return cell && this.fly(cell).hasClass(this.hdCls) ? cell : null;
29894     },
29895
29896         findHeaderIndex : function(el){
29897         return this.findCellIndex(el, this.hdCls);
29898     },
29899
29900         findRow : function(el){
29901         if(!el){
29902             return false;
29903         }
29904         return this.fly(el).findParent(this.rowSelector, 10);
29905     },
29906
29907         findRowIndex : function(el){
29908         var r = this.findRow(el);
29909         return r ? r.rowIndex : false;
29910     },
29911
29912     
29913
29914     getRow : function(row){
29915         return this.getRows()[row];
29916     },
29917
29918
29919     getCell : function(row, col){
29920         return this.getRow(row).getElementsByTagName('td')[col];
29921     },
29922
29923
29924     getHeaderCell : function(index){
29925       return this.mainHd.dom.getElementsByTagName('td')[index];
29926     },
29927
29928     
29929         addRowClass : function(row, cls){
29930         var r = this.getRow(row);
29931         if(r){
29932             this.fly(r).addClass(cls);
29933         }
29934     },
29935
29936         removeRowClass : function(row, cls){
29937         var r = this.getRow(row);
29938         if(r){
29939             this.fly(r).removeClass(cls);
29940         }
29941     },
29942
29943         removeRow : function(row){
29944         Ext.removeNode(this.getRow(row));
29945     },
29946
29947         removeRows : function(firstRow, lastRow){
29948         var bd = this.mainBody.dom;
29949         for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){
29950             Ext.removeNode(bd.childNodes[firstRow]);
29951         }
29952     },
29953
29954     
29955         getScrollState : function(){
29956         var sb = this.scroller.dom;
29957         return {left: sb.scrollLeft, top: sb.scrollTop};
29958     },
29959
29960         restoreScroll : function(state){
29961         var sb = this.scroller.dom;
29962         sb.scrollLeft = state.left;
29963         sb.scrollTop = state.top;
29964     },
29965
29966     
29967     scrollToTop : function(){
29968         this.scroller.dom.scrollTop = 0;
29969         this.scroller.dom.scrollLeft = 0;
29970     },
29971
29972         syncScroll : function(){
29973       this.syncHeaderScroll();
29974       var mb = this.scroller.dom;
29975         this.grid.fireEvent("bodyscroll", mb.scrollLeft, mb.scrollTop);
29976     },
29977
29978         syncHeaderScroll : function(){
29979         var mb = this.scroller.dom;
29980         this.innerHd.scrollLeft = mb.scrollLeft;
29981         this.innerHd.scrollLeft = mb.scrollLeft;     },
29982
29983         updateSortIcon : function(col, dir){
29984         var sc = this.sortClasses;
29985         var hds = this.mainHd.select('td').removeClass(sc);
29986         hds.item(col).addClass(sc[dir == "DESC" ? 1 : 0]);
29987     },
29988
29989         updateAllColumnWidths : function(){
29990         var tw = this.getTotalWidth();
29991         var clen = this.cm.getColumnCount();
29992         var ws = [];
29993         for(var i = 0; i < clen; i++){
29994             ws[i] = this.getColumnWidth(i);
29995         }
29996
29997         this.innerHd.firstChild.firstChild.style.width = tw;
29998
29999         for(var i = 0; i < clen; i++){
30000             var hd = this.getHeaderCell(i);
30001             hd.style.width = ws[i];
30002         }
30003
30004         var ns = this.getRows();
30005         for(var i = 0, len = ns.length; i < len; i++){
30006             ns[i].style.width = tw;
30007             ns[i].firstChild.style.width = tw;
30008             var row = ns[i].firstChild.rows[0];
30009             for(var j = 0; j < clen; j++){
30010                 row.childNodes[j].style.width = ws[j];
30011             }
30012         }
30013
30014         this.onAllColumnWidthsUpdated(ws, tw);
30015     },
30016
30017         updateColumnWidth : function(col, width){
30018         var w = this.getColumnWidth(col);
30019         var tw = this.getTotalWidth();
30020
30021         this.innerHd.firstChild.firstChild.style.width = tw;
30022         var hd = this.getHeaderCell(col);
30023         hd.style.width = w;
30024
30025         var ns = this.getRows();
30026         for(var i = 0, len = ns.length; i < len; i++){
30027             ns[i].style.width = tw;
30028             ns[i].firstChild.style.width = tw;
30029             ns[i].firstChild.rows[0].childNodes[col].style.width = w;
30030         }
30031
30032         this.onColumnWidthUpdated(col, w, tw);
30033     },
30034
30035         updateColumnHidden : function(col, hidden){
30036         var tw = this.getTotalWidth();
30037
30038         this.innerHd.firstChild.firstChild.style.width = tw;
30039
30040         var display = hidden ? 'none' : '';
30041
30042         var hd = this.getHeaderCell(col);
30043         hd.style.display = display;
30044
30045         var ns = this.getRows();
30046         for(var i = 0, len = ns.length; i < len; i++){
30047             ns[i].style.width = tw;
30048             ns[i].firstChild.style.width = tw;
30049             ns[i].firstChild.rows[0].childNodes[col].style.display = display;
30050         }
30051
30052         this.onColumnHiddenUpdated(col, hidden, tw);
30053
30054         delete this.lastViewWidth;         this.layout();
30055     },
30056
30057         doRender : function(cs, rs, ds, startRow, colCount, stripe){
30058         var ts = this.templates, ct = ts.cell, rt = ts.row, last = colCount-1;
30059         var tstyle = 'width:'+this.getTotalWidth()+';';
30060                 var buf = [], cb, c, p = {}, rp = {tstyle: tstyle}, r;
30061         for(var j = 0, len = rs.length; j < len; j++){
30062             r = rs[j]; cb = [];
30063             var rowIndex = (j+startRow);
30064             for(var i = 0; i < colCount; i++){
30065                 c = cs[i];
30066                 p.id = c.id;
30067                 p.css = i == 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');
30068                 p.attr = p.cellAttr = "";
30069                 p.value = c.renderer(r.data[c.name], p, r, rowIndex, i, ds);
30070                 p.style = c.style;
30071                 if(p.value == undefined || p.value === "") p.value = "&#160;";
30072                 if(r.dirty && typeof r.modified[c.name] !== 'undefined'){
30073                     p.css += ' x-grid3-dirty-cell';
30074                 }
30075                 cb[cb.length] = ct.apply(p);
30076             }
30077             var alt = [];
30078             if(stripe && ((rowIndex+1) % 2 == 0)){
30079                 alt[0] = "x-grid3-row-alt";
30080             }
30081             if(r.dirty){
30082                 alt[1] = " x-grid3-dirty-row";
30083             }
30084             rp.cols = colCount;
30085             if(this.getRowClass){
30086                 alt[2] = this.getRowClass(r, rowIndex, rp, ds);
30087             }
30088             rp.alt = alt.join(" ");
30089             rp.cells = cb.join("");
30090             buf[buf.length] =  rt.apply(rp);
30091         }
30092         return buf.join("");
30093     },
30094
30095         processRows : function(startRow, skipStripe){
30096         if(this.ds.getCount() < 1){
30097             return;
30098         }
30099         skipStripe = skipStripe || !this.grid.stripeRows;
30100         startRow = startRow || 0;
30101         var rows = this.getRows();
30102         var cls = ' x-grid3-row-alt ';
30103         for(var i = startRow, len = rows.length; i < len; i++){
30104             var row = rows[i];
30105             row.rowIndex = i;
30106             if(!skipStripe){
30107                 var isAlt = ((i+1) % 2 == 0);
30108                 var hasAlt = (' '+row.className + ' ').indexOf(cls) != -1;
30109                 if(isAlt == hasAlt){
30110                     continue;
30111                 }
30112                 if(isAlt){
30113                     row.className += " x-grid3-row-alt";
30114                 }else{
30115                     row.className = row.className.replace("x-grid3-row-alt", "");
30116                 }
30117             }
30118         }
30119     },
30120
30121         renderUI : function(){
30122
30123         var header = this.renderHeaders();
30124         var body = this.templates.body.apply({rows:''});
30125
30126
30127         var html = this.templates.master.apply({
30128             body: body,
30129             header: header
30130         });
30131
30132         var g = this.grid;
30133
30134         g.getGridEl().dom.innerHTML = html;
30135
30136         this.initElements();
30137
30138
30139         this.mainBody.dom.innerHTML = this.renderRows();
30140         this.processRows(0, true);
30141
30142
30143                 Ext.fly(this.innerHd).on("click", this.handleHdDown, this);
30144         this.mainHd.on("mouseover", this.handleHdOver, this);
30145         this.mainHd.on("mouseout", this.handleHdOut, this);
30146         this.mainHd.on("mousemove", this.handleHdMove, this);
30147
30148         this.scroller.on('scroll', this.syncScroll,  this);
30149         if(g.enableColumnResize !== false){
30150             this.splitone = new Ext.grid.GridView.SplitDragZone(g, this.mainHd.dom);
30151         }
30152
30153         if(g.enableColumnMove){
30154             this.columnDrag = new Ext.grid.GridView.ColumnDragZone(g, this.innerHd);
30155             this.columnDrop = new Ext.grid.HeaderDropZone(g, this.mainHd.dom);
30156         }
30157
30158         if(g.enableHdMenu !== false){
30159             if(g.enableColumnHide !== false){
30160                 this.colMenu = new Ext.menu.Menu({id:g.id + "-hcols-menu"});
30161                 this.colMenu.on("beforeshow", this.beforeColMenuShow, this);
30162                 this.colMenu.on("itemclick", this.handleHdMenuClick, this);
30163             }
30164             this.hmenu = new Ext.menu.Menu({id: g.id + "-hctx"});
30165             this.hmenu.add(
30166                 {id:"asc", text: this.sortAscText, cls: "xg-hmenu-sort-asc"},
30167                 {id:"desc", text: this.sortDescText, cls: "xg-hmenu-sort-desc"}
30168             );
30169             if(g.enableColumnHide !== false){
30170                 this.hmenu.add('-',
30171                     {id:"columns", text: this.columnsText, menu: this.colMenu, iconCls: 'x-cols-icon'}
30172                 );
30173             }
30174             this.hmenu.on("itemclick", this.handleHdMenuClick, this);
30175
30176                     }
30177
30178         if(g.enableDragDrop || g.enableDrag){
30179             var dd = new Ext.grid.GridDragZone(g, {
30180                 ddGroup : g.ddGroup || 'GridDD'
30181             });
30182         }
30183
30184         this.updateHeaderSortState();
30185
30186     },
30187
30188         layout : function(){
30189         if(!this.mainBody){
30190             return;         }
30191         var g = this.grid;
30192         var c = g.getGridEl(), cm = this.cm,
30193                 expandCol = g.autoExpandColumn,
30194                 gv = this;
30195
30196         var csize = c.getSize(true);
30197         var vw = csize.width;
30198
30199         if(vw < 20 || csize.height < 20){             return;
30200         }
30201
30202         if(g.autoHeight){
30203             this.scroller.dom.style.overflow = 'visible';
30204         }else{
30205             this.el.setSize(csize.width, csize.height);
30206
30207             var hdHeight = this.mainHd.getHeight();
30208             var vh = csize.height - (hdHeight);
30209
30210             this.scroller.setSize(vw, vh);
30211             if(this.innerHd){
30212                 this.innerHd.style.width = (vw)+'px';
30213             }
30214         }
30215         if(this.forceFit){
30216             if(this.lastViewWidth != vw){
30217                 this.fitColumns(false, false);
30218                 this.lastViewWidth = vw;
30219             }
30220         }else {
30221             this.autoExpand();
30222             this.syncHeaderScroll();
30223         }
30224         this.onLayout(vw, vh);
30225     },
30226
30227             onLayout : function(vw, vh){
30228             },
30229
30230     onColumnWidthUpdated : function(col, w, tw){
30231             },
30232
30233     onAllColumnWidthsUpdated : function(ws, tw){
30234             },
30235
30236     onColumnHiddenUpdated : function(col, hidden, tw){
30237             },
30238
30239     updateColumnText : function(col, text){
30240             },
30241
30242     afterMove : function(colIndex){
30243             },
30244
30245     
30246         init: function(grid){
30247         this.grid = grid;
30248
30249         this.initTemplates();
30250         this.initData(grid.store, grid.colModel);
30251         this.initUI(grid);
30252     },
30253
30254         getColumnId : function(index){
30255       return this.cm.getColumnId(index);
30256     },
30257
30258         renderHeaders : function(){
30259         var cm = this.cm, ts = this.templates;
30260         var ct = ts.hcell;
30261
30262         var cb = [], sb = [], p = {};
30263
30264         for(var i = 0, len = cm.getColumnCount(); i < len; i++){
30265             p.id = cm.getColumnId(i);
30266             p.value = cm.getColumnHeader(i) || "";
30267             p.style = this.getColumnStyle(i, true);
30268             p.tooltip = this.getColumnTooltip(i);
30269             if(cm.config[i].align == 'right'){
30270                 p.istyle = 'padding-right:16px';
30271             } else {
30272                 delete p.istyle;
30273             }
30274             cb[cb.length] = ct.apply(p);
30275         }
30276         return ts.header.apply({cells: cb.join(""), tstyle:'width:'+this.getTotalWidth()+';'});
30277     },
30278
30279         getColumnTooltip : function(i){
30280         var tt = this.cm.getColumnTooltip(i);
30281         if(tt){
30282             if(Ext.QuickTips.isEnabled()){
30283                 return 'ext:qtip="'+tt+'"';
30284             }else{
30285                 return 'title="'+tt+'"';
30286             }
30287         }
30288         return "";
30289     },
30290
30291         beforeUpdate : function(){
30292         this.grid.stopEditing(true);
30293     },
30294
30295         updateHeaders : function(){
30296         this.innerHd.firstChild.innerHTML = this.renderHeaders();
30297     },
30298
30299     
30300     focusRow : function(row){
30301         this.focusCell(row, 0, false);
30302     },
30303
30304     
30305     focusCell : function(row, col, hscroll){
30306         var xy = this.ensureVisible(row, col, hscroll);
30307         this.focusEl.setXY(xy);
30308         if(Ext.isGecko){
30309             this.focusEl.focus();
30310         }else{
30311             this.focusEl.focus.defer(1, this.focusEl);
30312         }
30313     },
30314
30315         ensureVisible : function(row, col, hscroll){
30316         if(typeof row != "number"){
30317             row = row.rowIndex;
30318         }
30319         if(!this.ds){
30320             return;
30321         }
30322         if(row < 0 || row >= this.ds.getCount()){
30323             return;
30324         }
30325         col = (col !== undefined ? col : 0);
30326
30327         var rowEl = this.getRow(row), cellEl;
30328         if(!(hscroll === false && col === 0)){
30329             while(this.cm.isHidden(col)){
30330                 col++;
30331             }
30332             cellEl = this.getCell(row, col);
30333         }
30334         if(!rowEl){
30335             return;
30336         }
30337
30338         var c = this.scroller.dom;
30339
30340         var ctop = 0;
30341         var p = rowEl, stop = this.el.dom;
30342         while(p && p != stop){
30343             ctop += p.offsetTop;
30344             p = p.offsetParent;
30345         }
30346         ctop -= this.mainHd.dom.offsetHeight;
30347
30348         var cbot = ctop + rowEl.offsetHeight;
30349
30350         var ch = c.clientHeight;
30351         var stop = parseInt(c.scrollTop, 10);
30352         var sbot = stop + ch;
30353
30354         if(ctop < stop){
30355           c.scrollTop = ctop;
30356         }else if(cbot > sbot){
30357             c.scrollTop = cbot-ch;
30358         }
30359
30360         if(hscroll !== false){
30361             var cleft = parseInt(cellEl.offsetLeft, 10);
30362             var cright = cleft + cellEl.offsetWidth;
30363
30364             var sleft = parseInt(c.scrollLeft, 10);
30365             var sright = sleft + c.clientWidth;
30366             if(cleft < sleft){
30367                 c.scrollLeft = cleft;
30368             }else if(cright > sright){
30369                 c.scrollLeft = cright-c.clientWidth;
30370             }
30371         }
30372         return cellEl ? Ext.fly(cellEl).getXY() : [c.scrollLeft, Ext.fly(rowEl).getY()];
30373     },
30374
30375         insertRows : function(dm, firstRow, lastRow, isUpdate){
30376         if(!isUpdate && firstRow === 0 && lastRow == dm.getCount()-1){
30377             this.refresh();
30378         }else{
30379             if(!isUpdate){
30380                 this.fireEvent("beforerowsinserted", this, firstRow, lastRow);
30381             }
30382             var html = this.renderRows(firstRow, lastRow);
30383             var before = this.getRow(firstRow);
30384             if(before){
30385                 Ext.DomHelper.insertHtml('beforeBegin', before, html);
30386             }else{
30387                 Ext.DomHelper.insertHtml('beforeEnd', this.mainBody.dom, html);
30388             }
30389             if(!isUpdate){
30390                 this.fireEvent("rowsinserted", this, firstRow, lastRow);
30391                 this.processRows(firstRow);
30392             }
30393         }
30394     },
30395
30396         deleteRows : function(dm, firstRow, lastRow){
30397         if(dm.getRowCount()<1){
30398             this.refresh();
30399         }else{
30400             this.fireEvent("beforerowsdeleted", this, firstRow, lastRow);
30401
30402             this.removeRows(firstRow, lastRow);
30403
30404             this.processRows(firstRow);
30405             this.fireEvent("rowsdeleted", this, firstRow, lastRow);
30406         }
30407     },
30408
30409         getColumnStyle : function(col, isHeader){
30410         var style = !isHeader ? (this.cm.config[col].css || '') : '';
30411         style += 'width:'+this.getColumnWidth(col)+';';
30412         if(this.cm.isHidden(col)){
30413             style += 'display:none;';
30414         }
30415         var align = this.cm.config[col].align;
30416         if(align){
30417             style += 'text-align:'+align+';';
30418         }
30419         return style;
30420     },
30421
30422         getColumnWidth : function(col){
30423         var w = this.cm.getColumnWidth(col);
30424         if(typeof w == 'number'){
30425             return (Ext.isBorderBox ? w : (w-this.borderWidth > 0 ? w-this.borderWidth:0)) + 'px';
30426         }
30427         return w;
30428     },
30429
30430         getTotalWidth : function(){
30431         return this.cm.getTotalWidth()+'px';
30432     },
30433
30434         fitColumns : function(preventRefresh, onlyExpand, omitColumn){
30435         var cm = this.cm, leftOver, dist, i;
30436         var tw = cm.getTotalWidth(false);
30437         var aw = this.grid.getGridEl().getWidth(true)-this.scrollOffset;
30438
30439         if(aw < 20){             return;
30440         }
30441         var extra = aw - tw;
30442
30443         if(extra === 0){
30444             return false;
30445         }
30446
30447         var vc = cm.getColumnCount(true);
30448         var ac = vc-(typeof omitColumn == 'number' ? 1 : 0);
30449         if(ac === 0){
30450             ac = 1;
30451             omitColumn = undefined;
30452         }
30453         var colCount = cm.getColumnCount();
30454         var cols = [];
30455         var extraCol = 0;
30456         var width = 0;
30457         var w;
30458         for (i = 0; i < colCount; i++){
30459             if(!cm.isHidden(i) && !cm.isFixed(i) && i !== omitColumn){
30460                 w = cm.getColumnWidth(i);
30461                 cols.push(i);
30462                 extraCol = i;
30463                 cols.push(w);
30464                 width += w;
30465             }
30466         }
30467         var frac = (aw - cm.getTotalWidth())/width;
30468         while (cols.length){
30469             w = cols.pop();
30470             i = cols.pop();
30471             cm.setColumnWidth(i, Math.max(this.grid.minColumnWidth, Math.floor(w + w*frac)), true);
30472         }
30473
30474         if((tw = cm.getTotalWidth(false)) > aw){
30475             var adjustCol = ac != vc ? omitColumn : extraCol;
30476              cm.setColumnWidth(adjustCol, Math.max(1,
30477                      cm.getColumnWidth(adjustCol)- (tw-aw)), true);
30478         }
30479
30480         if(preventRefresh !== true){
30481             this.updateAllColumnWidths();
30482         }
30483
30484
30485         return true;
30486     },
30487
30488         autoExpand : function(preventUpdate){
30489         var g = this.grid, cm = this.cm;
30490         if(!this.userResized && g.autoExpandColumn){
30491             var tw = cm.getTotalWidth(false);
30492             var aw = this.grid.getGridEl().getWidth(true)-this.scrollOffset;
30493             if(tw != aw){
30494                 var ci = cm.getIndexById(g.autoExpandColumn);
30495                 var currentWidth = cm.getColumnWidth(ci);
30496                 var cw = Math.min(Math.max(((aw-tw)+currentWidth), g.autoExpandMin), g.autoExpandMax);
30497                 if(cw != currentWidth){
30498                     cm.setColumnWidth(ci, cw, true);
30499                     if(preventUpdate !== true){
30500                         this.updateColumnWidth(ci, cw);
30501                     }
30502                 }
30503             }
30504         }
30505     },
30506
30507         getColumnData : function(){
30508                 var cs = [], cm = this.cm, colCount = cm.getColumnCount();
30509         for(var i = 0; i < colCount; i++){
30510             var name = cm.getDataIndex(i);
30511             cs[i] = {
30512                 name : (typeof name == 'undefined' ? this.ds.fields.get(i).name : name),
30513                 renderer : cm.getRenderer(i),
30514                 id : cm.getColumnId(i),
30515                 style : this.getColumnStyle(i)
30516             };
30517         }
30518         return cs;
30519     },
30520
30521         renderRows : function(startRow, endRow){
30522                 var g = this.grid, cm = g.colModel, ds = g.store, stripe = g.stripeRows;
30523         var colCount = cm.getColumnCount();
30524
30525         if(ds.getCount() < 1){
30526             return "";
30527         }
30528
30529         var cs = this.getColumnData();
30530
30531         startRow = startRow || 0;
30532         endRow = typeof endRow == "undefined"? ds.getCount()-1 : endRow;
30533
30534                 var rs = ds.getRange(startRow, endRow);
30535
30536         return this.doRender(cs, rs, ds, startRow, colCount, stripe);
30537     },
30538
30539         renderBody : function(){
30540         var markup = this.renderRows();
30541         return this.templates.body.apply({rows: markup});
30542     },
30543
30544         refreshRow : function(record){
30545         var ds = this.ds, index;
30546         if(typeof record == 'number'){
30547             index = record;
30548             record = ds.getAt(index);
30549         }else{
30550             index = ds.indexOf(record);
30551         }
30552         var cls = [];
30553         this.insertRows(ds, index, index, true);
30554         this.getRow(index).rowIndex = index;
30555         this.onRemove(ds, record, index+1, true);
30556         this.fireEvent("rowupdated", this, index, record);
30557     },
30558
30559     
30560     refresh : function(headersToo){
30561         this.fireEvent("beforerefresh", this);
30562         this.grid.stopEditing(true);
30563
30564         var result = this.renderBody();
30565         this.mainBody.update(result);
30566
30567         if(headersToo === true){
30568             this.updateHeaders();
30569             this.updateHeaderSortState();
30570         }
30571         this.processRows(0, true);
30572         this.layout();
30573         this.applyEmptyText();
30574         this.fireEvent("refresh", this);
30575     },
30576
30577         applyEmptyText : function(){
30578         if(this.emptyText && !this.hasRows()){
30579             this.mainBody.update('<div class="x-grid-empty">' + this.emptyText + '</div>');
30580         }
30581     },
30582
30583         updateHeaderSortState : function(){
30584         var state = this.ds.getSortState();
30585         if(!state){
30586             return;
30587         }
30588         if(!this.sortState || (this.sortState.field != state.field || this.sortState.direction != state.direction)){
30589             this.grid.fireEvent('sortchange', this.grid, state);
30590         }
30591         this.sortState = state;
30592         var sortColumn = this.cm.findColumnIndex(state.field);
30593         if(sortColumn != -1){
30594             var sortDir = state.direction;
30595             this.updateSortIcon(sortColumn, sortDir);
30596         }
30597     },
30598
30599         destroy : function(){
30600         if(this.colMenu){
30601             this.colMenu.removeAll();
30602             Ext.menu.MenuMgr.unregister(this.colMenu);
30603             this.colMenu.getEl().remove();
30604             delete this.colMenu;
30605         }
30606         if(this.hmenu){
30607             this.hmenu.removeAll();
30608             Ext.menu.MenuMgr.unregister(this.hmenu);
30609             this.hmenu.getEl().remove();
30610             delete this.hmenu;
30611         }
30612         if(this.grid.enableColumnMove){
30613             var dds = Ext.dd.DDM.ids['gridHeader' + this.grid.getGridEl().id];
30614             if(dds){
30615                 for(var dd in dds){
30616                     if(!dds[dd].config.isTarget && dds[dd].dragElId){
30617                         var elid = dds[dd].dragElId;
30618                         dds[dd].unreg();
30619                         Ext.get(elid).remove();
30620                     } else if(dds[dd].config.isTarget){
30621                         dds[dd].proxyTop.remove();
30622                         dds[dd].proxyBottom.remove();
30623                         dds[dd].unreg();
30624                     }
30625                     if(Ext.dd.DDM.locationCache[dd]){
30626                         delete Ext.dd.DDM.locationCache[dd];
30627                     }
30628                 }
30629                 delete Ext.dd.DDM.ids['gridHeader' + this.grid.getGridEl().id];
30630             }
30631         }
30632
30633         Ext.destroy(this.resizeMarker, this.resizeProxy);
30634
30635         this.initData(null, null);
30636         Ext.EventManager.removeResizeListener(this.onWindowResize, this);
30637     },
30638
30639         onDenyColumnHide : function(){
30640
30641     },
30642
30643         render : function(){
30644
30645         var cm = this.cm;
30646         var colCount = cm.getColumnCount();
30647
30648         if(this.autoFill){
30649             this.fitColumns(true, true);
30650         }else if(this.forceFit){
30651             this.fitColumns(true, false);
30652         }else if(this.grid.autoExpandColumn){
30653             this.autoExpand(true);
30654         }
30655
30656         this.renderUI();
30657     },
30658
30659     
30660         initData : function(ds, cm){
30661         if(this.ds){
30662             this.ds.un("load", this.onLoad, this);
30663             this.ds.un("datachanged", this.onDataChange, this);
30664             this.ds.un("add", this.onAdd, this);
30665             this.ds.un("remove", this.onRemove, this);
30666             this.ds.un("update", this.onUpdate, this);
30667             this.ds.un("clear", this.onClear, this);
30668         }
30669         if(ds){
30670             ds.on("load", this.onLoad, this);
30671             ds.on("datachanged", this.onDataChange, this);
30672             ds.on("add", this.onAdd, this);
30673             ds.on("remove", this.onRemove, this);
30674             ds.on("update", this.onUpdate, this);
30675             ds.on("clear", this.onClear, this);
30676         }
30677         this.ds = ds;
30678
30679         if(this.cm){
30680             this.cm.un("configchange", this.onColConfigChange, this);
30681             this.cm.un("widthchange", this.onColWidthChange, this);
30682             this.cm.un("headerchange", this.onHeaderChange, this);
30683             this.cm.un("hiddenchange", this.onHiddenChange, this);
30684             this.cm.un("columnmoved", this.onColumnMove, this);
30685             this.cm.un("columnlockchange", this.onColumnLock, this);
30686         }
30687         if(cm){
30688             cm.on("configchange", this.onColConfigChange, this);
30689             cm.on("widthchange", this.onColWidthChange, this);
30690             cm.on("headerchange", this.onHeaderChange, this);
30691             cm.on("hiddenchange", this.onHiddenChange, this);
30692             cm.on("columnmoved", this.onColumnMove, this);
30693             cm.on("columnlockchange", this.onColumnLock, this);
30694         }
30695         this.cm = cm;
30696     },
30697
30698         onDataChange : function(){
30699         this.refresh();
30700         this.updateHeaderSortState();
30701     },
30702
30703         onClear : function(){
30704         this.refresh();
30705     },
30706
30707         onUpdate : function(ds, record){
30708         this.refreshRow(record);
30709     },
30710
30711         onAdd : function(ds, records, index){
30712         this.insertRows(ds, index, index + (records.length-1));
30713     },
30714
30715         onRemove : function(ds, record, index, isUpdate){
30716         if(isUpdate !== true){
30717             this.fireEvent("beforerowremoved", this, index, record);
30718         }
30719         this.removeRow(index);
30720         if(isUpdate !== true){
30721             this.processRows(index);
30722             this.applyEmptyText();
30723             this.fireEvent("rowremoved", this, index, record);
30724         }
30725     },
30726
30727         onLoad : function(){
30728         this.scrollToTop();
30729     },
30730
30731         onColWidthChange : function(cm, col, width){
30732         this.updateColumnWidth(col, width);
30733     },
30734
30735         onHeaderChange : function(cm, col, text){
30736         this.updateHeaders();
30737     },
30738
30739         onHiddenChange : function(cm, col, hidden){
30740         this.updateColumnHidden(col, hidden);
30741     },
30742
30743         onColumnMove : function(cm, oldIndex, newIndex){
30744         this.indexMap = null;
30745         var s = this.getScrollState();
30746         this.refresh(true);
30747         this.restoreScroll(s);
30748         this.afterMove(newIndex);
30749     },
30750
30751         onColConfigChange : function(){
30752         delete this.lastViewWidth;
30753         this.indexMap = null;
30754         this.refresh(true);
30755     },
30756
30757     
30758         initUI : function(grid){
30759         grid.on("headerclick", this.onHeaderClick, this);
30760
30761         if(grid.trackMouseOver){
30762             grid.on("mouseover", this.onRowOver, this);
30763           grid.on("mouseout", this.onRowOut, this);
30764       }
30765     },
30766
30767         initEvents : function(){
30768
30769     },
30770
30771         onHeaderClick : function(g, index){
30772         if(this.headersDisabled || !this.cm.isSortable(index)){
30773             return;
30774         }
30775         g.stopEditing(true);
30776         g.store.sort(this.cm.getDataIndex(index));
30777     },
30778
30779         onRowOver : function(e, t){
30780         var row;
30781         if((row = this.findRowIndex(t)) !== false){
30782             this.addRowClass(row, "x-grid3-row-over");
30783         }
30784     },
30785
30786         onRowOut : function(e, t){
30787         var row;
30788         if((row = this.findRowIndex(t)) !== false && row !== this.findRowIndex(e.getRelatedTarget())){
30789             this.removeRowClass(row, "x-grid3-row-over");
30790         }
30791     },
30792
30793         handleWheel : function(e){
30794         e.stopPropagation();
30795     },
30796
30797         onRowSelect : function(row){
30798         this.addRowClass(row, "x-grid3-row-selected");
30799     },
30800
30801         onRowDeselect : function(row){
30802         this.removeRowClass(row, "x-grid3-row-selected");
30803     },
30804
30805         onCellSelect : function(row, col){
30806         var cell = this.getCell(row, col);
30807         if(cell){
30808             this.fly(cell).addClass("x-grid3-cell-selected");
30809         }
30810     },
30811
30812         onCellDeselect : function(row, col){
30813         var cell = this.getCell(row, col);
30814         if(cell){
30815             this.fly(cell).removeClass("x-grid3-cell-selected");
30816         }
30817     },
30818
30819         onColumnSplitterMoved : function(i, w){
30820         this.userResized = true;
30821         var cm = this.grid.colModel;
30822         cm.setColumnWidth(i, w, true);
30823
30824         if(this.forceFit){
30825             this.fitColumns(true, false, i);
30826             this.updateAllColumnWidths();
30827         }else{
30828             this.updateColumnWidth(i, w);
30829         }
30830
30831         this.grid.fireEvent("columnresize", i, w);
30832     },
30833
30834         handleHdMenuClick : function(item){
30835         var index = this.hdCtxIndex;
30836         var cm = this.cm, ds = this.ds;
30837         switch(item.id){
30838             case "asc":
30839                 ds.sort(cm.getDataIndex(index), "ASC");
30840                 break;
30841             case "desc":
30842                 ds.sort(cm.getDataIndex(index), "DESC");
30843                 break;
30844             default:
30845                 index = cm.getIndexById(item.id.substr(4));
30846                 if(index != -1){
30847                     if(item.checked && cm.getColumnsBy(this.isHideableColumn, this).length <= 1){
30848                         this.onDenyColumnHide();
30849                         return false;
30850                     }
30851                     cm.setHidden(index, item.checked);
30852                 }
30853         }
30854         return true;
30855     },
30856
30857         isHideableColumn : function(c){
30858         return !c.hidden && !c.fixed;
30859     },
30860
30861         beforeColMenuShow : function(){
30862         var cm = this.cm,  colCount = cm.getColumnCount();
30863         this.colMenu.removeAll();
30864         for(var i = 0; i < colCount; i++){
30865             if(cm.config[i].fixed !== true && cm.config[i].hideable !== false){
30866                 this.colMenu.add(new Ext.menu.CheckItem({
30867                     id: "col-"+cm.getColumnId(i),
30868                     text: cm.getColumnHeader(i),
30869                     checked: !cm.isHidden(i),
30870                     hideOnClick:false,
30871                     disabled: cm.config[i].hideable === false
30872                 }));
30873             }
30874         }
30875     },
30876
30877         handleHdDown : function(e, t){
30878         if(Ext.fly(t).hasClass('x-grid3-hd-btn')){
30879             e.stopEvent();
30880             var hd = this.findHeaderCell(t);
30881             Ext.fly(hd).addClass('x-grid3-hd-menu-open');
30882             var index = this.getCellIndex(hd);
30883             this.hdCtxIndex = index;
30884             var ms = this.hmenu.items, cm = this.cm;
30885             ms.get("asc").setDisabled(!cm.isSortable(index));
30886             ms.get("desc").setDisabled(!cm.isSortable(index));
30887             this.hmenu.on("hide", function(){
30888                 Ext.fly(hd).removeClass('x-grid3-hd-menu-open');
30889             }, this, {single:true});
30890             this.hmenu.show(t, "tl-bl?");
30891         }
30892     },
30893
30894         handleHdOver : function(e, t){
30895         var hd = this.findHeaderCell(t);
30896         if(hd && !this.headersDisabled){
30897             this.activeHd = hd;
30898             this.activeHdIndex = this.getCellIndex(hd);
30899             var fly = this.fly(hd);
30900             this.activeHdRegion = fly.getRegion();
30901             if(!this.cm.isMenuDisabled(this.activeHdIndex)){
30902                 fly.addClass("x-grid3-hd-over");
30903                 this.activeHdBtn = fly.child('.x-grid3-hd-btn');
30904                 if(this.activeHdBtn){
30905                     this.activeHdBtn.dom.style.height = (hd.firstChild.offsetHeight-1)+'px';
30906                 }
30907             }
30908         }
30909     },
30910
30911         handleHdMove : function(e, t){
30912         if(this.activeHd && !this.headersDisabled){
30913             var hw = this.splitHandleWidth || 5;
30914             var r = this.activeHdRegion;
30915             var x = e.getPageX();
30916             var ss = this.activeHd.style;
30917             if(x - r.left <= hw && this.cm.isResizable(this.activeHdIndex-1)){
30918                 ss.cursor = Ext.isAir ? 'move' : Ext.isSafari ? 'e-resize' : 'col-resize';             }else if(r.right - x <= (!this.activeHdBtn ? hw : 2) && this.cm.isResizable(this.activeHdIndex)){
30919                 ss.cursor = Ext.isAir ? 'move' : Ext.isSafari ? 'w-resize' : 'col-resize';
30920             }else{
30921                 ss.cursor = '';
30922             }
30923         }
30924     },
30925
30926         handleHdOut : function(e, t){
30927         var hd = this.findHeaderCell(t);
30928         if(hd && (!Ext.isIE || !e.within(hd, true))){
30929             this.activeHd = null;
30930             this.fly(hd).removeClass("x-grid3-hd-over");
30931             hd.style.cursor = '';
30932         }
30933     },
30934
30935         hasRows : function(){
30936         var fc = this.mainBody.dom.firstChild;
30937         return fc && fc.className != 'x-grid-empty';
30938     },
30939
30940         bind : function(d, c){
30941         this.initData(d, c);
30942     }
30943 });
30944
30945
30946 Ext.grid.GridView.SplitDragZone = function(grid, hd){
30947     this.grid = grid;
30948     this.view = grid.getView();
30949     this.marker = this.view.resizeMarker;
30950     this.proxy = this.view.resizeProxy;
30951     Ext.grid.GridView.SplitDragZone.superclass.constructor.call(this, hd,
30952         "gridSplitters" + this.grid.getGridEl().id, {
30953         dragElId : Ext.id(this.proxy.dom), resizeFrame:false
30954     });
30955     this.scroll = false;
30956     this.hw = this.view.splitHandleWidth || 5;
30957 };
30958 Ext.extend(Ext.grid.GridView.SplitDragZone, Ext.dd.DDProxy, {
30959
30960     b4StartDrag : function(x, y){
30961         this.view.headersDisabled = true;
30962         var h = this.view.mainWrap.getHeight();
30963         this.marker.setHeight(h);
30964         this.marker.show();
30965         this.marker.alignTo(this.view.getHeaderCell(this.cellIndex), 'tl-tl', [-2, 0]);
30966         this.proxy.setHeight(h);
30967         var w = this.cm.getColumnWidth(this.cellIndex);
30968         var minw = Math.max(w-this.grid.minColumnWidth, 0);
30969         this.resetConstraints();
30970         this.setXConstraint(minw, 1000);
30971         this.setYConstraint(0, 0);
30972         this.minX = x - minw;
30973         this.maxX = x + 1000;
30974         this.startPos = x;
30975         Ext.dd.DDProxy.prototype.b4StartDrag.call(this, x, y);
30976     },
30977
30978
30979     handleMouseDown : function(e){
30980         var t = this.view.findHeaderCell(e.getTarget());
30981         if(t){
30982             var xy = this.view.fly(t).getXY(), x = xy[0], y = xy[1];
30983             var exy = e.getXY(), ex = exy[0], ey = exy[1];
30984             var w = t.offsetWidth, adjust = false;
30985             if((ex - x) <= this.hw){
30986                 adjust = -1;
30987             }else if((x+w) - ex <= this.hw){
30988                 adjust = 0;
30989             }
30990             if(adjust !== false){
30991                 this.cm = this.grid.colModel;
30992                 var ci = this.view.getCellIndex(t);
30993                 if(adjust == -1){
30994                   if (ci + adjust < 0) {
30995                     return;
30996                   }
30997                     while(this.cm.isHidden(ci+adjust)){
30998                         --adjust;
30999                         if(ci+adjust < 0){
31000                             return;
31001                         }
31002                     }
31003                 }
31004                 this.cellIndex = ci+adjust;
31005                 this.split = t.dom;
31006                 if(this.cm.isResizable(this.cellIndex) && !this.cm.isFixed(this.cellIndex)){
31007                     Ext.grid.GridView.SplitDragZone.superclass.handleMouseDown.apply(this, arguments);
31008                 }
31009             }else if(this.view.columnDrag){
31010                 this.view.columnDrag.callHandleMouseDown(e);
31011             }
31012         }
31013     },
31014
31015     endDrag : function(e){
31016         this.marker.hide();
31017         var v = this.view;
31018         var endX = Math.max(this.minX, e.getPageX());
31019         var diff = endX - this.startPos;
31020         v.onColumnSplitterMoved(this.cellIndex, this.cm.getColumnWidth(this.cellIndex)+diff);
31021         setTimeout(function(){
31022             v.headersDisabled = false;
31023         }, 50);
31024     },
31025
31026     autoOffset : function(){
31027         this.setDelta(0,0);
31028     }
31029 });
31030
31031
31032 Ext.grid.GroupingView = Ext.extend(Ext.grid.GridView, {
31033     
31034     hideGroupedColumn:false,
31035     
31036     showGroupName:true,
31037     
31038     startCollapsed:false,
31039     
31040     enableGrouping:true,
31041     
31042     enableGroupingMenu:true,
31043     
31044     enableNoGroups:true,
31045     
31046     emptyGroupText : '(None)',
31047     
31048     ignoreAdd: false,
31049     
31050     groupTextTpl : '{text}',
31051     
31052     
31053
31054     
31055     gidSeed : 1000,
31056
31057     
31058     initTemplates : function(){
31059         Ext.grid.GroupingView.superclass.initTemplates.call(this);
31060         this.state = {};
31061
31062         var sm = this.grid.getSelectionModel();
31063         sm.on(sm.selectRow ? 'beforerowselect' : 'beforecellselect',
31064                 this.onBeforeRowSelect, this);
31065
31066         if(!this.startGroup){
31067             this.startGroup = new Ext.XTemplate(
31068                 '<div id="{groupId}" class="x-grid-group {cls}">',
31069                     '<div id="{groupId}-hd" class="x-grid-group-hd" style="{style}"><div>', this.groupTextTpl ,'</div></div>',
31070                     '<div id="{groupId}-bd" class="x-grid-group-body">'
31071             );
31072         }
31073         this.startGroup.compile();
31074         this.endGroup = '</div></div>';
31075     },
31076
31077     
31078     findGroup : function(el){
31079         return Ext.fly(el).up('.x-grid-group', this.mainBody.dom);
31080     },
31081
31082     
31083     getGroups : function(){
31084         return this.hasRows() ? this.mainBody.dom.childNodes : [];
31085     },
31086
31087     
31088     onAdd : function(){
31089         if(this.enableGrouping && !this.ignoreAdd){
31090             var ss = this.getScrollState();
31091             this.refresh();
31092             this.restoreScroll(ss);
31093         }else if(!this.enableGrouping){
31094             Ext.grid.GroupingView.superclass.onAdd.apply(this, arguments);
31095         }
31096     },
31097
31098     
31099     onRemove : function(ds, record, index, isUpdate){
31100         Ext.grid.GroupingView.superclass.onRemove.apply(this, arguments);
31101         var g = document.getElementById(record._groupId);
31102         if(g && g.childNodes[1].childNodes.length < 1){
31103             Ext.removeNode(g);
31104         }
31105         this.applyEmptyText();
31106     },
31107
31108     
31109     refreshRow : function(record){
31110         if(this.ds.getCount()==1){
31111             this.refresh();
31112         }else{
31113             this.isUpdating = true;
31114             Ext.grid.GroupingView.superclass.refreshRow.apply(this, arguments);
31115             this.isUpdating = false;
31116         }
31117     },
31118
31119     
31120     beforeMenuShow : function(){
31121         var field = this.getGroupField();
31122         var g = this.hmenu.items.get('groupBy');
31123         if(g){
31124             g.setDisabled(this.cm.config[this.hdCtxIndex].groupable === false);
31125         }
31126         var s = this.hmenu.items.get('showGroups');
31127         if(s){
31128             if (!!field){ 
31129                 s.setDisabled(this.cm.config[this.hdCtxIndex].groupable === false)
31130             }
31131             s.setChecked(!!field);
31132         }
31133     },
31134
31135     
31136     renderUI : function(){
31137         Ext.grid.GroupingView.superclass.renderUI.call(this);
31138         this.mainBody.on('mousedown', this.interceptMouse, this);
31139
31140         if(this.enableGroupingMenu && this.hmenu){
31141             this.hmenu.add('-',{
31142                 id:'groupBy',
31143                 text: this.groupByText,
31144                 handler: this.onGroupByClick,
31145                 scope: this,
31146                 iconCls:'x-group-by-icon'
31147             });
31148             if(this.enableNoGroups){
31149                 this.hmenu.add({
31150                     id:'showGroups',
31151                     text: this.showGroupsText,
31152                     checked: true,
31153                     checkHandler: this.onShowGroupsClick,
31154                     scope: this
31155                 });
31156             }
31157             this.hmenu.on('beforeshow', this.beforeMenuShow, this);
31158         }
31159     },
31160
31161     
31162     onGroupByClick : function(){
31163         this.grid.store.groupBy(this.cm.getDataIndex(this.hdCtxIndex));
31164         this.beforeMenuShow(); 
31165     },
31166
31167     
31168     onShowGroupsClick : function(mi, checked){
31169         if(checked){
31170             this.onGroupByClick();
31171         }else{
31172             this.grid.store.clearGrouping();
31173         }
31174     },
31175
31176     
31177     toggleGroup : function(group, expanded){
31178         this.grid.stopEditing(true);
31179         group = Ext.getDom(group);
31180         var gel = Ext.fly(group);
31181         expanded = expanded !== undefined ?
31182                 expanded : gel.hasClass('x-grid-group-collapsed');
31183
31184         this.state[gel.dom.id] = expanded;
31185         gel[expanded ? 'removeClass' : 'addClass']('x-grid-group-collapsed');
31186     },
31187
31188     
31189     toggleAllGroups : function(expanded){
31190         var groups = this.getGroups();
31191         for(var i = 0, len = groups.length; i < len; i++){
31192             this.toggleGroup(groups[i], expanded);
31193         }
31194     },
31195
31196     
31197     expandAllGroups : function(){
31198         this.toggleAllGroups(true);
31199     },
31200
31201     
31202     collapseAllGroups : function(){
31203         this.toggleAllGroups(false);
31204     },
31205
31206     
31207     interceptMouse : function(e){
31208         var hd = e.getTarget('.x-grid-group-hd', this.mainBody);
31209         if(hd){
31210             e.stopEvent();
31211             this.toggleGroup(hd.parentNode);
31212         }
31213     },
31214
31215     
31216     getGroup : function(v, r, groupRenderer, rowIndex, colIndex, ds){
31217         var g = groupRenderer ? groupRenderer(v, {}, r, rowIndex, colIndex, ds) : String(v);
31218         if(g === ''){
31219             g = this.cm.config[colIndex].emptyGroupText || this.emptyGroupText;
31220         }
31221         return g;
31222     },
31223
31224     
31225     getGroupField : function(){
31226         return this.grid.store.getGroupState();
31227     },
31228
31229     
31230     renderRows : function(){
31231         var groupField = this.getGroupField();
31232         var eg = !!groupField;
31233         
31234         if(this.hideGroupedColumn) {
31235             var colIndex = this.cm.findColumnIndex(groupField);
31236             if(!eg && this.lastGroupField !== undefined) {
31237                 this.mainBody.update('');
31238                 this.cm.setHidden(this.cm.findColumnIndex(this.lastGroupField), false);
31239                 delete this.lastGroupField;
31240             }else if (eg && this.lastGroupField === undefined) {
31241                 this.lastGroupField = groupField;
31242                 this.cm.setHidden(colIndex, true);
31243             }else if (eg && this.lastGroupField !== undefined && groupField !== this.lastGroupField) {
31244                 this.mainBody.update('');
31245                 var oldIndex = this.cm.findColumnIndex(this.lastGroupField);
31246                 this.cm.setHidden(oldIndex, false);
31247                 this.lastGroupField = groupField;
31248                 this.cm.setHidden(colIndex, true);
31249             }
31250         }
31251         return Ext.grid.GroupingView.superclass.renderRows.apply(
31252                     this, arguments);
31253     },
31254
31255     
31256     doRender : function(cs, rs, ds, startRow, colCount, stripe){
31257         if(rs.length < 1){
31258             return '';
31259         }
31260         var groupField = this.getGroupField();
31261         var colIndex = this.cm.findColumnIndex(groupField);
31262
31263         this.enableGrouping = !!groupField;
31264
31265         if(!this.enableGrouping || this.isUpdating){
31266             return Ext.grid.GroupingView.superclass.doRender.apply(
31267                     this, arguments);
31268         }
31269         var gstyle = 'width:'+this.getTotalWidth()+';';
31270
31271         var gidPrefix = this.grid.getGridEl().id;
31272         var cfg = this.cm.config[colIndex];
31273         var groupRenderer = cfg.groupRenderer || cfg.renderer;
31274         var prefix = this.showGroupName ?
31275                      (cfg.groupName || cfg.header)+': ' : '';
31276
31277         var groups = [], curGroup, i, len, gid;
31278         for(i = 0, len = rs.length; i < len; i++){
31279             var rowIndex = startRow + i;
31280             var r = rs[i],
31281                 gvalue = r.data[groupField],
31282                 g = this.getGroup(gvalue, r, groupRenderer, rowIndex, colIndex, ds);
31283             if(!curGroup || curGroup.group != g){
31284                 gid = gidPrefix + '-gp-' + groupField + '-' + Ext.util.Format.htmlEncode(g);
31285                 
31286                                 
31287                                 var isCollapsed  = typeof this.state[gid] !== 'undefined' ? !this.state[gid] : this.startCollapsed;
31288                                 var gcls = isCollapsed ? 'x-grid-group-collapsed' : ''; 
31289                 curGroup = {
31290                     group: g,
31291                     gvalue: gvalue,
31292                     text: prefix + g,
31293                     groupId: gid,
31294                     startRow: rowIndex,
31295                     rs: [r],
31296                     cls: gcls,
31297                     style: gstyle
31298                 };
31299                 groups.push(curGroup);
31300             }else{
31301                 curGroup.rs.push(r);
31302             }
31303             r._groupId = gid;
31304         }
31305
31306         var buf = [];
31307         for(i = 0, len = groups.length; i < len; i++){
31308             var g = groups[i];
31309             this.doGroupStart(buf, g, cs, ds, colCount);
31310             buf[buf.length] = Ext.grid.GroupingView.superclass.doRender.call(
31311                     this, cs, g.rs, ds, g.startRow, colCount, stripe);
31312
31313             this.doGroupEnd(buf, g, cs, ds, colCount);
31314         }
31315         return buf.join('');
31316     },
31317
31318     
31319     getGroupId : function(value){
31320         var gidPrefix = this.grid.getGridEl().id;
31321         var groupField = this.getGroupField();
31322         var colIndex = this.cm.findColumnIndex(groupField);
31323         var cfg = this.cm.config[colIndex];
31324         var groupRenderer = cfg.groupRenderer || cfg.renderer;
31325         var gtext = this.getGroup(value, {data:{}}, groupRenderer, 0, colIndex, this.ds);
31326         return gidPrefix + '-gp-' + groupField + '-' + Ext.util.Format.htmlEncode(value);
31327     },
31328
31329     
31330     doGroupStart : function(buf, g, cs, ds, colCount){
31331         buf[buf.length] = this.startGroup.apply(g);
31332     },
31333
31334     
31335     doGroupEnd : function(buf, g, cs, ds, colCount){
31336         buf[buf.length] = this.endGroup;
31337     },
31338
31339     
31340     getRows : function(){
31341         if(!this.enableGrouping){
31342             return Ext.grid.GroupingView.superclass.getRows.call(this);
31343         }
31344         var r = [];
31345         var g, gs = this.getGroups();
31346         for(var i = 0, len = gs.length; i < len; i++){
31347             g = gs[i].childNodes[1].childNodes;
31348             for(var j = 0, jlen = g.length; j < jlen; j++){
31349                 r[r.length] = g[j];
31350             }
31351         }
31352         return r;
31353     },
31354
31355     
31356     updateGroupWidths : function(){
31357         if(!this.enableGrouping || !this.hasRows()){
31358             return;
31359         }
31360         var tw = Math.max(this.cm.getTotalWidth(), this.el.dom.offsetWidth-this.scrollOffset) +'px';
31361         var gs = this.getGroups();
31362         for(var i = 0, len = gs.length; i < len; i++){
31363             gs[i].firstChild.style.width = tw;
31364         }
31365     },
31366
31367     
31368     onColumnWidthUpdated : function(col, w, tw){
31369         this.updateGroupWidths();
31370     },
31371
31372     
31373     onAllColumnWidthsUpdated : function(ws, tw){
31374         this.updateGroupWidths();
31375     },
31376
31377     
31378     onColumnHiddenUpdated : function(col, hidden, tw){
31379         this.updateGroupWidths();
31380     },
31381
31382     
31383     onLayout : function(){
31384         this.updateGroupWidths();
31385     },
31386
31387     
31388     onBeforeRowSelect : function(sm, rowIndex){
31389         if(!this.enableGrouping){
31390             return;
31391         }
31392         var row = this.getRow(rowIndex);
31393         if(row && !row.offsetParent){
31394             var g = this.findGroup(row);
31395             this.toggleGroup(g, true);
31396         }
31397     },
31398
31399     
31400     groupByText: 'Group By This Field',
31401     
31402     showGroupsText: 'Show in Groups'
31403 });
31404
31405 Ext.grid.GroupingView.GROUP_ID = 1000;
31406
31407
31408 Ext.grid.HeaderDragZone = function(grid, hd, hd2){
31409     this.grid = grid;
31410     this.view = grid.getView();
31411     this.ddGroup = "gridHeader" + this.grid.getGridEl().id;
31412     Ext.grid.HeaderDragZone.superclass.constructor.call(this, hd);
31413     if(hd2){
31414         this.setHandleElId(Ext.id(hd));
31415         this.setOuterHandleElId(Ext.id(hd2));
31416     }
31417     this.scroll = false;
31418 };
31419 Ext.extend(Ext.grid.HeaderDragZone, Ext.dd.DragZone, {
31420     maxDragWidth: 120,
31421     getDragData : function(e){
31422         var t = Ext.lib.Event.getTarget(e);
31423         var h = this.view.findHeaderCell(t);
31424         if(h){
31425             return {ddel: h.firstChild, header:h};
31426         }
31427         return false;
31428     },
31429
31430     onInitDrag : function(e){
31431         this.view.headersDisabled = true;
31432         var clone = this.dragData.ddel.cloneNode(true);
31433         clone.id = Ext.id();
31434         clone.style.width = Math.min(this.dragData.header.offsetWidth,this.maxDragWidth) + "px";
31435         this.proxy.update(clone);
31436         return true;
31437     },
31438
31439     afterValidDrop : function(){
31440         var v = this.view;
31441         setTimeout(function(){
31442             v.headersDisabled = false;
31443         }, 50);
31444     },
31445
31446     afterInvalidDrop : function(){
31447         var v = this.view;
31448         setTimeout(function(){
31449             v.headersDisabled = false;
31450         }, 50);
31451     }
31452 });
31453
31454
31455
31456 Ext.grid.HeaderDropZone = function(grid, hd, hd2){
31457     this.grid = grid;
31458     this.view = grid.getView();
31459     
31460     this.proxyTop = Ext.DomHelper.append(document.body, {
31461         cls:"col-move-top", html:"&#160;"
31462     }, true);
31463     this.proxyBottom = Ext.DomHelper.append(document.body, {
31464         cls:"col-move-bottom", html:"&#160;"
31465     }, true);
31466     this.proxyTop.hide = this.proxyBottom.hide = function(){
31467         this.setLeftTop(-100,-100);
31468         this.setStyle("visibility", "hidden");
31469     };
31470     this.ddGroup = "gridHeader" + this.grid.getGridEl().id;
31471     
31472     
31473     Ext.grid.HeaderDropZone.superclass.constructor.call(this, grid.getGridEl().dom);
31474 };
31475 Ext.extend(Ext.grid.HeaderDropZone, Ext.dd.DropZone, {
31476     proxyOffsets : [-4, -9],
31477     fly: Ext.Element.fly,
31478
31479     getTargetFromEvent : function(e){
31480         var t = Ext.lib.Event.getTarget(e);
31481         var cindex = this.view.findCellIndex(t);
31482         if(cindex !== false){
31483             return this.view.getHeaderCell(cindex);
31484         }
31485     },
31486
31487     nextVisible : function(h){
31488         var v = this.view, cm = this.grid.colModel;
31489         h = h.nextSibling;
31490         while(h){
31491             if(!cm.isHidden(v.getCellIndex(h))){
31492                 return h;
31493             }
31494             h = h.nextSibling;
31495         }
31496         return null;
31497     },
31498
31499     prevVisible : function(h){
31500         var v = this.view, cm = this.grid.colModel;
31501         h = h.prevSibling;
31502         while(h){
31503             if(!cm.isHidden(v.getCellIndex(h))){
31504                 return h;
31505             }
31506             h = h.prevSibling;
31507         }
31508         return null;
31509     },
31510
31511     positionIndicator : function(h, n, e){
31512         var x = Ext.lib.Event.getPageX(e);
31513         var r = Ext.lib.Dom.getRegion(n.firstChild);
31514         var px, pt, py = r.top + this.proxyOffsets[1];
31515         if((r.right - x) <= (r.right-r.left)/2){
31516             px = r.right+this.view.borderWidth;
31517             pt = "after";
31518         }else{
31519             px = r.left;
31520             pt = "before";
31521         }
31522         var oldIndex = this.view.getCellIndex(h);
31523         var newIndex = this.view.getCellIndex(n);
31524
31525         if(this.grid.colModel.isFixed(newIndex)){
31526             return false;
31527         }
31528
31529         var locked = this.grid.colModel.isLocked(newIndex);
31530
31531         if(pt == "after"){
31532             newIndex++;
31533         }
31534         if(oldIndex < newIndex){
31535             newIndex--;
31536         }
31537         if(oldIndex == newIndex && (locked == this.grid.colModel.isLocked(oldIndex))){
31538             return false;
31539         }
31540         px +=  this.proxyOffsets[0];
31541         this.proxyTop.setLeftTop(px, py);
31542         this.proxyTop.show();
31543         if(!this.bottomOffset){
31544             this.bottomOffset = this.view.mainHd.getHeight();
31545         }
31546         this.proxyBottom.setLeftTop(px, py+this.proxyTop.dom.offsetHeight+this.bottomOffset);
31547         this.proxyBottom.show();
31548         return pt;
31549     },
31550
31551     onNodeEnter : function(n, dd, e, data){
31552         if(data.header != n){
31553             this.positionIndicator(data.header, n, e);
31554         }
31555     },
31556
31557     onNodeOver : function(n, dd, e, data){
31558         var result = false;
31559         if(data.header != n){
31560             result = this.positionIndicator(data.header, n, e);
31561         }
31562         if(!result){
31563             this.proxyTop.hide();
31564             this.proxyBottom.hide();
31565         }
31566         return result ? this.dropAllowed : this.dropNotAllowed;
31567     },
31568
31569     onNodeOut : function(n, dd, e, data){
31570         this.proxyTop.hide();
31571         this.proxyBottom.hide();
31572     },
31573
31574     onNodeDrop : function(n, dd, e, data){
31575         var h = data.header;
31576         if(h != n){
31577             var cm = this.grid.colModel;
31578             var x = Ext.lib.Event.getPageX(e);
31579             var r = Ext.lib.Dom.getRegion(n.firstChild);
31580             var pt = (r.right - x) <= ((r.right-r.left)/2) ? "after" : "before";
31581             var oldIndex = this.view.getCellIndex(h);
31582             var newIndex = this.view.getCellIndex(n);
31583             var locked = cm.isLocked(newIndex);
31584             if(pt == "after"){
31585                 newIndex++;
31586             }
31587             if(oldIndex < newIndex){
31588                 newIndex--;
31589             }
31590             if(oldIndex == newIndex && (locked == cm.isLocked(oldIndex))){
31591                 return false;
31592             }
31593             cm.setLocked(oldIndex, locked, true);
31594             cm.moveColumn(oldIndex, newIndex);
31595             this.grid.fireEvent("columnmove", oldIndex, newIndex);
31596             return true;
31597         }
31598         return false;
31599     }
31600 });
31601
31602
31603 Ext.grid.GridView.ColumnDragZone = function(grid, hd){
31604     Ext.grid.GridView.ColumnDragZone.superclass.constructor.call(this, grid, hd, null);
31605     this.proxy.el.addClass('x-grid3-col-dd');
31606 };
31607
31608 Ext.extend(Ext.grid.GridView.ColumnDragZone, Ext.grid.HeaderDragZone, {
31609     handleMouseDown : function(e){
31610
31611     },
31612
31613     callHandleMouseDown : function(e){
31614         Ext.grid.GridView.ColumnDragZone.superclass.handleMouseDown.call(this, e);
31615     }
31616 });
31617 Ext.grid.SplitDragZone = function(grid, hd, hd2){
31618     this.grid = grid;
31619     this.view = grid.getView();
31620     this.proxy = this.view.resizeProxy;
31621     Ext.grid.SplitDragZone.superclass.constructor.call(this, hd,
31622         "gridSplitters" + this.grid.getGridEl().id, {
31623         dragElId : Ext.id(this.proxy.dom), resizeFrame:false
31624     });
31625     this.setHandleElId(Ext.id(hd));
31626     this.setOuterHandleElId(Ext.id(hd2));
31627     this.scroll = false;
31628 };
31629 Ext.extend(Ext.grid.SplitDragZone, Ext.dd.DDProxy, {
31630     fly: Ext.Element.fly,
31631
31632     b4StartDrag : function(x, y){
31633         this.view.headersDisabled = true;
31634         this.proxy.setHeight(this.view.mainWrap.getHeight());
31635         var w = this.cm.getColumnWidth(this.cellIndex);
31636         var minw = Math.max(w-this.grid.minColumnWidth, 0);
31637         this.resetConstraints();
31638         this.setXConstraint(minw, 1000);
31639         this.setYConstraint(0, 0);
31640         this.minX = x - minw;
31641         this.maxX = x + 1000;
31642         this.startPos = x;
31643         Ext.dd.DDProxy.prototype.b4StartDrag.call(this, x, y);
31644     },
31645
31646
31647     handleMouseDown : function(e){
31648         ev = Ext.EventObject.setEvent(e);
31649         var t = this.fly(ev.getTarget());
31650         if(t.hasClass("x-grid-split")){
31651             this.cellIndex = this.view.getCellIndex(t.dom);
31652             this.split = t.dom;
31653             this.cm = this.grid.colModel;
31654             if(this.cm.isResizable(this.cellIndex) && !this.cm.isFixed(this.cellIndex)){
31655                 Ext.grid.SplitDragZone.superclass.handleMouseDown.apply(this, arguments);
31656             }
31657         }
31658     },
31659
31660     endDrag : function(e){
31661         this.view.headersDisabled = false;
31662         var endX = Math.max(this.minX, Ext.lib.Event.getPageX(e));
31663         var diff = endX - this.startPos;
31664         this.view.onColumnSplitterMoved(this.cellIndex, this.cm.getColumnWidth(this.cellIndex)+diff);
31665     },
31666
31667     autoOffset : function(){
31668         this.setDelta(0,0);
31669     }
31670 });
31671 Ext.grid.GridDragZone = function(grid, config){
31672     this.view = grid.getView();
31673     Ext.grid.GridDragZone.superclass.constructor.call(this, this.view.mainBody.dom, config);
31674     if(this.view.lockedBody){
31675         this.setHandleElId(Ext.id(this.view.mainBody.dom));
31676         this.setOuterHandleElId(Ext.id(this.view.lockedBody.dom));
31677     }
31678     this.scroll = false;
31679     this.grid = grid;
31680     this.ddel = document.createElement('div');
31681     this.ddel.className = 'x-grid-dd-wrap';
31682 };
31683
31684 Ext.extend(Ext.grid.GridDragZone, Ext.dd.DragZone, {
31685     ddGroup : "GridDD",
31686
31687     getDragData : function(e){
31688         var t = Ext.lib.Event.getTarget(e);
31689         var rowIndex = this.view.findRowIndex(t);
31690         if(rowIndex !== false){
31691             var sm = this.grid.selModel;
31692             if(!sm.isSelected(rowIndex) || e.hasModifier()){
31693                 sm.handleMouseDown(this.grid, rowIndex, e);
31694             }
31695             return {grid: this.grid, ddel: this.ddel, rowIndex: rowIndex, selections:sm.getSelections()};
31696         }
31697         return false;
31698     },
31699
31700     onInitDrag : function(e){
31701         var data = this.dragData;
31702         this.ddel.innerHTML = this.grid.getDragDropText();
31703         this.proxy.update(this.ddel);
31704             },
31705
31706     afterRepair : function(){
31707         this.dragging = false;
31708     },
31709
31710     getRepairXY : function(e, data){
31711         return false;
31712     },
31713
31714     onEndDrag : function(data, e){
31715             },
31716
31717     onValidDrop : function(dd, e, id){
31718                 this.hideProxy();
31719     },
31720
31721     beforeInvalidDrop : function(e, id){
31722
31723     }
31724 });
31725
31726
31727 Ext.grid.ColumnModel = function(config){
31728         
31729     this.defaultWidth = 100;
31730
31731     
31732     this.defaultSortable = false;
31733
31734     
31735     if(config.columns){
31736         Ext.apply(this, config);
31737         this.setConfig(config.columns, true);
31738     }else{
31739         this.setConfig(config, true);
31740     }
31741     this.addEvents(
31742         
31743             "widthchange",
31744         
31745             "headerchange",
31746         
31747             "hiddenchange",
31748             
31749         "columnmoved",
31750         
31751         "columnlockchange",
31752         
31753         "configchange"
31754     );
31755     Ext.grid.ColumnModel.superclass.constructor.call(this);
31756 };
31757 Ext.extend(Ext.grid.ColumnModel, Ext.util.Observable, {
31758     
31759     
31760     
31761     
31762     
31763     
31764     
31765     
31766     
31767     
31768     
31769     
31770     
31771     
31772     
31773
31774     
31775     getColumnId : function(index){
31776         return this.config[index].id;
31777     },
31778
31779     
31780     setConfig : function(config, initial){
31781         if(!initial){ 
31782             delete this.totalWidth;
31783             for(var i = 0, len = this.config.length; i < len; i++){
31784                 var c = this.config[i];
31785                 if(c.editor){
31786                     c.editor.destroy();
31787                 }
31788             }
31789         }
31790         this.config = config;
31791         this.lookup = {};
31792         
31793         for(var i = 0, len = config.length; i < len; i++){
31794             var c = config[i];
31795             if(typeof c.renderer == "string"){
31796                 c.renderer = Ext.util.Format[c.renderer];
31797             }
31798             if(typeof c.id == "undefined"){
31799                 c.id = i;
31800             }
31801             if(c.editor && c.editor.isFormField){
31802                 c.editor = new Ext.grid.GridEditor(c.editor);
31803             }
31804             this.lookup[c.id] = c;
31805         }
31806         if(!initial){
31807             this.fireEvent('configchange', this);
31808         }
31809     },
31810
31811     
31812     getColumnById : function(id){
31813         return this.lookup[id];
31814     },
31815
31816     
31817     getIndexById : function(id){
31818         for(var i = 0, len = this.config.length; i < len; i++){
31819             if(this.config[i].id == id){
31820                 return i;
31821             }
31822         }
31823         return -1;
31824     },
31825
31826     
31827     moveColumn : function(oldIndex, newIndex){
31828         var c = this.config[oldIndex];
31829         this.config.splice(oldIndex, 1);
31830         this.config.splice(newIndex, 0, c);
31831         this.dataMap = null;
31832         this.fireEvent("columnmoved", this, oldIndex, newIndex);
31833     },
31834
31835     
31836     isLocked : function(colIndex){
31837         return this.config[colIndex].locked === true;
31838     },
31839
31840     
31841     setLocked : function(colIndex, value, suppressEvent){
31842         if(this.isLocked(colIndex) == value){
31843             return;
31844         }
31845         this.config[colIndex].locked = value;
31846         if(!suppressEvent){
31847             this.fireEvent("columnlockchange", this, colIndex, value);
31848         }
31849     },
31850
31851     
31852     getTotalLockedWidth : function(){
31853         var totalWidth = 0;
31854         for(var i = 0; i < this.config.length; i++){
31855             if(this.isLocked(i) && !this.isHidden(i)){
31856                 this.totalWidth += this.getColumnWidth(i);
31857             }
31858         }
31859         return totalWidth;
31860     },
31861
31862     
31863     getLockedCount : function(){
31864         for(var i = 0, len = this.config.length; i < len; i++){
31865             if(!this.isLocked(i)){
31866                 return i;
31867             }
31868         }
31869     },
31870
31871     
31872     getColumnCount : function(visibleOnly){
31873         if(visibleOnly === true){
31874             var c = 0;
31875             for(var i = 0, len = this.config.length; i < len; i++){
31876                 if(!this.isHidden(i)){
31877                     c++;
31878                 }
31879             }
31880             return c;
31881         }
31882         return this.config.length;
31883     },
31884
31885     
31886     getColumnsBy : function(fn, scope){
31887         var r = [];
31888         for(var i = 0, len = this.config.length; i < len; i++){
31889             var c = this.config[i];
31890             if(fn.call(scope||this, c, i) === true){
31891                 r[r.length] = c;
31892             }
31893         }
31894         return r;
31895     },
31896
31897     
31898     isSortable : function(col){
31899         if(typeof this.config[col].sortable == "undefined"){
31900             return this.defaultSortable;
31901         }
31902         return this.config[col].sortable;
31903     },
31904
31905     
31906     isMenuDisabled : function(col){
31907         return !!this.config[col].menuDisabled;
31908     },
31909
31910     
31911     getRenderer : function(col){
31912         if(!this.config[col].renderer){
31913             return Ext.grid.ColumnModel.defaultRenderer;
31914         }
31915         return this.config[col].renderer;
31916     },
31917
31918     
31919     setRenderer : function(col, fn){
31920         this.config[col].renderer = fn;
31921     },
31922
31923     
31924     getColumnWidth : function(col){
31925         return this.config[col].width || this.defaultWidth;
31926     },
31927
31928     
31929     setColumnWidth : function(col, width, suppressEvent){
31930         this.config[col].width = width;
31931         this.totalWidth = null;
31932         if(!suppressEvent){
31933              this.fireEvent("widthchange", this, col, width);
31934         }
31935     },
31936
31937     
31938     getTotalWidth : function(includeHidden){
31939         if(!this.totalWidth){
31940             this.totalWidth = 0;
31941             for(var i = 0, len = this.config.length; i < len; i++){
31942                 if(includeHidden || !this.isHidden(i)){
31943                     this.totalWidth += this.getColumnWidth(i);
31944                 }
31945             }
31946         }
31947         return this.totalWidth;
31948     },
31949
31950     
31951     getColumnHeader : function(col){
31952         return this.config[col].header;
31953     },
31954
31955     
31956     setColumnHeader : function(col, header){
31957         this.config[col].header = header;
31958         this.fireEvent("headerchange", this, col, header);
31959     },
31960
31961     
31962     getColumnTooltip : function(col){
31963             return this.config[col].tooltip;
31964     },
31965     
31966     setColumnTooltip : function(col, tooltip){
31967             this.config[col].tooltip = tooltip;
31968     },
31969
31970     
31971     getDataIndex : function(col){
31972         return this.config[col].dataIndex;
31973     },
31974
31975     
31976     setDataIndex : function(col, dataIndex){
31977         this.config[col].dataIndex = dataIndex;
31978     },
31979
31980     findColumnIndex : function(dataIndex){
31981         var c = this.config;
31982         for(var i = 0, len = c.length; i < len; i++){
31983             if(c[i].dataIndex == dataIndex){
31984                 return i;
31985             }
31986         }
31987         return -1;
31988     },
31989
31990     
31991     isCellEditable : function(colIndex, rowIndex){
31992         return (this.config[colIndex].editable || (typeof this.config[colIndex].editable == "undefined" && this.config[colIndex].editor)) ? true : false;
31993     },
31994
31995     
31996     getCellEditor : function(colIndex, rowIndex){
31997         return this.config[colIndex].editor;
31998     },
31999
32000     
32001     setEditable : function(col, editable){
32002         this.config[col].editable = editable;
32003     },
32004
32005
32006     
32007     isHidden : function(colIndex){
32008         return this.config[colIndex].hidden;
32009     },
32010
32011
32012     
32013     isFixed : function(colIndex){
32014         return this.config[colIndex].fixed;
32015     },
32016
32017     
32018     isResizable : function(colIndex){
32019         return colIndex >= 0 && this.config[colIndex].resizable !== false && this.config[colIndex].fixed !== true;
32020     },
32021     
32022     setHidden : function(colIndex, hidden){
32023         var c = this.config[colIndex];
32024         if(c.hidden !== hidden){
32025             c.hidden = hidden;
32026             this.totalWidth = null;
32027             this.fireEvent("hiddenchange", this, colIndex, hidden);
32028         }
32029     },
32030
32031     
32032     setEditor : function(col, editor){
32033         this.config[col].editor = editor;
32034     }
32035 });
32036
32037
32038 Ext.grid.ColumnModel.defaultRenderer = function(value){
32039         if(typeof value == "string" && value.length < 1){
32040             return "&#160;";
32041         }
32042         return value;
32043 };
32044
32045
32046 Ext.grid.DefaultColumnModel = Ext.grid.ColumnModel;
32047
32048
32049 Ext.grid.AbstractSelectionModel = function(){
32050     this.locked = false;
32051     Ext.grid.AbstractSelectionModel.superclass.constructor.call(this);
32052 };
32053
32054 Ext.extend(Ext.grid.AbstractSelectionModel, Ext.util.Observable,  {
32055     
32056     init : function(grid){
32057         this.grid = grid;
32058         this.initEvents();
32059     },
32060
32061     
32062     lock : function(){
32063         this.locked = true;
32064     },
32065
32066     
32067     unlock : function(){
32068         this.locked = false;
32069     },
32070
32071     
32072     isLocked : function(){
32073         return this.locked;
32074     }
32075 });
32076
32077 Ext.grid.RowSelectionModel = function(config){
32078     Ext.apply(this, config);
32079     this.selections = new Ext.util.MixedCollection(false, function(o){
32080         return o.id;
32081     });
32082
32083     this.last = false;
32084     this.lastActive = false;
32085
32086     this.addEvents(
32087         
32088             "selectionchange",
32089         
32090             "beforerowselect",
32091         
32092             "rowselect",
32093         
32094             "rowdeselect"
32095     );
32096
32097     Ext.grid.RowSelectionModel.superclass.constructor.call(this);
32098 };
32099
32100 Ext.extend(Ext.grid.RowSelectionModel, Ext.grid.AbstractSelectionModel,  {
32101     
32102     singleSelect : false,
32103
32104         
32105         initEvents : function(){
32106
32107         if(!this.grid.enableDragDrop && !this.grid.enableDrag){
32108             this.grid.on("rowmousedown", this.handleMouseDown, this);
32109         }else{             this.grid.on("rowclick", function(grid, rowIndex, e) {
32110                 if(e.button === 0 && !e.shiftKey && !e.ctrlKey) {
32111                     this.selectRow(rowIndex, false);
32112                     grid.view.focusRow(rowIndex);
32113                 }
32114             }, this);
32115         }
32116
32117         this.rowNav = new Ext.KeyNav(this.grid.getGridEl(), {
32118             "up" : function(e){
32119                 if(!e.shiftKey){
32120                     this.selectPrevious(e.shiftKey);
32121                 }else if(this.last !== false && this.lastActive !== false){
32122                     var last = this.last;
32123                     this.selectRange(this.last,  this.lastActive-1);
32124                     this.grid.getView().focusRow(this.lastActive);
32125                     if(last !== false){
32126                         this.last = last;
32127                     }
32128                 }else{
32129                     this.selectFirstRow();
32130                 }
32131             },
32132             "down" : function(e){
32133                 if(!e.shiftKey){
32134                     this.selectNext(e.shiftKey);
32135                 }else if(this.last !== false && this.lastActive !== false){
32136                     var last = this.last;
32137                     this.selectRange(this.last,  this.lastActive+1);
32138                     this.grid.getView().focusRow(this.lastActive);
32139                     if(last !== false){
32140                         this.last = last;
32141                     }
32142                 }else{
32143                     this.selectFirstRow();
32144                 }
32145             },
32146             scope: this
32147         });
32148
32149         var view = this.grid.view;
32150         view.on("refresh", this.onRefresh, this);
32151         view.on("rowupdated", this.onRowUpdated, this);
32152         view.on("rowremoved", this.onRemove, this);
32153     },
32154
32155         onRefresh : function(){
32156         var ds = this.grid.store, index;
32157         var s = this.getSelections();
32158         this.clearSelections(true);
32159         for(var i = 0, len = s.length; i < len; i++){
32160             var r = s[i];
32161             if((index = ds.indexOfId(r.id)) != -1){
32162                 this.selectRow(index, true);
32163             }
32164         }
32165         if(s.length != this.selections.getCount()){
32166             this.fireEvent("selectionchange", this);
32167         }
32168     },
32169
32170         onRemove : function(v, index, r){
32171         if(this.selections.remove(r) !== false){
32172             this.fireEvent('selectionchange', this);
32173         }
32174     },
32175
32176         onRowUpdated : function(v, index, r){
32177         if(this.isSelected(r)){
32178             v.onRowSelect(index);
32179         }
32180     },
32181
32182     
32183     selectRecords : function(records, keepExisting){
32184         if(!keepExisting){
32185             this.clearSelections();
32186         }
32187         var ds = this.grid.store;
32188         for(var i = 0, len = records.length; i < len; i++){
32189             this.selectRow(ds.indexOf(records[i]), true);
32190         }
32191     },
32192
32193     
32194     getCount : function(){
32195         return this.selections.length;
32196     },
32197
32198     
32199     selectFirstRow : function(){
32200         this.selectRow(0);
32201     },
32202
32203     
32204     selectLastRow : function(keepExisting){
32205         this.selectRow(this.grid.store.getCount() - 1, keepExisting);
32206     },
32207
32208     
32209     selectNext : function(keepExisting){
32210         if(this.hasNext()){
32211             this.selectRow(this.last+1, keepExisting);
32212             this.grid.getView().focusRow(this.last);
32213                         return true;
32214         }
32215                 return false;
32216     },
32217
32218     
32219     selectPrevious : function(keepExisting){
32220         if(this.hasPrevious()){
32221             this.selectRow(this.last-1, keepExisting);
32222             this.grid.getView().focusRow(this.last);
32223                         return true;
32224         }
32225                 return false;
32226     },
32227
32228     
32229     hasNext : function(){
32230         return this.last !== false && (this.last+1) < this.grid.store.getCount();
32231     },
32232
32233     
32234     hasPrevious : function(){
32235         return !!this.last;
32236     },
32237
32238
32239     
32240     getSelections : function(){
32241         return [].concat(this.selections.items);
32242     },
32243
32244     
32245     getSelected : function(){
32246         return this.selections.itemAt(0);
32247     },
32248
32249     
32250     each : function(fn, scope){
32251         var s = this.getSelections();
32252         for(var i = 0, len = s.length; i < len; i++){
32253             if(fn.call(scope || this, s[i], i) === false){
32254                 return false;
32255             }
32256         }
32257         return true;
32258     },
32259
32260     
32261     clearSelections : function(fast){
32262         if(this.locked) return;
32263         if(fast !== true){
32264             var ds = this.grid.store;
32265             var s = this.selections;
32266             s.each(function(r){
32267                 this.deselectRow(ds.indexOfId(r.id));
32268             }, this);
32269             s.clear();
32270         }else{
32271             this.selections.clear();
32272         }
32273         this.last = false;
32274     },
32275
32276
32277     
32278     selectAll : function(){
32279         if(this.locked) return;
32280         this.selections.clear();
32281         for(var i = 0, len = this.grid.store.getCount(); i < len; i++){
32282             this.selectRow(i, true);
32283         }
32284     },
32285
32286     
32287     hasSelection : function(){
32288         return this.selections.length > 0;
32289     },
32290
32291     
32292     isSelected : function(index){
32293         var r = typeof index == "number" ? this.grid.store.getAt(index) : index;
32294         return (r && this.selections.key(r.id) ? true : false);
32295     },
32296
32297     
32298     isIdSelected : function(id){
32299         return (this.selections.key(id) ? true : false);
32300     },
32301
32302         handleMouseDown : function(g, rowIndex, e){
32303         if(e.button !== 0 || this.isLocked()){
32304             return;
32305         };
32306         var view = this.grid.getView();
32307         if(e.shiftKey && this.last !== false){
32308             var last = this.last;
32309             this.selectRange(last, rowIndex, e.ctrlKey);
32310             this.last = last;             view.focusRow(rowIndex);
32311         }else{
32312             var isSelected = this.isSelected(rowIndex);
32313             if(e.ctrlKey && isSelected){
32314                 this.deselectRow(rowIndex);
32315             }else if(!isSelected || this.getCount() > 1){
32316                 this.selectRow(rowIndex, e.ctrlKey || e.shiftKey);
32317                 view.focusRow(rowIndex);
32318             }
32319         }
32320     },
32321
32322     
32323     selectRows : function(rows, keepExisting){
32324         if(!keepExisting){
32325             this.clearSelections();
32326         }
32327         for(var i = 0, len = rows.length; i < len; i++){
32328             this.selectRow(rows[i], true);
32329         }
32330     },
32331
32332     
32333     selectRange : function(startRow, endRow, keepExisting){
32334         if(this.locked) return;
32335         if(!keepExisting){
32336             this.clearSelections();
32337         }
32338         if(startRow <= endRow){
32339             for(var i = startRow; i <= endRow; i++){
32340                 this.selectRow(i, true);
32341             }
32342         }else{
32343             for(var i = startRow; i >= endRow; i--){
32344                 this.selectRow(i, true);
32345             }
32346         }
32347     },
32348
32349     
32350     deselectRange : function(startRow, endRow, preventViewNotify){
32351         if(this.locked) return;
32352         for(var i = startRow; i <= endRow; i++){
32353             this.deselectRow(i, preventViewNotify);
32354         }
32355     },
32356
32357     
32358     selectRow : function(index, keepExisting, preventViewNotify){
32359         if(this.locked || (index < 0 || index >= this.grid.store.getCount())) return;
32360         var r = this.grid.store.getAt(index);
32361         if(r && this.fireEvent("beforerowselect", this, index, keepExisting, r) !== false){
32362             if(!keepExisting || this.singleSelect){
32363                 this.clearSelections();
32364             }
32365             this.selections.add(r);
32366             this.last = this.lastActive = index;
32367             if(!preventViewNotify){
32368                 this.grid.getView().onRowSelect(index);
32369             }
32370             this.fireEvent("rowselect", this, index, r);
32371             this.fireEvent("selectionchange", this);
32372         }
32373     },
32374
32375     
32376     deselectRow : function(index, preventViewNotify){
32377         if(this.locked) return;
32378         if(this.last == index){
32379             this.last = false;
32380         }
32381         if(this.lastActive == index){
32382             this.lastActive = false;
32383         }
32384         var r = this.grid.store.getAt(index);
32385         if(r){
32386             this.selections.remove(r);
32387             if(!preventViewNotify){
32388                 this.grid.getView().onRowDeselect(index);
32389             }
32390             this.fireEvent("rowdeselect", this, index, r);
32391             this.fireEvent("selectionchange", this);
32392         }
32393     },
32394
32395         restoreLast : function(){
32396         if(this._last){
32397             this.last = this._last;
32398         }
32399     },
32400
32401         acceptsNav : function(row, col, cm){
32402         return !cm.isHidden(col) && cm.isCellEditable(col, row);
32403     },
32404
32405         onEditorKey : function(field, e){
32406         var k = e.getKey(), newCell, g = this.grid, ed = g.activeEditor;
32407         var shift = e.shiftKey;
32408         if(k == e.TAB){
32409             e.stopEvent();
32410             ed.completeEdit();
32411             if(shift){
32412                 newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
32413             }else{
32414                 newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
32415             }
32416         }else if(k == e.ENTER){
32417             e.stopEvent();
32418             ed.completeEdit();
32419                         if(this.moveEditorOnEnter !== false){
32420                                 if(shift){
32421                                         newCell = g.walkCells(ed.row - 1, ed.col, -1, this.acceptsNav, this);
32422                                 }else{
32423                                         newCell = g.walkCells(ed.row + 1, ed.col, 1, this.acceptsNav, this);
32424                                 }
32425                         }
32426         }else if(k == e.ESC){
32427             ed.cancelEdit();
32428         }
32429         if(newCell){
32430             g.startEditing(newCell[0], newCell[1]);
32431         }
32432     }
32433 });
32434
32435 Ext.grid.CellSelectionModel = function(config){
32436     Ext.apply(this, config);
32437
32438     this.selection = null;
32439
32440     this.addEvents(
32441         
32442             "beforecellselect",
32443         
32444             "cellselect",
32445         
32446             "selectionchange"
32447     );
32448
32449     Ext.grid.CellSelectionModel.superclass.constructor.call(this);
32450 };
32451
32452 Ext.extend(Ext.grid.CellSelectionModel, Ext.grid.AbstractSelectionModel,  {
32453
32454     
32455     initEvents : function(){
32456         this.grid.on("cellmousedown", this.handleMouseDown, this);
32457         this.grid.getGridEl().on(Ext.isIE ? "keydown" : "keypress", this.handleKeyDown, this);
32458         var view = this.grid.view;
32459         view.on("refresh", this.onViewChange, this);
32460         view.on("rowupdated", this.onRowUpdated, this);
32461         view.on("beforerowremoved", this.clearSelections, this);
32462         view.on("beforerowsinserted", this.clearSelections, this);
32463         if(this.grid.isEditor){
32464             this.grid.on("beforeedit", this.beforeEdit,  this);
32465         }
32466     },
32467
32468             beforeEdit : function(e){
32469         this.select(e.row, e.column, false, true, e.record);
32470     },
32471
32472             onRowUpdated : function(v, index, r){
32473         if(this.selection && this.selection.record == r){
32474             v.onCellSelect(index, this.selection.cell[1]);
32475         }
32476     },
32477
32478             onViewChange : function(){
32479         this.clearSelections(true);
32480     },
32481
32482         
32483     getSelectedCell : function(){
32484         return this.selection ? this.selection.cell : null;
32485     },
32486
32487     
32488     clearSelections : function(preventNotify){
32489         var s = this.selection;
32490         if(s){
32491             if(preventNotify !== true){
32492                 this.grid.view.onCellDeselect(s.cell[0], s.cell[1]);
32493             }
32494             this.selection = null;
32495             this.fireEvent("selectionchange", this, null);
32496         }
32497     },
32498
32499     
32500     hasSelection : function(){
32501         return this.selection ? true : false;
32502     },
32503
32504     
32505     handleMouseDown : function(g, row, cell, e){
32506         if(e.button !== 0 || this.isLocked()){
32507             return;
32508         };
32509         this.select(row, cell);
32510     },
32511
32512     
32513     select : function(rowIndex, colIndex, preventViewNotify, preventFocus,  r){
32514         if(this.fireEvent("beforecellselect", this, rowIndex, colIndex) !== false){
32515             this.clearSelections();
32516             r = r || this.grid.store.getAt(rowIndex);
32517             this.selection = {
32518                 record : r,
32519                 cell : [rowIndex, colIndex]
32520             };
32521             if(!preventViewNotify){
32522                 var v = this.grid.getView();
32523                 v.onCellSelect(rowIndex, colIndex);
32524                 if(preventFocus !== true){
32525                     v.focusCell(rowIndex, colIndex);
32526                 }
32527             }
32528             this.fireEvent("cellselect", this, rowIndex, colIndex);
32529             this.fireEvent("selectionchange", this, this.selection);
32530         }
32531     },
32532
32533             isSelectable : function(rowIndex, colIndex, cm){
32534         return !cm.isHidden(colIndex);
32535     },
32536
32537     
32538     handleKeyDown : function(e){
32539         if(!e.isNavKeyPress()){
32540             return;
32541         }
32542         var g = this.grid, s = this.selection;
32543         if(!s){
32544             e.stopEvent();
32545             var cell = g.walkCells(0, 0, 1, this.isSelectable,  this);
32546             if(cell){
32547                 this.select(cell[0], cell[1]);
32548             }
32549             return;
32550         }
32551         var sm = this;
32552         var walk = function(row, col, step){
32553             return g.walkCells(row, col, step, sm.isSelectable,  sm);
32554         };
32555         var k = e.getKey(), r = s.cell[0], c = s.cell[1];
32556         var newCell;
32557
32558         switch(k){
32559              case e.TAB:
32560                  if(e.shiftKey){
32561                      newCell = walk(r, c-1, -1);
32562                  }else{
32563                      newCell = walk(r, c+1, 1);
32564                  }
32565              break;
32566              case e.DOWN:
32567                  newCell = walk(r+1, c, 1);
32568              break;
32569              case e.UP:
32570                  newCell = walk(r-1, c, -1);
32571              break;
32572              case e.RIGHT:
32573                  newCell = walk(r, c+1, 1);
32574              break;
32575              case e.LEFT:
32576                  newCell = walk(r, c-1, -1);
32577              break;
32578              case e.ENTER:
32579                  if(g.isEditor && !g.editing){
32580                     g.startEditing(r, c);
32581                     e.stopEvent();
32582                     return;
32583                 }
32584              break;
32585         };
32586         if(newCell){
32587             this.select(newCell[0], newCell[1]);
32588             e.stopEvent();
32589         }
32590     },
32591
32592     acceptsNav : function(row, col, cm){
32593         return !cm.isHidden(col) && cm.isCellEditable(col, row);
32594     },
32595
32596     onEditorKey : function(field, e){
32597         var k = e.getKey(), newCell, g = this.grid, ed = g.activeEditor;
32598         if(k == e.TAB){
32599             if(e.shiftKey){
32600                 newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
32601             }else{
32602                 newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
32603             }
32604             e.stopEvent();
32605         }else if(k == e.ENTER){
32606             ed.completeEdit();
32607             e.stopEvent();
32608         }else if(k == e.ESC){
32609                 e.stopEvent();
32610             ed.cancelEdit();
32611         }
32612         if(newCell){
32613             g.startEditing(newCell[0], newCell[1]);
32614         }
32615     }
32616 });
32617
32618 Ext.grid.EditorGridPanel = Ext.extend(Ext.grid.GridPanel, {
32619     
32620     clicksToEdit: 2,
32621
32622     
32623     isEditor : true,
32624     
32625     detectEdit: false,
32626
32627         
32628         autoEncode : false,
32629
32630         
32631     
32632     trackMouseOver: false, 
32633     
32634     
32635     initComponent : function(){
32636         Ext.grid.EditorGridPanel.superclass.initComponent.call(this);
32637
32638         if(!this.selModel){
32639             this.selModel = new Ext.grid.CellSelectionModel();
32640         }
32641
32642         this.activeEditor = null;
32643
32644             this.addEvents(
32645             
32646             "beforeedit",
32647             
32648             "afteredit",
32649             
32650             "validateedit"
32651         );
32652     },
32653
32654     
32655     initEvents : function(){
32656         Ext.grid.EditorGridPanel.superclass.initEvents.call(this);
32657         
32658         this.on("bodyscroll", this.stopEditing, this, [true]);
32659
32660         if(this.clicksToEdit == 1){
32661             this.on("cellclick", this.onCellDblClick, this);
32662         }else {
32663             if(this.clicksToEdit == 'auto' && this.view.mainBody){
32664                 this.view.mainBody.on("mousedown", this.onAutoEditClick, this);
32665             }
32666             this.on("celldblclick", this.onCellDblClick, this);
32667         }
32668         this.getGridEl().addClass("xedit-grid");
32669     },
32670
32671     
32672     onCellDblClick : function(g, row, col){
32673         this.startEditing(row, col);
32674     },
32675
32676     
32677     onAutoEditClick : function(e, t){
32678         if(e.button !== 0){
32679             return;
32680         }
32681         var row = this.view.findRowIndex(t);
32682         var col = this.view.findCellIndex(t);
32683         if(row !== false && col !== false){
32684             this.stopEditing();
32685             if(this.selModel.getSelectedCell){ 
32686                 var sc = this.selModel.getSelectedCell();
32687                 if(sc && sc.cell[0] === row && sc.cell[1] === col){
32688                     this.startEditing(row, col);
32689                 }
32690             }else{
32691                 if(this.selModel.isSelected(row)){
32692                     this.startEditing(row, col);
32693                 }
32694             }
32695         }
32696     },
32697
32698     
32699     onEditComplete : function(ed, value, startValue){
32700         this.editing = false;
32701         this.activeEditor = null;
32702         ed.un("specialkey", this.selModel.onEditorKey, this.selModel);
32703                 var r = ed.record;
32704         var field = this.colModel.getDataIndex(ed.col);
32705         value = this.postEditValue(value, startValue, r, field);
32706         if(String(value) !== String(startValue)){
32707             var e = {
32708                 grid: this,
32709                 record: r,
32710                 field: field,
32711                 originalValue: startValue,
32712                 value: value,
32713                 row: ed.row,
32714                 column: ed.col,
32715                 cancel:false
32716             };
32717             if(this.fireEvent("validateedit", e) !== false && !e.cancel){
32718                 r.set(field, e.value);
32719                 delete e.cancel;
32720                 this.fireEvent("afteredit", e);
32721             }
32722         }
32723         this.view.focusCell(ed.row, ed.col);
32724     },
32725
32726     
32727     startEditing : function(row, col){
32728         this.stopEditing();
32729         if(this.colModel.isCellEditable(col, row)){
32730             this.view.ensureVisible(row, col, true);
32731             var r = this.store.getAt(row);
32732             var field = this.colModel.getDataIndex(col);
32733             var e = {
32734                 grid: this,
32735                 record: r,
32736                 field: field,
32737                 value: r.data[field],
32738                 row: row,
32739                 column: col,
32740                 cancel:false
32741             };
32742             if(this.fireEvent("beforeedit", e) !== false && !e.cancel){
32743                 this.editing = true;
32744                 var ed = this.colModel.getCellEditor(col, row);
32745                 if(!ed.rendered){
32746                     ed.render(this.view.getEditorParent(ed));
32747                 }
32748                 (function(){ 
32749                     ed.row = row;
32750                     ed.col = col;
32751                     ed.record = r;
32752                     ed.on("complete", this.onEditComplete, this, {single: true});
32753                     ed.on("specialkey", this.selModel.onEditorKey, this.selModel);
32754                     this.activeEditor = ed;
32755                     var v = this.preEditValue(r, field);
32756                     ed.startEdit(this.view.getCell(row, col), v);
32757                 }).defer(50, this);
32758             }
32759         }
32760     },
32761     
32762         preEditValue : function(r, field){
32763                 return this.autoEncode && typeof value == 'string' ? Ext.util.Format.htmlDecode(r.data[field]) : r.data[field];
32764         },
32765         
32766         postEditValue : function(value, originalValue, r, field){
32767                 return this.autoEncode && typeof value == 'string' ? Ext.util.Format.htmlEncode(value) : value;
32768         },
32769             
32770     
32771     stopEditing : function(cancel){
32772         if(this.activeEditor){
32773             this.activeEditor[cancel === true ? 'cancelEdit' : 'completeEdit']();
32774         }
32775         this.activeEditor = null;
32776     }
32777 });
32778 Ext.reg('editorgrid', Ext.grid.EditorGridPanel);
32779 Ext.grid.GridEditor = function(field, config){
32780     Ext.grid.GridEditor.superclass.constructor.call(this, field, config);
32781     field.monitorTab = false;
32782 };
32783
32784 Ext.extend(Ext.grid.GridEditor, Ext.Editor, {
32785     alignment: "tl-tl",
32786     autoSize: "width",
32787     hideEl : false,
32788     cls: "x-small-editor x-grid-editor",
32789     shim:false,
32790     shadow:false
32791 });
32792
32793 Ext.grid.PropertyRecord = Ext.data.Record.create([
32794     {name:'name',type:'string'}, 'value'
32795 ]);
32796
32797
32798 Ext.grid.PropertyStore = function(grid, source){
32799     this.grid = grid;
32800     this.store = new Ext.data.Store({
32801         recordType : Ext.grid.PropertyRecord
32802     });
32803     this.store.on('update', this.onUpdate,  this);
32804     if(source){
32805         this.setSource(source);
32806     }
32807     Ext.grid.PropertyStore.superclass.constructor.call(this);
32808 };
32809 Ext.extend(Ext.grid.PropertyStore, Ext.util.Observable, {
32810         setSource : function(o){
32811         this.source = o;
32812         this.store.removeAll();
32813         var data = [];
32814         for(var k in o){
32815             if(this.isEditableValue(o[k])){
32816                 data.push(new Ext.grid.PropertyRecord({name: k, value: o[k]}, k));
32817             }
32818         }
32819         this.store.loadRecords({records: data}, {}, true);
32820     },
32821
32822         onUpdate : function(ds, record, type){
32823         if(type == Ext.data.Record.EDIT){
32824             var v = record.data['value'];
32825             var oldValue = record.modified['value'];
32826             if(this.grid.fireEvent('beforepropertychange', this.source, record.id, v, oldValue) !== false){
32827                 this.source[record.id] = v;
32828                 record.commit();
32829                 this.grid.fireEvent('propertychange', this.source, record.id, v, oldValue);
32830             }else{
32831                 record.reject();
32832             }
32833         }
32834     },
32835
32836         getProperty : function(row){
32837        return this.store.getAt(row);
32838     },
32839
32840         isEditableValue: function(val){
32841         if(Ext.isDate(val)){
32842             return true;
32843         }else if(typeof val == 'object' || typeof val == 'function'){
32844             return false;
32845         }
32846         return true;
32847     },
32848
32849         setValue : function(prop, value){
32850         this.source[prop] = value;
32851         this.store.getById(prop).set('value', value);
32852     },
32853
32854         getSource : function(){
32855         return this.source;
32856     }
32857 });
32858
32859
32860 Ext.grid.PropertyColumnModel = function(grid, store){
32861     this.grid = grid;
32862     var g = Ext.grid;
32863     g.PropertyColumnModel.superclass.constructor.call(this, [
32864         {header: this.nameText, width:50, sortable: true, dataIndex:'name', id: 'name', menuDisabled:true},
32865         {header: this.valueText, width:50, resizable:false, dataIndex: 'value', id: 'value', menuDisabled:true}
32866     ]);
32867     this.store = store;
32868     this.bselect = Ext.DomHelper.append(document.body, {
32869         tag: 'select', cls: 'x-grid-editor x-hide-display', children: [
32870             {tag: 'option', value: 'true', html: 'true'},
32871             {tag: 'option', value: 'false', html: 'false'}
32872         ]
32873     });
32874     var f = Ext.form;
32875
32876     var bfield = new f.Field({
32877         el:this.bselect,
32878         bselect : this.bselect,
32879         autoShow: true,
32880         getValue : function(){
32881             return this.bselect.value == 'true';
32882         }
32883     });
32884     this.editors = {
32885         'date' : new g.GridEditor(new f.DateField({selectOnFocus:true})),
32886         'string' : new g.GridEditor(new f.TextField({selectOnFocus:true})),
32887         'number' : new g.GridEditor(new f.NumberField({selectOnFocus:true, style:'text-align:left;'})),
32888         'boolean' : new g.GridEditor(bfield)
32889     };
32890     this.renderCellDelegate = this.renderCell.createDelegate(this);
32891     this.renderPropDelegate = this.renderProp.createDelegate(this);
32892 };
32893
32894 Ext.extend(Ext.grid.PropertyColumnModel, Ext.grid.ColumnModel, {
32895         nameText : 'Name',
32896     valueText : 'Value',
32897     dateFormat : 'm/j/Y',
32898
32899         renderDate : function(dateVal){
32900         return dateVal.dateFormat(this.dateFormat);
32901     },
32902
32903         renderBool : function(bVal){
32904         return bVal ? 'true' : 'false';
32905     },
32906
32907         isCellEditable : function(colIndex, rowIndex){
32908         return colIndex == 1;
32909     },
32910
32911         getRenderer : function(col){
32912         return col == 1 ?
32913             this.renderCellDelegate : this.renderPropDelegate;
32914     },
32915
32916         renderProp : function(v){
32917         return this.getPropertyName(v);
32918     },
32919
32920         renderCell : function(val){
32921         var rv = val;
32922         if(Ext.isDate(val)){
32923             rv = this.renderDate(val);
32924         }else if(typeof val == 'boolean'){
32925             rv = this.renderBool(val);
32926         }
32927         return Ext.util.Format.htmlEncode(rv);
32928     },
32929
32930         getPropertyName : function(name){
32931         var pn = this.grid.propertyNames;
32932         return pn && pn[name] ? pn[name] : name;
32933     },
32934
32935         getCellEditor : function(colIndex, rowIndex){
32936         var p = this.store.getProperty(rowIndex);
32937         var n = p.data['name'], val = p.data['value'];
32938         if(this.grid.customEditors[n]){
32939             return this.grid.customEditors[n];
32940         }
32941         if(Ext.isDate(val)){
32942             return this.editors['date'];
32943         }else if(typeof val == 'number'){
32944             return this.editors['number'];
32945         }else if(typeof val == 'boolean'){
32946             return this.editors['boolean'];
32947         }else{
32948             return this.editors['string'];
32949         }
32950     }
32951 });
32952
32953
32954 Ext.grid.PropertyGrid = Ext.extend(Ext.grid.EditorGridPanel, {
32955     
32956     
32957
32958         enableColumnMove:false,
32959     stripeRows:false,
32960     trackMouseOver: false,
32961     clicksToEdit:1,
32962     enableHdMenu : false,
32963     viewConfig : {
32964         forceFit:true
32965     },
32966
32967         initComponent : function(){
32968         this.customEditors = this.customEditors || {};
32969         this.lastEditRow = null;
32970         var store = new Ext.grid.PropertyStore(this);
32971         this.propStore = store;
32972         var cm = new Ext.grid.PropertyColumnModel(this, store);
32973         store.store.sort('name', 'ASC');
32974         this.addEvents(
32975             
32976             'beforepropertychange',
32977             
32978             'propertychange'
32979         );
32980         this.cm = cm;
32981         this.ds = store.store;
32982         Ext.grid.PropertyGrid.superclass.initComponent.call(this);
32983
32984         this.selModel.on('beforecellselect', function(sm, rowIndex, colIndex){
32985             if(colIndex === 0){
32986                 this.startEditing.defer(200, this, [rowIndex, 1]);
32987                 return false;
32988             }
32989         }, this);
32990     },
32991
32992         onRender : function(){
32993         Ext.grid.PropertyGrid.superclass.onRender.apply(this, arguments);
32994
32995         this.getGridEl().addClass('x-props-grid');
32996     },
32997
32998         afterRender: function(){
32999         Ext.grid.PropertyGrid.superclass.afterRender.apply(this, arguments);
33000         if(this.source){
33001             this.setSource(this.source);
33002         }
33003     },
33004
33005     
33006     setSource : function(source){
33007         this.propStore.setSource(source);
33008     },
33009
33010     
33011     getSource : function(){
33012         return this.propStore.getSource();
33013     }
33014 });
33015
33016 Ext.grid.RowNumberer = function(config){
33017     Ext.apply(this, config);
33018     if(this.rowspan){
33019         this.renderer = this.renderer.createDelegate(this);
33020     }
33021 };
33022
33023 Ext.grid.RowNumberer.prototype = {
33024     
33025     header: "",
33026     
33027     width: 23,
33028     
33029     sortable: false,
33030
33031     
33032     fixed:true,
33033     menuDisabled:true,
33034     dataIndex: '',
33035     id: 'numberer',
33036     rowspan: undefined,
33037
33038     
33039     renderer : function(v, p, record, rowIndex){
33040         if(this.rowspan){
33041             p.cellAttr = 'rowspan="'+this.rowspan+'"';
33042         }
33043         return rowIndex+1;
33044     }
33045 };
33046
33047 Ext.grid.CheckboxSelectionModel = Ext.extend(Ext.grid.RowSelectionModel, {
33048     
33049     header: '<div class="x-grid3-hd-checker">&#160;</div>',
33050     
33051     width: 20,
33052     
33053     sortable: false,
33054
33055     
33056     menuDisabled:true,
33057     fixed:true,
33058     dataIndex: '',
33059     id: 'checker',
33060
33061     
33062     initEvents : function(){
33063         Ext.grid.CheckboxSelectionModel.superclass.initEvents.call(this);
33064         this.grid.on('render', function(){
33065             var view = this.grid.getView();
33066             view.mainBody.on('mousedown', this.onMouseDown, this);
33067             Ext.fly(view.innerHd).on('mousedown', this.onHdMouseDown, this);
33068
33069         }, this);
33070     },
33071
33072     
33073     onMouseDown : function(e, t){
33074         if(e.button === 0 && t.className == 'x-grid3-row-checker'){ 
33075             e.stopEvent();
33076             var row = e.getTarget('.x-grid3-row');
33077             if(row){
33078                 var index = row.rowIndex;
33079                 if(this.isSelected(index)){
33080                     this.deselectRow(index);
33081                 }else{
33082                     this.selectRow(index, true);
33083                 }
33084             }
33085         }
33086     },
33087
33088     
33089     onHdMouseDown : function(e, t){
33090         if(t.className == 'x-grid3-hd-checker'){
33091             e.stopEvent();
33092             var hd = Ext.fly(t.parentNode);
33093             var isChecked = hd.hasClass('x-grid3-hd-checker-on');
33094             if(isChecked){
33095                 hd.removeClass('x-grid3-hd-checker-on');
33096                 this.clearSelections();
33097             }else{
33098                 hd.addClass('x-grid3-hd-checker-on');
33099                 this.selectAll();
33100             }
33101         }
33102     },
33103
33104     
33105     renderer : function(v, p, record){
33106         return '<div class="x-grid3-row-checker">&#160;</div>';
33107     }
33108 });
33109
33110 Ext.LoadMask = function(el, config){
33111     this.el = Ext.get(el);
33112     Ext.apply(this, config);
33113     if(this.store){
33114         this.store.on('beforeload', this.onBeforeLoad, this);
33115         this.store.on('load', this.onLoad, this);
33116         this.store.on('loadexception', this.onLoad, this);
33117         this.removeMask = Ext.value(this.removeMask, false);
33118     }else{
33119         var um = this.el.getUpdater();
33120         um.showLoadIndicator = false;         um.on('beforeupdate', this.onBeforeLoad, this);
33121         um.on('update', this.onLoad, this);
33122         um.on('failure', this.onLoad, this);
33123         this.removeMask = Ext.value(this.removeMask, true);
33124     }
33125 };
33126
33127 Ext.LoadMask.prototype = {
33128     
33129     
33130     
33131     msg : 'Loading...',
33132     
33133     msgCls : 'x-mask-loading',
33134
33135     
33136     disabled: false,
33137
33138     
33139     disable : function(){
33140        this.disabled = true;
33141     },
33142
33143     
33144     enable : function(){
33145         this.disabled = false;
33146     },
33147
33148         onLoad : function(){
33149         this.el.unmask(this.removeMask);
33150     },
33151
33152         onBeforeLoad : function(){
33153         if(!this.disabled){
33154             this.el.mask(this.msg, this.msgCls);
33155         }
33156     },
33157
33158     
33159     show: function(){
33160         this.onBeforeLoad();
33161     },
33162
33163     
33164     hide: function(){
33165         this.onLoad();    
33166     },
33167
33168         destroy : function(){
33169         if(this.store){
33170             this.store.un('beforeload', this.onBeforeLoad, this);
33171             this.store.un('load', this.onLoad, this);
33172             this.store.un('loadexception', this.onLoad, this);
33173         }else{
33174             var um = this.el.getUpdater();
33175             um.un('beforeupdate', this.onBeforeLoad, this);
33176             um.un('update', this.onLoad, this);
33177             um.un('failure', this.onLoad, this);
33178         }
33179     }
33180 };
33181
33182 Ext.ProgressBar = Ext.extend(Ext.BoxComponent, {
33183    
33184     baseCls : 'x-progress',
33185
33186     
33187     waitTimer : null,
33188
33189     
33190     initComponent : function(){
33191         Ext.ProgressBar.superclass.initComponent.call(this);
33192         this.addEvents(
33193             
33194             "update"
33195         );
33196     },
33197
33198     
33199     onRender : function(ct, position){
33200         Ext.ProgressBar.superclass.onRender.call(this, ct, position);
33201
33202         var tpl = new Ext.Template(
33203             '<div class="{cls}-wrap">',
33204                 '<div class="{cls}-inner">',
33205                     '<div class="{cls}-bar">',
33206                         '<div class="{cls}-text">',
33207                             '<div>&#160;</div>',
33208                         '</div>',
33209                     '</div>',
33210                     '<div class="{cls}-text {cls}-text-back">',
33211                         '<div>&#160;</div>',
33212                     '</div>',
33213                 '</div>',
33214             '</div>'
33215         );
33216
33217         if(position){
33218             this.el = tpl.insertBefore(position, {cls: this.baseCls}, true);
33219         }else{
33220             this.el = tpl.append(ct, {cls: this.baseCls}, true);
33221         }
33222         if(this.id){
33223             this.el.dom.id = this.id;
33224         }
33225         var inner = this.el.dom.firstChild;
33226         this.progressBar = Ext.get(inner.firstChild);
33227
33228         if(this.textEl){
33229             
33230             this.textEl = Ext.get(this.textEl);
33231             delete this.textTopEl;
33232         }else{
33233             
33234             this.textTopEl = Ext.get(this.progressBar.dom.firstChild);
33235             var textBackEl = Ext.get(inner.childNodes[1]);
33236             this.textTopEl.setStyle("z-index", 99).addClass('x-hidden');
33237             this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, textBackEl.dom.firstChild]);
33238             this.textEl.setWidth(inner.offsetWidth);
33239         }
33240         if(this.value){
33241             this.updateProgress(this.value, this.text);
33242         }else{
33243             this.updateText(this.text);
33244         }
33245         this.setSize(this.width || 'auto', 'auto');
33246         this.progressBar.setHeight(inner.offsetHeight);
33247     },
33248
33249     
33250     updateProgress : function(value, text){
33251         this.value = value || 0;
33252         if(text){
33253             this.updateText(text);
33254         }
33255         var w = Math.floor(value*this.el.dom.firstChild.offsetWidth);
33256         this.progressBar.setWidth(w);
33257         if(this.textTopEl){
33258             
33259             this.textTopEl.removeClass('x-hidden').setWidth(w);
33260         }
33261         this.fireEvent('update', this, value, text);
33262         return this;
33263     },
33264
33265     
33266     wait : function(o){
33267         if(!this.waitTimer){
33268             var scope = this;
33269             o = o || {};
33270             this.waitTimer = Ext.TaskMgr.start({
33271                 run: function(i){
33272                     var inc = o.increment || 10;
33273                     this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*.01);
33274                 },
33275                 interval: o.interval || 1000,
33276                 duration: o.duration,
33277                 onStop: function(){
33278                     if(o.fn){
33279                         o.fn.apply(o.scope || this);
33280                     }
33281                     this.reset();
33282                 },
33283                 scope: scope
33284             });
33285         }
33286         return this;
33287     },
33288
33289     
33290     isWaiting : function(){
33291         return this.waitTimer != null;
33292     },
33293
33294     
33295     updateText : function(text){
33296         this.text = text || '&#160;';
33297         this.textEl.update(this.text);
33298         return this;
33299     },
33300
33301     
33302     setSize : function(w, h){
33303         Ext.ProgressBar.superclass.setSize.call(this, w, h);
33304         if(this.textTopEl){
33305             var inner = this.el.dom.firstChild;
33306             this.textEl.setSize(inner.offsetWidth, inner.offsetHeight);
33307         }
33308         return this;
33309     },
33310
33311     
33312     reset : function(hide){
33313         this.updateProgress(0);
33314         if(this.textTopEl){
33315             this.textTopEl.addClass('x-hidden');
33316         }
33317         if(this.waitTimer){
33318             this.waitTimer.onStop = null; 
33319             Ext.TaskMgr.stop(this.waitTimer);
33320             this.waitTimer = null;
33321         }
33322         if(hide === true){
33323             this.hide();
33324         }
33325         return this;
33326     }
33327 });
33328 Ext.reg('progress', Ext.ProgressBar);
33329 Ext.debug = {};
33330
33331 (function(){
33332
33333 var cp;
33334
33335 function createConsole(){
33336
33337     var scriptPanel = new Ext.debug.ScriptsPanel();
33338     var logView = new Ext.debug.LogPanel();
33339     var tree = new Ext.debug.DomTree();
33340
33341     var tabs = new Ext.TabPanel({
33342         activeTab: 0,
33343         border: false,
33344         tabPosition: 'bottom',
33345         items: [{
33346             title: 'Debug Console',
33347             layout:'border',
33348             items: [logView, scriptPanel]
33349         },{
33350             title: 'DOM Inspector',
33351             layout:'border',
33352             items: [tree]
33353         }]
33354     });
33355
33356     cp = new Ext.Panel({
33357         id: 'x-debug-browser',
33358         title: 'Console',
33359         collapsible: true,
33360         animCollapse: false,
33361         style: 'position:absolute;left:0;bottom:0;',
33362         height:200,
33363         logView: logView,
33364         layout: 'fit',
33365         
33366         tools:[{
33367             id: 'close',
33368             handler: function(){
33369                 cp.destroy();
33370                 cp = null;
33371                 Ext.EventManager.removeResizeListener(handleResize);
33372             }
33373         }],
33374
33375         items: tabs
33376     });
33377
33378     cp.render(document.body);
33379
33380     cp.resizer = new Ext.Resizable(cp.el, {
33381         minHeight:50,
33382         handles: "n",
33383         pinned: true,
33384         transparent:true,
33385         resizeElement : function(){
33386             var box = this.proxy.getBox();
33387             this.proxy.hide();
33388             cp.setHeight(box.height);
33389             return box;
33390         }
33391     });
33392
33393     function handleResize(){
33394         cp.setWidth(Ext.getBody().getViewSize().width);
33395     }
33396     Ext.EventManager.onWindowResize(handleResize);
33397
33398     handleResize();
33399 }
33400
33401
33402 Ext.apply(Ext, {
33403     log : function(){
33404         if(!cp){
33405             createConsole();
33406         }
33407         cp.logView.log.apply(cp.logView, arguments);
33408     },
33409
33410     logf : function(format, arg1, arg2, etc){
33411         Ext.log(String.format.apply(String, arguments));
33412     },
33413
33414     dump : function(o){
33415         if(typeof o == 'string' || typeof o == 'number' || typeof o == 'undefined' || Ext.isDate(o)){
33416             Ext.log(o);
33417         }else if(!o){
33418             Ext.log("null");
33419         }else if(typeof o != "object"){
33420             Ext.log('Unknown return type');
33421         }else if(Ext.isArray(o)){
33422             Ext.log('['+o.join(',')+']');
33423         }else{
33424             var b = ["{\n"];
33425             for(var key in o){
33426                 var to = typeof o[key];
33427                 if(to != "function" && to != "object"){
33428                     b.push(String.format("  {0}: {1},\n", key, o[key]));
33429                 }
33430             }
33431             var s = b.join("");
33432             if(s.length > 3){
33433                 s = s.substr(0, s.length-2);
33434             }
33435             Ext.log(s + "\n}");
33436         }
33437     },
33438
33439     _timers : {},
33440
33441     time : function(name){
33442         name = name || "def";
33443         Ext._timers[name] = new Date().getTime();
33444     },
33445
33446     timeEnd : function(name, printResults){
33447         var t = new Date().getTime();
33448         name = name || "def";
33449         var v = String.format("{0} ms", t-Ext._timers[name]);
33450         Ext._timers[name] = new Date().getTime();
33451         if(printResults !== false){
33452             Ext.log('Timer ' + (name == "def" ? v : name + ": " + v));
33453         }
33454         return v;
33455     }
33456 });
33457
33458 })();
33459
33460
33461 Ext.debug.ScriptsPanel = Ext.extend(Ext.Panel, {
33462     id:'x-debug-scripts',
33463     region: 'east',
33464     minWidth: 200,
33465     split: true,
33466     width: 350,
33467     border: false,
33468     layout:'anchor',
33469     style:'border-width:0 0 0 1px;',
33470
33471     initComponent : function(){
33472
33473         this.scriptField = new Ext.form.TextArea({
33474             anchor: '100% -26',
33475             style:'border-width:0;'
33476         });
33477
33478         this.trapBox = new Ext.form.Checkbox({
33479             id: 'console-trap',
33480             boxLabel: 'Trap Errors',
33481             checked: true
33482         });
33483
33484         this.toolbar = new Ext.Toolbar([{
33485                 text: 'Run',
33486                 scope: this,
33487                 handler: this.evalScript
33488             },{
33489                 text: 'Clear',
33490                 scope: this,
33491                 handler: this.clear
33492             },
33493             '->',
33494             this.trapBox,
33495             ' ', ' '
33496         ]);
33497
33498         this.items = [this.toolbar, this.scriptField];
33499
33500         Ext.debug.ScriptsPanel.superclass.initComponent.call(this);
33501     },
33502
33503     evalScript : function(){
33504         var s = this.scriptField.getValue();
33505         if(this.trapBox.getValue()){
33506             try{
33507                 var rt = eval(s);
33508                 Ext.dump(rt === undefined? '(no return)' : rt);
33509             }catch(e){
33510                 Ext.log(e.message || e.descript);
33511             }
33512         }else{
33513             var rt = eval(s);
33514             Ext.dump(rt === undefined? '(no return)' : rt);
33515         }
33516     },
33517
33518     clear : function(){
33519         this.scriptField.setValue('');
33520         this.scriptField.focus();
33521     }
33522
33523 });
33524
33525 Ext.debug.LogPanel = Ext.extend(Ext.Panel, {
33526     autoScroll: true,
33527     region: 'center',
33528     border: false,
33529     style:'border-width:0 1px 0 0',
33530
33531     log : function(){
33532         var markup = [  '<div style="padding:5px !important;border-bottom:1px solid #ccc;">',
33533                     Ext.util.Format.htmlEncode(Array.prototype.join.call(arguments, ', ')).replace(/\n/g, '<br />').replace(/\s/g, '&#160;'),
33534                     '</div>'].join('');
33535
33536         this.body.insertHtml('beforeend', markup);
33537         this.body.scrollTo('top', 100000);
33538     },
33539
33540     clear : function(){
33541         this.body.update('');
33542         this.body.dom.scrollTop = 0;
33543     }
33544 });
33545
33546 Ext.debug.DomTree = Ext.extend(Ext.tree.TreePanel, {
33547     enableDD:false ,
33548     lines:false,
33549     rootVisible:false,
33550     animate:false,
33551     hlColor:'ffff9c',
33552     autoScroll: true,
33553     region:'center',
33554     border:false,
33555
33556     initComponent : function(){
33557
33558
33559         Ext.debug.DomTree.superclass.initComponent.call(this);
33560         
33561                 var styles = false, hnode;
33562         var nonSpace = /^\s*$/;
33563         var html = Ext.util.Format.htmlEncode;
33564         var ellipsis = Ext.util.Format.ellipsis;
33565         var styleRe = /\s?([a-z\-]*)\:([^;]*)(?:[;\s\n\r]*)/gi;
33566
33567         function findNode(n){
33568             if(!n || n.nodeType != 1 || n == document.body || n == document){
33569                 return false;
33570             }
33571             var pn = [n], p = n;
33572             while((p = p.parentNode) && p.nodeType == 1 && p.tagName.toUpperCase() != 'HTML'){
33573                 pn.unshift(p);
33574             }
33575             var cn = hnode;
33576             for(var i = 0, len = pn.length; i < len; i++){
33577                 cn.expand();
33578                 cn = cn.findChild('htmlNode', pn[i]);
33579                 if(!cn){                     return false;
33580                 }
33581             }
33582             cn.select();
33583             var a = cn.ui.anchor;
33584             treeEl.dom.scrollTop = Math.max(0 ,a.offsetTop-10);
33585                         cn.highlight();
33586             return true;
33587         }
33588
33589         function nodeTitle(n){
33590             var s = n.tagName;
33591             if(n.id){
33592                 s += '#'+n.id;
33593             }else if(n.className){
33594                 s += '.'+n.className;
33595             }
33596             return s;
33597         }
33598
33599         function onNodeSelect(t, n, last){
33600             return;
33601             if(last && last.unframe){
33602                 last.unframe();
33603             }
33604             var props = {};
33605             if(n && n.htmlNode){
33606                 if(frameEl.pressed){
33607                     n.frame();
33608                 }
33609                 if(inspecting){
33610                     return;
33611                 }
33612                 addStyle.enable();
33613                 reload.setDisabled(n.leaf);
33614                 var dom = n.htmlNode;
33615                 stylePanel.setTitle(nodeTitle(dom));
33616                 if(styles && !showAll.pressed){
33617                     var s = dom.style ? dom.style.cssText : '';
33618                     if(s){
33619                         var m;
33620                         while ((m = styleRe.exec(s)) != null){
33621                             props[m[1].toLowerCase()] = m[2];
33622                         }
33623                     }
33624                 }else if(styles){
33625                     var cl = Ext.debug.cssList;
33626                     var s = dom.style, fly = Ext.fly(dom);
33627                     if(s){
33628                         for(var i = 0, len = cl.length; i<len; i++){
33629                             var st = cl[i];
33630                             var v = s[st] || fly.getStyle(st);
33631                             if(v != undefined && v !== null && v !== ''){
33632                                 props[st] = v;
33633                             }
33634                         }
33635                     }
33636                 }else{
33637                     for(var a in dom){
33638                         var v = dom[a];
33639                         if((isNaN(a+10)) && v != undefined && v !== null && v !== '' && !(Ext.isGecko && a[0] == a[0].toUpperCase())){
33640                             props[a] = v;
33641                         }
33642                     }
33643                 }
33644             }else{
33645                 if(inspecting){
33646                     return;
33647                 }
33648                 addStyle.disable();
33649                 reload.disabled();
33650             }
33651             stylesGrid.setSource(props);
33652             stylesGrid.treeNode = n;
33653             stylesGrid.view.fitColumns();
33654         }
33655
33656         this.loader = new Ext.tree.TreeLoader();
33657         this.loader.load = function(n, cb){
33658             var isBody = n.htmlNode == document.body;
33659             var cn = n.htmlNode.childNodes;
33660             for(var i = 0, c; c = cn[i]; i++){
33661                 if(isBody && c.id == 'x-debug-browser'){
33662                     continue;
33663                 }
33664                 if(c.nodeType == 1){
33665                     n.appendChild(new Ext.debug.HtmlNode(c));
33666                 }else if(c.nodeType == 3 && !nonSpace.test(c.nodeValue)){
33667                     n.appendChild(new Ext.tree.TreeNode({
33668                         text:'<em>' + ellipsis(html(String(c.nodeValue)), 35) + '</em>',
33669                         cls: 'x-tree-noicon'
33670                     }));
33671                 }
33672             }
33673             cb();
33674         };
33675
33676         
33677         this.root = this.setRootNode(new Ext.tree.TreeNode('Ext'));
33678
33679         hnode = this.root.appendChild(new Ext.debug.HtmlNode(
33680                 document.getElementsByTagName('html')[0]
33681         ));
33682
33683     }
33684 });
33685
33686
33687 Ext.debug.HtmlNode = function(){
33688     var html = Ext.util.Format.htmlEncode;
33689     var ellipsis = Ext.util.Format.ellipsis;
33690     var nonSpace = /^\s*$/;
33691
33692     var attrs = [
33693         {n: 'id', v: 'id'},
33694         {n: 'className', v: 'class'},
33695         {n: 'name', v: 'name'},
33696         {n: 'type', v: 'type'},
33697         {n: 'src', v: 'src'},
33698         {n: 'href', v: 'href'}
33699     ];
33700
33701     function hasChild(n){
33702         for(var i = 0, c; c = n.childNodes[i]; i++){
33703             if(c.nodeType == 1){
33704                 return true;
33705             }
33706         }
33707         return false;
33708     }
33709
33710     function renderNode(n, leaf){
33711         var tag = n.tagName.toLowerCase();
33712         var s = '&lt;' + tag;
33713         for(var i = 0, len = attrs.length; i < len; i++){
33714             var a = attrs[i];
33715             var v = n[a.n];
33716             if(v && !nonSpace.test(v)){
33717                 s += ' ' + a.v + '=&quot;<i>' + html(v) +'</i>&quot;';
33718             }
33719         }
33720         var style = n.style ? n.style.cssText : '';
33721         if(style){
33722             s += ' style=&quot;<i>' + html(style.toLowerCase()) +'</i>&quot;';
33723         }
33724         if(leaf && n.childNodes.length > 0){
33725             s+='&gt;<em>' + ellipsis(html(String(n.innerHTML)), 35) + '</em>&lt;/'+tag+'&gt;';
33726         }else if(leaf){
33727             s += ' /&gt;';
33728         }else{
33729             s += '&gt;';
33730         }
33731         return s;
33732     }
33733
33734     var HtmlNode = function(n){
33735         var leaf = !hasChild(n);
33736         this.htmlNode = n;
33737         this.tagName = n.tagName.toLowerCase();
33738         var attr = {
33739             text : renderNode(n, leaf),
33740             leaf : leaf,
33741             cls: 'x-tree-noicon'
33742         };
33743         HtmlNode.superclass.constructor.call(this, attr);
33744         this.attributes.htmlNode = n;         if(!leaf){
33745             this.on('expand', this.onExpand,  this);
33746             this.on('collapse', this.onCollapse,  this);
33747         }
33748     };
33749
33750
33751     Ext.extend(HtmlNode, Ext.tree.AsyncTreeNode, {
33752         cls: 'x-tree-noicon',
33753         preventHScroll: true,
33754         refresh : function(highlight){
33755             var leaf = !hasChild(this.htmlNode);
33756             this.setText(renderNode(this.htmlNode, leaf));
33757             if(highlight){
33758                 Ext.fly(this.ui.textNode).highlight();
33759             }
33760         },
33761
33762         onExpand : function(){
33763             if(!this.closeNode && this.parentNode){
33764                 this.closeNode = this.parentNode.insertBefore(new Ext.tree.TreeNode({
33765                     text:'&lt;/' + this.tagName + '&gt;',
33766                     cls: 'x-tree-noicon'
33767                 }), this.nextSibling);
33768             }else if(this.closeNode){
33769                 this.closeNode.ui.show();
33770             }
33771         },
33772
33773         onCollapse : function(){
33774             if(this.closeNode){
33775                 this.closeNode.ui.hide();
33776             }
33777         },
33778
33779         render : function(bulkRender){
33780             HtmlNode.superclass.render.call(this, bulkRender);
33781         },
33782
33783         highlightNode : function(){
33784                     },
33785
33786         highlight : function(){
33787                     },
33788
33789         frame : function(){
33790             this.htmlNode.style.border = '1px solid #0000ff';
33791                     },
33792
33793         unframe : function(){
33794                         this.htmlNode.style.border = '';
33795         }
33796     });
33797
33798     return HtmlNode;
33799 }();
33800
33801
33802
33803 </pre>    \r
33804 </body>\r
33805 </html>