PageSourceSearch

https://sivdao.cvrdao.pt/site_media/js-lib/extjs/ext-all-debug.js

js cvrdao.pt collected 2026-09-24 10:00:22 UTC 1,053,911 bytes, 37,063 lines download raw bytes

1/*
2 * Ext JS Library 2.2.1
3 * Copyright(c) 2006-2009, Ext JS, LLC.
4 * [email protected]
5 * 
6 * http://extjs.com/license
7 */
8
9
10Ext.DomHelper = function(){
11    var tempTableEl = null;
12    var emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;
13    var tableRe = /^table|tbody|tr|td$/i;
14
15    // build as innerHTML where available
16    var createHtml = function(o){
17        if(typeof o == 'string'){
18            return o;
19        }
20        var b = "";
21        if (Ext.isArray(o)) {
22            for (var i = 0, l = o.length; i < l; i++) {
23                b += createHtml(o[i]);
24            }
25            return b;
26        }
27        if(!o.tag){
28            o.tag = "div";
29        }
30        b += "<" + o.tag;
31        for(var attr in o){
32            if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || typeof o[attr] == "function") continue;
33            if(attr == "style"){
34                var s = o["style"];
35                if(typeof s == "function"){
36                    s = s.call();
37                }
38                if(typeof s == "string"){
39                    b += ' style="' + s + '"';
40                }else if(typeof s == "object"){
41                    b += ' style="';
42                    for(var key in s){
43                        if(typeof s[key] != "function"){
44                            b += key + ":" + s[key] + ";";
45                        }
46                    }
47                    b += '"';
48                }
49            }else{
50                if(attr == "cls"){
51                    b += ' class="' + o["cls"] + '"';
52                }else if(attr == "htmlFor"){
53                    b += ' for="' + o["htmlFor"] + '"';
54                }else{
55                    b += " " + attr + '="' + o[attr] + '"';
56                }
57            }
58        }
59        if(emptyTags.test(o.tag)){
60            b += "/>";
61        }else{
62            b += ">";
63            var cn = o.children || o.cn;
64            if(cn){
65                b += createHtml(cn);
66            } else if(o.html){
67                b += o.html;
68            }
69            b += "</" + o.tag + ">";
70        }
71        return b;
72    };
73
74    // build as dom
75    
76    var createDom = function(o, parentNode){
77        var el;
78        if (Ext.isArray(o)) {                       // Allow Arrays of siblings to be inserted
79            el = document.createDocumentFragment(); // in one shot using a DocumentFragment
80            for(var i = 0, l = o.length; i < l; i++) {
81                createDom(o[i], el);
82            }
83        } else if (typeof o == "string") {         // Allow a string as a child spec.
84            el = document.createTextNode(o);
85        } else {
86            el = document.createElement(o.tag||'div');
87            var useSet = !!el.setAttribute; // In IE some elements don't have setAttribute
88            for(var attr in o){
89                if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || attr == "style" || typeof o[attr] == "function") continue;
90                if(attr=="cls"){
91                    el.className = o["cls"];
92                }else{
93                    if(useSet) el.setAttribute(attr, o[attr]);
94                    else el[attr] = o[attr];
95                }
96            }
97            Ext.DomHelper.applyStyles(el, o.style);
98            var cn = o.children || o.cn;
99            if(cn){
100                createDom(cn, el);
101            } else if(o.html){
102                el.innerHTML = o.html;
103            }
104        }
105        if(parentNode){
106           parentNode.appendChild(el);
107        }
108        return el;
109    };
110
111    var ieTable = function(depth, s, h, e){
112        tempTableEl.innerHTML = [s, h, e].join('');
113        var i = -1, el = tempTableEl;
114        while(++i < depth){
115            el = el.firstChild;
116        }
117        return el;
118    };
119
120    // kill repeat to save bytes
121    var ts = '<table>',
122        te = '</table>',
123        tbs = ts+'<tbody>',
124        tbe = '</tbody>'+te,
125        trs = tbs + '<tr>',
126        tre = '</tr>'+tbe;
127
128    
129    var insertIntoTable = function(tag, where, el, html){
130        if(!tempTableEl){
131            tempTableEl = document.createElement('div');
132        }
133        var node;
134        var before = null;
135        if(tag == 'td'){
136            if(where == 'afterbegin' || where == 'beforeend'){ // INTO a TD
137                return;
138            }
139            if(where == 'beforebegin'){
140                before = el;
141                el = el.parentNode;
142            } else{
143                before = el.nextSibling;
144                el = el.parentNode;
145            }
146            node = ieTable(4, trs, html, tre);
147        }
148        else if(tag == 'tr'){
149            if(where == 'beforebegin'){
150                before = el;
151                el = el.parentNode;
152                node = ieTable(3, tbs, html, tbe);
153            } else if(where == 'afterend'){
154                before = el.nextSibling;
155                el = el.parentNode;
156                node = ieTable(3, tbs, html, tbe);
157            } else{ // INTO a TR
158                if(where == 'afterbegin'){
159                    before = el.firstChild;
160                }
161                node = ieTable(4, trs, html, tre);
162            }
163        } else if(tag == 'tbody'){
164            if(where == 'beforebegin'){
165                before = el;
166                el = el.parentNode;
167                node = ieTable(2, ts, html, te);
168            } else if(where == 'afterend'){
169                before = el.nextSibling;
170                el = el.parentNode;
171                node = ieTable(2, ts, html, te);
172            } else{
173                if(where == 'afterbegin'){
174                    before = el.firstChild;
175                }
176                node = ieTable(3, tbs, html, tbe);
177            }
178        } else{ // TABLE
179            if(where == 'beforebegin' || where == 'afterend'){ // OUTSIDE the table
180                return;
181            }
182            if(where == 'afterbegin'){
183                before = el.firstChild;
184            }
185            node = ieTable(2, ts, html, te);
186        }
187        el.insertBefore(node, before);
188        return node;
189    };
190
191
192    return {
193    
194    useDom : false,
195
196    
197    markup : function(o){
198        return createHtml(o);
199    },
200
201    
202    applyStyles : function(el, styles){
203        if(styles){
204           el = Ext.fly(el);
205           if(typeof styles == "string"){
206               var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
207               var matches;
208               while ((matches = re.exec(styles)) != null){
209                   el.setStyle(matches[1], matches[2]);
210               }
211           }else if (typeof styles == "object"){
212               for (var style in styles){
213                  el.setStyle(style, styles[style]);
214               }
215           }else if (typeof styles == "function"){
216                Ext.DomHelper.applyStyles(el, styles.call());
217           }
218        }
219    },
220
221    
222    insertHtml : function(where, el, html){
223        where = where.toLowerCase();
224        if(el.insertAdjacentHTML){
225            if(tableRe.test(el.tagName)){
226                var rs;
227                if(rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)){
228                    return rs;
229                }
230            }
231            switch(where){
232                case "beforebegin":
233                    el.insertAdjacentHTML('BeforeBegin', html);
234                    return el.previousSibling;
235                case "afterbegin":
236                    el.insertAdjacentHTML('AfterBegin', html);
237                    return el.firstChild;
238                case "beforeend":
239                    el.insertAdjacentHTML('BeforeEnd', html);
240                    return el.lastChild;
241                case "afterend":
242                    el.insertAdjacentHTML('AfterEnd', html);
243                    return el.nextSibling;
244            }
245            throw 'Illegal insertion point -> "' + where + '"';
246        }
247        var range = el.ownerDocument.createRange();
248        var frag;
249        switch(where){
250             case "beforebegin":
251                range.setStartBefore(el);
252                frag = range.createContextualFragment(html);
253                el.parentNode.insertBefore(frag, el);
254                return el.previousSibling;
255             case "afterbegin":
256                if(el.firstChild){
257                    range.setStartBefore(el.firstChild);
258                    frag = range.createContextualFragment(html);
259                    el.insertBefore(frag, el.firstChild);
260                    return el.firstChild;
261                }else{
262                    el.innerHTML = html;
263                    return el.firstChild;
264                }
265            case "beforeend":
266                if(el.lastChild){
267                    range.setStartAfter(el.lastChild);
268                    frag = range.createContextualFragment(html);
269                    el.appendChild(frag);
270                    return el.lastChild;
271                }else{
272                    el.innerHTML = html;
273                    return el.lastChild;
274                }
275            case "afterend":
276                range.setStartAfter(el);
277                frag = range.createContextualFragment(html);
278                el.parentNode.insertBefore(frag, el.nextSibling);
279                return el.nextSibling;
280            }
281            throw 'Illegal insertion point -> "' + where + '"';
282    },
283
284    
285    insertBefore : function(el, o, returnElement){
286        return this.doInsert(el, o, returnElement, "beforeBegin");
287    },
288
289    
290    insertAfter : function(el, o, returnElement){
291        return this.doInsert(el, o, returnElement, "afterEnd", "nextSibling");
292    },
293
294    
295    insertFirst : function(el, o, returnElement){
296        return this.doInsert(el, o, returnElement, "afterBegin", "firstChild");
297    },
298
299    // private
300    doInsert : function(el, o, returnElement, pos, sibling){
301        el = Ext.getDom(el);
302        var newNode;
303        if(this.useDom){
304            newNode = createDom(o, null);
305            (sibling === "firstChild" ? el : el.parentNode).insertBefore(newNode, sibling ? el[sibling] : el);
306        }else{
307            var html = createHtml(o);
308            newNode = this.insertHtml(pos, el, html);
309        }
310        return returnElement ? Ext.get(newNode, true) : newNode;
311    },
312
313    
314    append : function(el, o, returnElement){
315        el = Ext.getDom(el);
316        var newNode;
317        if(this.useDom){
318            newNode = createDom(o, null);
319            el.appendChild(newNode);
320        }else{
321            var html = createHtml(o);
322            newNode = this.insertHtml("beforeEnd", el, html);
323        }
324        return returnElement ? Ext.get(newNode, true) : newNode;
325    },
326
327    
328    overwrite : function(el, o, returnElement){
329        el = Ext.getDom(el);
330        el.innerHTML = createHtml(o);
331        return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;
332    },
333
334    
335    createTemplate : function(o){
336        var html = createHtml(o);
337        return new Ext.Template(html);
338    }
339    };
340}();
341
342
343Ext.Template = function(html){
344    var a = arguments;
345    if(Ext.isArray(html)){
346        html = html.join("");
347    }else if(a.length > 1){
348        var buf = [];
349        for(var i = 0, len = a.length; i < len; i++){
350            if(typeof a[i] == 'object'){
351                Ext.apply(this, a[i]);
352            }else{
353                buf[buf.length] = a[i];
354            }
355        }
356        html = buf.join('');
357    }
358    
359    this.html = html;
360    if(this.compiled){
361        this.compile();
362    }
363};
364Ext.Template.prototype = {
365    
366    applyTemplate : function(values){
367        if(this.compiled){
368            return this.compiled(values);
369        }
370        var useF = this.disableFormats !== true;
371        var fm = Ext.util.Format, tpl = this;
372        var fn = function(m, name, format, args){
373            if(format && useF){
374                if(format.substr(0, 5) == "this."){
375                    return tpl.call(format.substr(5), values[name], values);
376                }else{
377                    if(args){
378                        // quoted values are required for strings in compiled templates,
379                        // but for non compiled we need to strip them
380                        // quoted reversed for jsmin
381                        var re = /^\s*['"](.*)["']\s*$/;
382                        args = args.split(',');
383                        for(var i = 0, len = args.length; i < len; i++){
384                            args[i] = args[i].replace(re, "$1");
385                        }
386                        args = [values[name]].concat(args);
387                    }else{
388                        args = [values[name]];
389                    }
390                    return fm[format].apply(fm, args);
391                }
392            }else{
393                return values[name] !== undefined ? values[name] : "";
394            }
395        };
396        return this.html.replace(this.re, fn);
397    },
398
399    
400    set : function(html, compile){
401        this.html = html;
402        this.compiled = null;
403        if(compile){
404            this.compile();
405        }
406        return this;
407    },
408
409    
410    disableFormats : false,
411
412    
413    re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
414
415    
416    compile : function(){
417        var fm = Ext.util.Format;
418        var useF = this.disableFormats !== true;
419        var sep = Ext.isGecko ? "+" : ",";
420        var fn = function(m, name, format, args){
421            if(format && useF){
422                args = args ? ',' + args : "";
423                if(format.substr(0, 5) != "this."){
424                    format = "fm." + format + '(';
425                }else{
426                    format = 'this.call("'+ format.substr(5) + '", ';
427                    args = ", values";
428                }
429            }else{
430                args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
431            }
432            return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
433        };
434        var body;
435        // branched to use + in gecko and [].join() in others
436        if(Ext.isGecko){
437            body = "this.compiled = function(values){ return '" +
438                   this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
439                    "';};";
440        }else{
441            body = ["this.compiled = function(values){ return ['"];
442            body.push(this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn));
443            body.push("'].join('');};");
444            body = body.join('');
445        }
446        eval(body);
447        return this;
448    },
449
450    // private function used to call members
451    call : function(fnName, value, allValues){
452        return this[fnName](value, allValues);
453    },
454
455    
456    insertFirst: function(el, values, returnElement){
457        return this.doInsert('afterBegin', el, values, returnElement);
458    },
459
460    
461    insertBefore: function(el, values, returnElement){
462        return this.doInsert('beforeBegin', el, values, returnElement);
463    },
464
465    
466    insertAfter : function(el, values, returnElement){
467        return this.doInsert('afterEnd', el, values, returnElement);
468    },
469
470    
471    append : function(el, values, returnElement){
472        return this.doInsert('beforeEnd', el, values, returnElement);
473    },
474
475    doInsert : function(where, el, values, returnEl){
476        el = Ext.getDom(el);
477        var newNode = Ext.DomHelper.insertHtml(where, el, this.applyTemplate(values));
478        return returnEl ? Ext.get(newNode, true) : newNode;
479    },
480
481    
482    overwrite : function(el, values, returnElement){
483        el = Ext.getDom(el);
484        el.innerHTML = this.applyTemplate(values);
485        return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;
486    }
487};
488
489Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate;
490
491// backwards compat
492Ext.DomHelper.Template = Ext.Template;
493
494
495Ext.Template.from = function(el, config){
496    el = Ext.getDom(el);
497    return new Ext.Template(el.value || el.innerHTML, config || '');
498};
499
500
501Ext.DomQuery = function(){
502    var cache = {}, simpleCache = {}, valueCache = {};
503    var nonSpace = /\S/;
504    var trimRe = /^\s+|\s+$/g;
505    var tplRe = /\{(\d+)\}/g;
506    var modeRe = /^(\s?[\/>+~]\s?|\s|$)/;
507    var tagTokenRe = /^(#)?([\w-\*]+)/;
508    var nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/;
509
510    function child(p, index){
511        var i = 0;
512        var n = p.firstChild;
513        while(n){
514            if(n.nodeType == 1){
515               if(++i == index){
516                   return n;
517               }
518            }
519            n = n.nextSibling;
520        }
521        return null;
522    };
523
524    function next(n){
525        while((n = n.nextSibling) && n.nodeType != 1);
526        return n;
527    };
528
529    function prev(n){
530        while((n = n.previousSibling) && n.nodeType != 1);
531        return n;
532    };
533
534    function children(d){
535        var n = d.firstChild, ni = -1;
536 	    while(n){
537 	        var nx = n.nextSibling;
538 	        if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
539 	            d.removeChild(n);
540 	        }else{
541 	            n.nodeIndex = ++ni;
542 	        }
543 	        n = nx;
544 	    }
545 	    return this;
546 	};
547
548    function byClassName(c, a, v){
549        if(!v){
550            return c;
551        }
552        var r = [], ri = -1, cn;
553        for(var i = 0, ci; ci = c[i]; i++){
554            if((' '+ci.className+' ').indexOf(v) != -1){
555                r[++ri] = ci;
556            }
557        }
558        return r;
559    };
560
561    function attrValue(n, attr){
562        if(!n.tagName && typeof n.length != "undefined"){
563            n = n[0];
564        }
565        if(!n){
566            return null;
567        }
568        if(attr == "for"){
569            return n.htmlFor;
570        }
571        if(attr == "class" || attr == "className"){
572            return n.className;
573        }
574        return n.getAttribute(attr) || n[attr];
575
576    };
577
578    function getNodes(ns, mode, tagName){
579        var result = [], ri = -1, cs;
580        if(!ns){
581            return result;
582        }
583        tagName = tagName || "*";
584        if(typeof ns.getElementsByTagName != "undefined"){
585            ns = [ns];
586        }
587        if(!mode){
588            for(var i = 0, ni; ni = ns[i]; i++){
589                cs = ni.getElementsByTagName(tagName);
590                for(var j = 0, ci; ci = cs[j]; j++){
591                    result[++ri] = ci;
592                }
593            }
594        }else if(mode == "/" || mode == ">"){
595            var utag = tagName.toUpperCase();
596            for(var i = 0, ni, cn; ni = ns[i]; i++){
597                cn = ni.children || ni.childNodes;
598                for(var j = 0, cj; cj = cn[j]; j++){
599                    if(cj.nodeName == utag || cj.nodeName == tagName  || tagName == '*'){
600                        result[++ri] = cj;
601                    }
602                }
603            }
604        }else if(mode == "+"){
605            var utag = tagName.toUpperCase();
606            for(var i = 0, n; n = ns[i]; i++){
607                while((n = n.nextSibling) && n.nodeType != 1);
608                if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
609                    result[++ri] = n;
610                }
611            }
612        }else if(mode == "~"){
613            for(var i = 0, n; n = ns[i]; i++){
614                while((n = n.nextSibling) && (n.nodeType != 1 || (tagName == '*' || n.tagName.toLowerCase()!=tagName)));
615                if(n){
616                    result[++ri] = n;
617                }
618            }
619        }
620        return result;
621    };
622
623    function concat(a, b){
624        if(b.slice){
625            return a.concat(b);
626        }
627        for(var i = 0, l = b.length; i < l; i++){
628            a[a.length] = b[i];
629        }
630        return a;
631    }
632
633    function byTag(cs, tagName){
634        if(cs.tagName || cs == document){
635            cs = [cs];
636        }
637        if(!tagName){
638            return cs;
639        }
640        var r = [], ri = -1;
641        tagName = tagName.toLowerCase();
642        for(var i = 0, ci; ci = cs[i]; i++){
643            if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
644                r[++ri] = ci;
645            }
646        }
647        return r;
648    };
649
650    function byId(cs, attr, id){
651        if(cs.tagName || cs == document){
652            cs = [cs];
653        }
654        if(!id){
655            return cs;
656        }
657        var r = [], ri = -1;
658        for(var i = 0,ci; ci = cs[i]; i++){
659            if(ci && ci.id == id){
660                r[++ri] = ci;
661                return r;
662            }
663        }
664        return r;
665    };
666
667    function byAttribute(cs, attr, value, op, custom){
668        var r = [], ri = -1, st = custom=="{";
669        var f = Ext.DomQuery.operators[op];
670        for(var i = 0, ci; ci = cs[i]; i++){
671            var a;
672            if(st){
673                a = Ext.DomQuery.getStyle(ci, attr);
674            }
675            else if(attr == "class" || attr == "className"){
676                a = ci.className;
677            }else if(attr == "for"){
678                a = ci.htmlFor;
679            }else if(attr == "href"){
680                a = ci.getAttribute("href", 2);
681            }else{
682                a = ci.getAttribute(attr);
683            }
684            if((f && f(a, value)) || (!f && a)){
685                r[++ri] = ci;
686            }
687        }
688        return r;
689    };
690
691    function byPseudo(cs, name, value){
692        return Ext.DomQuery.pseudos[name](cs, value);
693    };
694
695    // This is for IE MSXML which does not support expandos.
696    // IE runs the same speed using setAttribute, however FF slows way down
697    // and Safari completely fails so they need to continue to use expandos.
698    var isIE = window.ActiveXObject ? true : false;
699
700    // this eval is stop the compressor from
701    // renaming the variable to something shorter
702    eval("var batch = 30803;");
703
704    var key = 30803;
705
706    function nodupIEXml(cs){
707        var d = ++key;
708        cs[0].setAttribute("_nodup", d);
709        var r = [cs[0]];
710        for(var i = 1, len = cs.length; i < len; i++){
711            var c = cs[i];
712            if(!c.getAttribute("_nodup") != d){
713                c.setAttribute("_nodup", d);
714                r[r.length] = c;
715            }
716        }
717        for(var i = 0, len = cs.length; i < len; i++){
718            cs[i].removeAttribute("_nodup");
719        }
720        return r;
721    }
722
723    function nodup(cs){
724        if(!cs){
725            return [];
726        }
727        var len = cs.length, c, i, r = cs, cj, ri = -1;
728        if(!len || typeof cs.nodeType != "undefined" || len == 1){
729            return cs;
730        }
731        if(isIE && typeof cs[0].selectSingleNode != "undefined"){
732            return nodupIEXml(cs);
733        }
734        var d = ++key;
735        cs[0]._nodup = d;
736        for(i = 1; c = cs[i]; i++){
737            if(c._nodup != d){
738                c._nodup = d;
739            }else{
740                r = [];
741                for(var j = 0; j < i; j++){
742                    r[++ri] = cs[j];
743                }
744                for(j = i+1; cj = cs[j]; j++){
745                    if(cj._nodup != d){
746                        cj._nodup = d;
747                        r[++ri] = cj;
748                    }
749                }
750                return r;
751            }
752        }
753        return r;
754    }
755
756    function quickDiffIEXml(c1, c2){
757        var d = ++key;
758        for(var i = 0, len = c1.length; i < len; i++){
759            c1[i].setAttribute("_qdiff", d);
760        }
761        var r = [];
762        for(var i = 0, len = c2.length; i < len; i++){
763            if(c2[i].getAttribute("_qdiff") != d){
764                r[r.length] = c2[i];
765            }
766        }
767        for(var i = 0, len = c1.length; i < len; i++){
768           c1[i].removeAttribute("_qdiff");
769        }
770        return r;
771    }
772
773    function quickDiff(c1, c2){
774        var len1 = c1.length;
775        if(!len1){
776            return c2;
777        }
778        if(isIE && c1[0].selectSingleNode){
779            return quickDiffIEXml(c1, c2);
780        }
781        var d = ++key;
782        for(var i = 0; i < len1; i++){
783            c1[i]._qdiff = d;
784        }
785        var r = [];
786        for(var i = 0, len = c2.length; i < len; i++){
787            if(c2[i]._qdiff != d){
788                r[r.length] = c2[i];
789            }
790        }
791        return r;
792    }
793
794    function quickId(ns, mode, root, id){
795        if(ns == root){
796           var d = root.ownerDocument || root;
797           return d.getElementById(id);
798        }
799        ns = getNodes(ns, mode, "*");
800        return byId(ns, null, id);
801    }
802
803    return {
804        getStyle : function(el, name){
805            return Ext.fly(el).getStyle(name);
806        },
807        
808        compile : function(path, type){
809            type = type || "select";
810
811            var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"];
812            var q = path, mode, lq;
813            var tk = Ext.DomQuery.matchers;
814            var tklen = tk.length;
815            var mm;
816
817            // accept leading mode switch
818            var lmode = q.match(modeRe);
819            if(lmode && lmode[1]){
820                fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
821                q = q.replace(lmode[1], "");
822            }
823            // strip leading slashes
824            while(path.substr(0, 1)=="/"){
825                path = path.substr(1);
826            }
827
828            while(q && lq != q){
829                lq = q;
830                var tm = q.match(tagTokenRe);
831                if(type == "select"){
832                    if(tm){
833                        if(tm[1] == "#"){
834                            fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
835                        }else{
836                            fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
837                        }
838                        q = q.replace(tm[0], "");
839                    }else if(q.substr(0, 1) != '@'){
840                        fn[fn.length] = 'n = getNodes(n, mode, "*");';
841                    }
842                }else{
843                    if(tm){
844                        if(tm[1] == "#"){
845                            fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
846                        }else{
847                            fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
848                        }
849                        q = q.replace(tm[0], "");
850                    }
851                }
852                while(!(mm = q.match(modeRe))){
853                    var matched = false;
854                    for(var j = 0; j < tklen; j++){
855                        var t = tk[j];
856                        var m = q.match(t.re);
857                        if(m){
858                            fn[fn.length] = t.select.replace(tplRe, function(x, i){
859                                                    return m[i];
860                                                });
861                            q = q.replace(m[0], "");
862                            matched = true;
863                            break;
864                        }
865                    }
866                    // prevent infinite loop on bad selector
867                    if(!matched){
868                        throw 'Error parsing selector, parsing failed at "' + q + '"';
869                    }
870                }
871                if(mm[1]){
872                    fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';
873                    q = q.replace(mm[1], "");
874                }
875            }
876            fn[fn.length] = "return nodup(n);\n}";
877            eval(fn.join(""));
878            return f;
879        },
880
881        
882        select : function(path, root, type){
883            if(!root || root == document){
884                root = document;
885            }
886            if(typeof root == "string"){
887                root = document.getElementById(root);
888            }
889            var paths = path.split(",");
890            var results = [];
891            for(var i = 0, len = paths.length; i < len; i++){
892                var p = paths[i].replace(trimRe, "");
893                if(!cache[p]){
894                    cache[p] = Ext.DomQuery.compile(p);
895                    if(!cache[p]){
896                        throw p + " is not a valid selector";
897                    }
898                }
899                var result = cache[p](root);
900                if(result && result != document){
901                    results = results.concat(result);
902                }
903            }
904            if(paths.length > 1){
905                return nodup(results);
906            }
907            return results;
908        },
909
910        
911        selectNode : function(path, root){
912            return Ext.DomQuery.select(path, root)[0];
913        },
914
915        
916        selectValue : function(path, root, defaultValue){
917            path = path.replace(trimRe, "");
918            if(!valueCache[path]){
919                valueCache[path] = Ext.DomQuery.compile(path, "select");
920            }
921            var n = valueCache[path](root);
922            n = n[0] ? n[0] : n;
923            var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
924            return ((v === null||v === undefined||v==='') ? defaultValue : v);
925        },
926
927        
928        selectNumber : function(path, root, defaultValue){
929            var v = Ext.DomQuery.selectValue(path, root, defaultValue || 0
929);
930            return parseFloat(v);
931        },
932
933        
934        is : function(el, ss){
935            if(typeof el == "string"){
936                el = document.getElementById(el);
937            }
938            var isArray = Ext.isArray(el);
939            var result = Ext.DomQuery.filter(isArray ? el : [el], ss);
940            return isArray ? (result.length == el.length) : (result.length > 0);
941        },
942
943        
944        filter : function(els, ss, nonMatches){
945            ss = ss.replace(trimRe, "");
946            if(!simpleCache[ss]){
947                simpleCache[ss] = Ext.DomQuery.compile(ss, "simple");
948            }
949            var result = simpleCache[ss](els);
950            return nonMatches ? quickDiff(result, els) : result;
951        },
952
953        
954        matchers : [{
955                re: /^\.([\w-]+)/,
956                select: 'n = byClassName(n, null, " {1} ");'
957            }, {
958                re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
959                select: 'n = byPseudo(n, "{1}", "{2}");'
960            },{
961                re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
962                select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
963            }, {
964                re: /^#([\w-]+)/,
965                select: 'n = byId(n, null, "{1}");'
966            },{
967                re: /^@([\w-]+)/,
968                select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
969            }
970        ],
971
972        
973        operators : {
974            "=" : function(a, v){
975                return a == v;
976            },
977            "!=" : function(a, v){
978                return a != v;
979            },
980            "^=" : function(a, v){
981                return a && a.substr(0, v.length) == v;
982            },
983            "$=" : function(a, v){
984                return a && a.substr(a.length-v.length) == v;
985            },
986            "*=" : function(a, v){
987                return a && a.indexOf(v) !== -1;
988            },
989            "%=" : function(a, v){
990                return (a % v) == 0;
991            },
992            "|=" : function(a, v){
993                return a && (a == v || a.substr(0, v.length+1) == v+'-');
994            },
995            "~=" : function(a, v){
996                return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
997            }
998        },
999
1000        
1001        pseudos : {
1002            "first-child" : function(c){
1003                var r = [], ri = -1, n;
1004                for(var i = 0, ci; ci = n = c[i]; i++){
1005                    while((n = n.previousSibling) && n.nodeType != 1);
1006                    if(!n){
1007                        r[++ri] = ci;
1008                    }
1009                }
1010                return r;
1011            },
1012
1013            "last-child" : function(c){
1014                var r = [], ri = -1, n;
1015                for(var i = 0, ci; ci = n = c[i]; i++){
1016                    while((n = n.nextSibling) && n.nodeType != 1);
1017                    if(!n){
1018                        r[++ri] = ci;
1019                    }
1020                }
1021                return r;
1022            },
1023
1024            "nth-child" : function(c, a) {
1025                var r = [], ri = -1;
1026                var m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a);
1027                var f = (m[1] || 1) - 0, l = m[2] - 0;
1028                for(var i = 0, n; n = c[i]; i++){
1029                    var pn = n.parentNode;
1030                    if (batch != pn._batch) {
1031                        var j = 0;
1032                        for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
1033                            if(cn.nodeType == 1){
1034                               cn.nodeIndex = ++j;
1035                            }
1036                        }
1037                        pn._batch = batch;
1038                    }
1039                    if (f == 1) {
1040                        if (l == 0 || n.nodeIndex == l){
1041                            r[++ri] = n;
1042                        }
1043                    } else if ((n.nodeIndex + l) % f == 0){
1044                        r[++ri] = n;
1045                    }
1046                }
1047
1048                return r;
1049            },
1050
1051            "only-child" : function(c){
1052                var r = [], ri = -1;;
1053                for(var i = 0, ci; ci = c[i]; i++){
1054                    if(!prev(ci) && !next(ci)){
1055                        r[++ri] = ci;
1056                    }
1057                }
1058                return r;
1059            },
1060
1061            "empty" : function(c){
1062                var r = [], ri = -1;
1063                for(var i = 0, ci; ci = c[i]; i++){
1064                    var cns = ci.childNodes, j = 0, cn, empty = true;
1065                    while(cn = cns[j]){
1066                        ++j;
1067                        if(cn.nodeType == 1 || cn.nodeType == 3){
1068                            empty = false;
1069                            break;
1070                        }
1071                    }
1072                    if(empty){
1073                        r[++ri] = ci;
1074                    }
1075                }
1076                return r;
1077            },
1078
1079            "contains" : function(c, v){
1080                var r = [], ri = -1;
1081                for(var i = 0, ci; ci = c[i]; i++){
1082                    if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
1083                        r[++ri] = ci;
1084                    }
1085                }
1086                return r;
1087            },
1088
1089            "nodeValue" : function(c, v){
1090                var r = [], ri = -1;
1091                for(var i = 0, ci; ci = c[i]; i++){
1092                    if(ci.firstChild && ci.firstChild.nodeValue == v){
1093                        r[++ri] = ci;
1094                    }
1095                }
1096                return r;
1097            },
1098
1099            "checked" : function(c){
1100                var r = [], ri = -1;
1101                for(var i = 0, ci; ci = c[i]; i++){
1102                    if(ci.checked == true){
1103                        r[++ri] = ci;
1104                    }
1105                }
1106                return r;
1107            },
1108
1109            "not" : function(c, ss){
1110                return Ext.DomQuery.filter(c, ss, true);
1111            },
1112
1113            "any" : function(c, selectors){
1114                var ss = selectors.split('|');
1115                var r = [], ri = -1, s;
1116                for(var i = 0, ci; ci = c[i]; i++){
1117                    for(var j = 0; s = ss[j]; j++){
1118                        if(Ext.DomQuery.is(ci, s)){
1119                            r[++ri] = ci;
1120                            break;
1121                        }
1122                    }
1123                }
1124                return r;
1125            },
1126
1127            "odd" : function(c){
1128                return this["nth-child"](c, "odd");
1129            },
1130
1131            "even" : function(c){
1132                return this["nth-child"](c, "even");
1133            },
1134
1135            "nth" : function(c, a){
1136                return c[a-1] || [];
1137            },
1138
1139            "first" : function(c){
1140                return c[0] || [];
1141            },
1142
1143            "last" : function(c){
1144                return c[c.length-1] || [];
1145            },
1146
1147            "has" : function(c, ss){
1148                var s = Ext.DomQuery.select;
1149                var r = [], ri = -1;
1150                for(var i = 0, ci; ci = c[i]; i++){
1151                    if(s(ss, ci).length > 0){
1152                        r[++ri] = ci;
1153                    }
1154                }
1155                return r;
1156            },
1157
1158            "next" : function(c, ss){
1159                var is = Ext.DomQuery.is;
1160                var r = [], ri = -1;
1161                for(var i = 0, ci; ci = c[i]; i++){
1162                    var n = next(ci);
1163                    if(n && is(n, ss)){
1164                        r[++ri] = ci;
1165                    }
1166                }
1167                return r;
1168            },
1169
1170            "prev" : function(c, ss){
1171                var is = Ext.DomQuery.is;
1172                var r = [], ri = -1;
1173                for(var i = 0, ci; ci = c[i]; i++){
1174                    var n = prev(ci);
1175                    if(n && is(n, ss)){
1176                        r[++ri] = ci;
1177                    }
1178                }
1179                return r;
1180            }
1181        }
1182    };
1183}();
1184
1185
1186Ext.query = Ext.DomQuery.select;
1187
1188
1189Ext.util.Observable = function(){
1190    
1191    if(this.listeners){
1192        this.on(this.listeners);
1193        delete this.listeners;
1194    }
1195};
1196Ext.util.Observable.prototype = {
1197    
1198    fireEvent : function(){
1199        if(this.eventsSuspended !== true){
1200            var ce = this.events[arguments[0].toLowerCase()];
1201            if(typeof ce == "object"){
1202                return ce.fire.apply(ce, Array.prototype.slice.call(arguments, 1));
1203            }
1204        }
1205        return true;
1206    },
1207
1208    // private
1209    filterOptRe : /^(?:scope|delay|buffer|single)$/,
1210
1211    
1212    addListener : function(eventName, fn, scope, o){
1213        if(typeof eventName == "object"){
1214            o = eventName;
1215            for(var e in o){
1216                if(this.filterOptRe.test(e)){
1217                    continue;
1218                }
1219                if(typeof o[e] == "function"){
1220                    // shared options
1221                    this.addListener(e, o[e], o.scope,  o);
1222                }else{
1223                    // individual options
1224                    this.addListener(e, o[e].fn, o[e].scope, o[e]);
1225                }
1226            }
1227            return;
1228        }
1229        o = (!o || typeof o == "boolean") ? {} : o;
1230        eventName = eventName.toLowerCase();
1231        var ce = this.events[eventName] || true;
1232        if(typeof ce == "boolean"){
1233            ce = new Ext.util.Event(this, eventName);
1234            this.events[eventName] = ce;
1235        }
1236        ce.addListener(fn, scope, o);
1237    },
1238
1239    
1240    removeListener : function(eventName, fn, scope){
1241        var ce = this.events[eventName.toLowerCase()];
1242        if(typeof ce == "object"){
1243            ce.removeListener(fn, scope);
1244        }
1245    },
1246
1247    
1248    purgeListeners : function(){
1249        for(var evt in this.events){
1250            if(typeof this.events[evt] == "object"){
1251                 this.events[evt].clearListeners();
1252            }
1253        }
1254    },
1255
1256    
1257    relayEvents : function(o, events){
1258        var createHandler = function(ename){
1259            return function(){
1260                return this.fireEvent.apply(this, Ext.combine(ename, Array.prototype.slice.call(arguments, 0)));
1261            };
1262        };
1263        for(var i = 0, len = events.length; i < len; i++){
1264            var ename = events[i];
1265            if(!this.events[ename]){ this.events[ename] = true; };
1266            o.on(ename, createHandler(ename), this);
1267        }
1268    },
1269
1270    
1271    addEvents : function(o){
1272        if(!this.events){
1273            this.events = {};
1274        }
1275        if(typeof o == 'string'){
1276            for(var i = 0, a = arguments, v; v = a[i]; i++){
1277                if(!this.events[a[i]]){
1278                    this.events[a[i]] = true;
1279                }
1280            }
1281        }else{
1282            Ext.applyIf(this.events, o);
1283        }
1284    },
1285
1286    
1287    hasListener : function(eventName){
1288        var e = this.events[eventName];
1289        return typeof e == "object" && e.listeners.length > 0;
1290    },
1291
1292    
1293    suspendEvents : function(){
1294        this.eventsSuspended = true;
1295    },
1296
1297    
1298    resumeEvents : function(){
1299        this.eventsSuspended = false;
1300    },
1301
1302    // these are considered experimental
1303    // allows for easier interceptor and sequences, including cancelling and overwriting the return value of the call
1304    // private
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    // adds an "interceptor" called before the original method
1369    beforeMethod : function(method, fn, scope){
1370        var e = this.getMethodEvent(method);
1371        e.before.push({fn: fn, scope: scope});
1372    },
1373
1374    // adds a "sequence" called after the original method
1375    afterMethod : function(method, fn, scope){
1376        var e = this.getMethodEvent(method);
1377        e.after.push({fn: fn, scope: scope});
1378    },
1379
1380    removeMethodListener : function(method, fn, scope){
1381        var e = this.getMethodEvent(method);
1382        for(var i = 0, len = e.before.length; i < len; i++){
1383            if(e.before[i].fn == fn && e.before[i].scope == scope){
1384                e.before.splice(i, 1);
1385                return;
1386            }
1387        }
1388        for(var i = 0, len = e.after.length; i < len; i++){
1389            if(e.after[i].fn == fn && e.after[i].scope == scope){
1390                e.after.splice(i, 1);
1391                return;
1392            }
1393        }
1394    }
1395};
1396
1397Ext.util.Observable.prototype.on = Ext.util.Observable.prototype.addListener;
1398
1399Ext.util.Observable.prototype.un = Ext.util.Observable.prototype.removeListener;
1400
1401
1402Ext.util.Observable.capture = function(o, fn, scope){
1403    o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
1404};
1405
1406
1407Ext.util.Observable.releaseCapture = function(o){
1408    o.fireEvent = Ext.util.Observable.prototype.fireEvent;
1409};
1410
1411(function(){
1412
1413    var createBuffered = function(h, o, scope){
1414        var task = new Ext.util.DelayedTask();
1415        return function(){
1416            task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
1417        };
1418    };
1419
1420    var createSingle = function(h, e, fn, scope){
1421        return function(){
1422            e.removeListener(fn, scope);
1423            return h.apply(scope, arguments);
1424        };
1425    };
1426
1427    var createDelayed = function(h, o, scope){
1428        return function(){
1429            var args = Array.prototype.slice.call(arguments, 0);
1430            setTimeout(function(){
1431                h.apply(scope, args);
1432            }, o.delay || 10);
1433        };
1434    };
1435
1436    Ext.util.Event = function(obj, name){
1437        this.name = name;
1438        this.obj = obj;
1439        this.listeners = [];
1440    };
1441
1442    Ext.util.Event.prototype = {
1443        addListener : function(fn, scope, options){
1444            scope = scope || this.obj;
1445            if(!this.isListening(fn, scope)){
1446                var l = this.createListener(fn, scope, options);
1447                if(!this.firing){
1448                    this.listeners.push(l);
1449                }else{ // if we are currently firing this event, don't disturb the listener loop
1450                    this.listeners = this.listeners.slice(0);
1451                    this.listeners.push(l);
1452                }
1453            }
1454        },
1455
1456        createListener : function(fn, scope, o){
1457            o = o || {};
1458            scope = scope || this.obj;
1459            var l = {fn: fn, scope: scope, options: o};
1460            var h = fn;
1461            if(o.delay){
1462                h = createDelayed(h, o, scope);
1463            }
1464            if(o.single){
1465                h = createSingle(h, this, fn, scope);
1466            }
1467            if(o.buffer){
1468                h = createBuffered(h, o, scope);
1469            }
1470            l.fireFn = h;
1471            return l;
1472        },
1473
1474        findListener : function(fn, scope){
1475            scope = scope || this.obj;
1476            var ls = this.listeners;
1477            for(var i = 0, len = ls.length; i < len; i++){
1478                var l = ls[i];
1479                if(l.fn == fn && l.scope == scope){
1480                    return i;
1481                }
1482            }
1483            return -1;
1484        },
1485
1486        isListening : function(fn, scope){
1487            return this.findListener(fn, scope) != -1;
1488        },
1489
1490        removeListener : function(fn, scope){
1491            var index;
1492            if((index = this.findListener(fn, scope)) != -1){
1493                if(!this.firing){
1494                    this.listeners.splice(index, 1);
1495                }else{
1496                    this.listeners = this.listeners.slice(0);
1497                    this.listeners.splice(index, 1);
1498                }
1499                return true;
1500            }
1501            return false;
1502        },
1503
1504        clearListeners : function(){
1505            this.listeners = [];
1506        },
1507
1508        fire : function(){
1509            var ls = this.listeners, scope, len = ls.length;
1510            if(len > 0){
1511                this.firing = true;
1512                var args = Array.prototype.slice.call(arguments, 0);
1513                for(var i = 0; i < len; i++){
1514                    var l = ls[i];
1515                    if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){
1516                        this.firing = false;
1517                        return false;
1518                    }
1519                }
1520                this.firing = false;
1521            }
1522            return true;
1523        }
1524    };
1525})();
1526
1527Ext.EventManager = function(){
1528    var docReadyEvent, docReadyProcId, docReadyState = false;
1529    var resizeEvent, resizeTask, textEvent, textSize;
1530    var E = Ext.lib.Event;
1531    var D = Ext.lib.Dom;
1532    // fix parser confusion
1533    var xname = 'Ex' + 't';
1534
1535    var elHash = {};
1536
1537    var addListener = function(el, ename, fn, wrap, scope){
1538        var id = Ext.id(el);
1539        if(!elHash[id]){
1540            elHash[id] = {};
1541        }
1542        var es = elHash[id];
1543        if(!es[ename]){
1544            es[ename] = [];
1545        }
1546        var ls = es[ename];
1547        ls.push({
1548            id: id,
1549            ename: ename,
1550            fn: fn,
1551            wrap: wrap,
1552            scope: scope
1553        });
1554
1555         E.on(el, ename, wrap);
1556
1557        if(ename == "mousewheel" && el.addEventListener){ // workaround for jQuery
1558            el.addEventListener("DOMMouseScroll", wrap, false);
1559            E.on(window, 'unload', function(){
1560                el.removeEventListener("DOMMouseScroll", wrap, false);
1561            });
1562        }
1563        if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
1564            Ext.EventManager.stoppedMouseDownEvent.addListener(wrap);
1565        }
1566    }
1567
1568    var removeListener = function(el, ename, fn, scope){
1569        el = Ext.getDom(el);
1570
1571        var id = Ext.id(el), es = elHash[id], wrap;
1572        if(es){
1573            var ls = es[ename], l;
1574            if(ls){
1575                for(var i = 0, len = ls.length; i < len; i++){
1576                    l = ls[i];
1577                    if(l.fn == fn && (!scope || l.scope == scope)){
1578                        wrap = l.wrap;
1579                        E.un(el, ename, wrap);
1580                        ls.splice(i, 1);
1581                        break;
1582                    }
1583                }
1584            }
1585        }
1586        if(ename == "mousewheel" && el.addEventListener && wrap){
1587            el.removeEventListener("DOMMouseScroll", wrap, false);
1588        }
1589        if(ename == "mousedown" && el == document && wrap){ // fix stopped mousedowns on the document
1590            Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);
1591        }
1592    }
1593
1594    var removeAll = function(el){
1595        el = Ext.getDom(el);
1596        var id = Ext.id(el), es = elHash[id], ls;
1597        if(es){
1598            for(var ename in es){
1599                if(es.hasOwnProperty(ename)){
1600                    ls = es[ename];
1601                    for(var i = 0, len = ls.length; i < len; i++){
1602                        E.un(el, ename, ls[i].wrap);
1603                        ls[i] = null;
1604                    }
1605                }
1606                es[ename] = null;
1607            }
1608            delete elHash[id];
1609        }
1610    }
1611
1612
1613    var fireDocReady = function(){
1614        if(!docReadyState){
1615            docReadyState = true;
1616            Ext.isReady = true;
1617            if(docReadyProcId){
1618                clearInterval(docReadyProcId);
1619            }
1620            if(Ext.isGecko || Ext.isOpera) {
1621                document.removeEventListener("DOMContentLoaded", fireDocReady, false);
1622            }
1623            if(Ext.isIE){
1624                var defer = document.getElementById("ie-deferred-loader");
1625                if(defer){
1626                    defer.onreadystatechange = null;
1627                    defer.parentNode.removeChild(defer);
1628                }
1629            }
1630            if(docReadyEvent){
1631                docReadyEvent.fire();
1632                docReadyEvent.clearListeners();
1633            }
1634        }
1635    };
1636
1637    var initDocReady = function(){
1638        docReadyEvent = new Ext.util.Event();
1639        if(Ext.isGecko || Ext.isOpera) {
1640            document.addEventListener("DOMContentLoaded", fireDocReady, false);
1641        }else if(Ext.isIE){
1642            document.write("<s"+'cript id="ie-deferred-loader" defer="defer" src="/'+'/:"></s'+"cript>");
1643            var defer = document.getElementById("ie-deferred-loader");
1644            defer.onreadystatechange = function(){
1645                if(this.readyState == "complete"){
1646                    fireDocReady();
1647                }
1648            };
1649        }else if(Ext.isSafari){
1650            docReadyProcId = setInterval(function(){
1651                var rs = document.readyState;
1652                if(rs == "complete") {
1653                    fireDocReady();
1654                 }
1655            }, 10);
1656        }
1657        // no matter what, make sure it fires on load
1658        E.on(window, "load", fireDocReady);
1659    };
1660
1661    var createBuffered = function(h, o){
1662        var task = new Ext.util.DelayedTask(h);
1663        return function(e){
1664            // create new event object impl so new events don't wipe out properties
1665            e = new Ext.EventObjectImpl(e);
1666            task.delay(o.buffer, h, null, [e]);
1667        };
1668    };
1669
1670    var createSingle = function(h, el, ename, fn, scope){
1671        return function(e){
1672            Ext.EventManager.removeListener(el, ename, fn, scope);
1673            h(e);
1674        };
1675    };
1676
1677    var createDelayed = function(h, o){
1678        return function(e){
1679            // create new event object impl so new events don't wipe out properties
1680            e = new Ext.EventObjectImpl(e);
1681            setTimeout(function(){
1682                h(e);
1683            }, o.delay || 10);
1684        };
1685    };
1686
1687    var listen = function(element, ename, opt, fn, scope){
1688        var o = (!opt || typeof opt == "boolean") ? {} : opt;
1689        fn = fn || o.fn; scope = scope || o.scope;
1690        var el = Ext.getDom(element);
1691        if(!el){
1692            throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
1693        }
1694        var h = function(e){
1695            // prevent errors while unload occurring
1696            if(!window[xname]){
1697                return;
1698            }
1699            e = Ext.EventObject.setEvent(e);
1700            var t;
1701            if(o.delegate){
1702                t = e.getTarget(o.delegate, el);
1703                if(!t){
1704                    return;
1705                }
1706            }else{
1707                t = e.target;
1708            }
1709            if(o.stopEvent === true){
1710                e.stopEvent();
1711            }
1712            if(o.preventDefault === true){
1713               e.preventDefault();
1714            }
1715            if(o.stopPropagation === true){
1716                e.stopPropagation();
1717            }
1718
1719            if(o.normalized === false){
1720                e = e.browserEvent;
1721            }
1722
1723            fn.call(scope || el, e, t, o);
1724        };
1725        if(o.delay){
1726            h = createDelayed(h, o);
1727        }
1728        if(o.single){
1729            h = createSingle(h, el, ename, fn, scope);
1730        }
1731        if(o.buffer){
1732            h = createBuffered(h, o);
1733        }
1734
1735        addListener(el, ename, fn, h, scope);
1736        return h;
1737    };
1738
1739    var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
1740    var pub = {
1741
1742    
1743        addListener : function(element, eventName, fn, scope, options){
1744            if(typeof eventName == "object"){
1745                var o = eventName;
1746                for(var e in o){
1747                    if(propRe.test(e)){
1748                        continue;
1749                    }
1750                    if(typeof o[e] == "function"){
1751                        // shared options
1752                        listen(element, e, o, o[e], o.scope);
1753                    }else{
1754                        // individual options
1755                        listen(element, e, o[e]);
1756                    }
1757                }
1758                return;
1759            }
1760            return listen(element, eventName, options, fn, scope);
1761        },
1762
1763        
1764        removeListener : function(element, eventName, fn, scope){
1765            return removeListener(element, eventName, fn, scope);
1766        },
1767
1768        
1769        removeAll : function(element){
1770            return removeAll(element);
1771        },
1772
1773        
1774        onDocumentReady : function(fn, scope, options){
1775            if(docReadyState){ // if it already fired
1776                docReadyEvent.addListener(fn, scope, options);
1777                docReadyEvent.fire();
1778                docReadyEvent.clearListeners();
1779                return;
1780            }
1781            if(!docReadyEvent){
1782                initDocReady();
1783            }
1784            options = options || {};
1785            if(!options.delay){
1786                options.delay = 1;
1787            }
1788            docReadyEvent.addListener(fn, scope, options);
1789        },
1790        
1791        // private
1792        doResizeEvent: function(){
1793            resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
1794        },
1795
1796        
1797        onWindowResize : function(fn, scope, options){
1798            if(!resizeEvent){
1799                resizeEvent = new Ext.util.Event();
1800                resizeTask = new Ext.util.DelayedTask(this.doResizeEvent);
1801                E.on(window, "resize", this.fireWindowResize, this);
1802            }
1803            resizeEvent.addListener(fn, scope, options);
1804        },
1805
1806        // exposed only to allow manual firing
1807        fireWindowResize : function(){
1808            if(resizeEvent){
1809                if((Ext.isIE||Ext.isAir) && resizeTask){
1810                    resizeTask.delay(50);
1811                }else{
1812                    resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
1813                }
1814            }
1815        },
1816
1817        
1818        onTextResize : function(fn, scope, options){
1819            if(!textEvent){
1820                textEvent = new Ext.util.Event();
1821                var textEl = new Ext.Element(document.createElement('div'));
1822                textEl.dom.className = 'x-text-resize';
1823                textEl.dom.innerHTML = 'X';
1824                textEl.appendTo(document.body);
1825                textSize = textEl.dom.offsetHeight;
1826                setInterval(function(){
1827                    if(textEl.dom.offsetHeight != textSize){
1828                        textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
1829                    }
1830                }, this.textResizeInterval);
1831            }
1832            textEvent.addListener(fn, scope, options);
1833        },
1834
1835        
1836        removeResizeListener : function(fn, scope){
1837            if(resizeEvent){
1838                resizeEvent.removeListener(fn, scope);
1839            }
1840        },
1841
1842        // private
1843        fireResize : function(){
1844            if(resizeEvent){
1845                resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
1846            }
1847        },
1848        
1849        ieDeferSrc : false,
1850        
1851        textResizeInterval : 50
1852    };
1853     
1854    pub.on = pub.addListener;
1855    
1856    pub.un = pub.removeListener;
1857
1858    pub.stoppedMouseDownEvent = new Ext.util.Event();
1859    return pub;
1860}();
1861
1862Ext.onReady = Ext.EventManager.onDocumentReady;
1863
1864
1865// Initialize doc classes
1866(function(){
1867    var initExtCss = function(){
1868        // find the body element
1869        var bd = document.body || document.getElementsByTagName('body')[0];
1870        if(!bd){ return false; }
1871        var cls = [' ',
1872                Ext.isIE ? "ext-ie " + (Ext.isIE6 ? 'ext-ie6' : (Ext.isIE7 ? 'ext-ie7' : 'ext-ie8'))
1873                : Ext.isGecko ? "ext-gecko " + (Ext.isGecko2 ? 'ext-gecko2' : 'ext-gecko3')
1874                : Ext.isOpera ? "ext-opera"
1875                : Ext.isSafari ? "ext-safari"
1876                : Ext.isChrome ? "ext-chrome" : ""];
1877
1878        if(Ext.isMac){
1879            cls.push("ext-mac");
1880        }
1881        if(Ext.isLinux){
1882            cls.push("ext-linux");
1883        }
1884        if(Ext.isBorderBox){
1885            cls.push('ext-border-box');
1886        }
1887        if(Ext.isStrict){ // add to the parent to allow for selectors like ".ext-strict .ext-ie"
1888            var p = bd.parentNode;
1889            if(p){
1890                p.className += ' ext-strict';
1891            }
1892        }
1893        bd.className += cls.join(' ');
1894        return true;
1895    }
1896
1897    if(!initExtCss()){
1898        Ext.onReady(initExtCss);
1899    }
1900})();
1901
1902
1903Ext.EventObject = function(){
1904
1905    var E = Ext.lib.Event;
1906
1907    // safari keypress events for special keys return bad keycodes
1908    var safariKeys = {
1909        3 : 13, // enter
1910        63234 : 37, // left
1911        63235 : 39, // right
1912        63232 : 38, // up
1913        63233 : 40, // down
1914        63276 : 33, // page up
1915        63277 : 34, // page down
1916        63272 : 46, // delete
1917        63273 : 36, // home
1918        63275 : 35  // end
1919    };
1920
1921    // normalize button clicks
1922    var btnMap = Ext.isIE ? {1:0,4:1,2:2} :
1923                (Ext.isSafari ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
1924
1925    Ext.EventObjectImpl = function(e){
1926        if(e){
1927            this.setEvent(e.browserEvent || e);
1928        }
1929    };
1930
1931    Ext.EventObjectImpl.prototype = {
1932        
1933        browserEvent : null,
1934        
1935        button : -1,
1936        
1937        shiftKey : false,
1938        
1939        ctrlKey : false,
1940        
1941        altKey : false,
1942
1943        
1944        BACKSPACE: 8,
1945        
1946        TAB: 9,
1947        
1948        NUM_CENTER: 12,
1949        
1950        ENTER: 13,
1951        
1952        RETURN: 13,
1953        
1954        SHIFT: 16,
1955        
1956        CTRL: 17,
1957        CONTROL : 17, // legacy
1958        
1959        ALT: 18,
1960        
1961        PAUSE: 19,
1962        
1963        CAPS_LOCK: 20,
1964        
1965        ESC: 27,
1966        
1967        SPACE: 32,
1968        
1969        PAGE_UP: 33,
1970        PAGEUP : 33, // legacy
1971        
1972        PAGE_DOWN: 34,
1973        PAGEDOWN : 34, // legacy
1974        
1975        END: 35,
1976        
1977        HOME: 36,
1978        
1979        LEFT: 37,
1980        
1981        UP: 38,
1982        
1983        RIGHT: 39,
1984        
1985        DOWN: 40,
1986        
1987        PRINT_SCREEN: 44,
1988        
1989        INSERT: 45,
1990        
1991        DELETE: 46,
1992        
1993        ZERO: 48,
1994        
1995        ONE: 49,
1996        
1997        TWO: 50,
1998        
1999        THREE: 51,
2000        
2001        FOUR: 52,
2002        
2003        FIVE: 53,
2004        
2005        SIX: 54,
2006        
2007        SEVEN: 55,
2008        
2009        EIGHT: 56,
2010        
2011        NINE: 57,
2012        
2013        A: 65,
2014        
2015        B: 66,
2016        
2017        C: 67,
2018        
2019        D: 68,
2020        
2021        E: 69,
2022        
2023        F: 70,
2024        
2025        G: 71,
2026        
2027        H: 72,
2028        
2029        I: 73,
2030        
2031        J: 74,
2032        
2033        K: 75,
2034        
2035        L: 76,
2036        
2037        M: 77,
2038        
2039        N: 78,
2040        
2041        O: 79,
2042        
2043        P: 80,
2044        
2045        Q: 81,
2046        
2047        R: 82,
2048        
2049        S: 83,
2050        
2051        T: 84,
2052        
2053        U: 85,
2054        
2055        V: 86,
2056        
2057        W: 87,
2058        
2059        X: 88,
2060        
2061        Y: 89,
2062        
2063        Z: 90,
2064        
2065        CONTEXT_MENU: 93,
2066        
2067        NUM_ZERO: 96,
2068        
2069        NUM_ONE: 97,
2070        
2071        NUM_TWO: 98,
2072        
2073        NUM_THREE: 99,
2074        
2075        NUM_FOUR: 100,
2076        
2077        NUM_FIVE: 101,
2078        
2079        NUM_SIX: 102,
2080        
2081        NUM_SEVEN: 103,
2082        
2083        NUM_EIGHT: 104,
2084        
2085        NUM_NINE: 105,
2086        
2087        NUM_MULTIPLY: 106,
2088        
2089        NUM_PLUS: 107,
2090        
2091        NUM_MINUS: 109,
2092        
2093        NUM_PERIOD: 110,
2094        
2095        NUM_DIVISION: 111,
2096        
2097        F1: 112,
2098        
2099        F2: 113,
2100        
2101        F3: 114,
2102        
2103        F4: 115,
2104        
2105        F5: 116,
2106        
2107        F6: 117,
2108        
2109        F7: 118,
2110        
2111        F8: 119,
2112        
2113        F9: 120,
2114        
2115        F10: 121,
2116        
2117        F11: 122,
2118        
2119        F12: 123,
2120
2121           
2122        setEvent : function(e){
2123            if(e == this || (e && e.browserEvent)){ // already wrapped
2124                return e;
2125            }
2126            this.browserEvent = e;
2127            if(e){
2128                // normalize buttons
2129                this.button = e.button ? btnMap[e.button] : (e.which ? e.which-1 : -1);
2130                if(e.type == 'click' && this.button == -1){
2131                    this.button = 0;
2132                }
2133                this.type = e.type;
2134                this.shiftKey = e.shiftKey;
2135                // mac metaKey behaves like ctrlKey
2136                this.ctrlKey = e.ctrlKey || e.metaKey;
2137                this.altKey = e.altKey;
2138                // in getKey these will be normalized for the mac
2139                this.keyCode = e.keyCode;
2140                this.charCode = e.charCode;
2141                // cache the target for the delayed and or buffered events
2142                this.target = E.getTarget(e);
2143                // same for XY
2144                this.xy = E.getXY(e);
2145            }else{
2146                this.button = -1;
2147                this.shiftKey = false;
2148                this.ctrlKey = false;
2149                this.altKey = false;
2150                this.keyCode = 0;
2151                this.charCode = 0;
2152                this.target = null;
2153                this.xy = [0, 0];
2154            }
2155            return this;
2156        },
2157
2158        
2159        stopEvent : function(){
2160            if(this.browserEvent){
2161                if(this.browserEvent.type == 'mousedown'){
2162                    Ext.EventManager.stoppedMouseDownEvent.fire(this);
2163                }
2164                E.stopEvent(this.browserEvent);
2165            }
2166        },
2167
2168        
2169        preventDefault : function(){
2170            if(this.browserEvent){
2171                E.preventDefault(this.browserEvent);
2172            }
2173        },
2174
2175        
2176        isNavKeyPress : function(){
2177            var k = this.keyCode;
2178            k = Ext.isSafari ? (safariKeys[k] || k) : k;
2179            return (k >= 33 && k <= 40) || k == this.RETURN || k == this.TAB || k == this.ESC;
2180        },
2181
2182        isSpecialKey : function(){
2183            var k = this.keyCode;
2184            return (this.type == 'keypress' && this.ctrlKey) || k == 9 || k == 13  || k == 40 || k == 27 ||
2185            (k == 16) || (k == 17) ||
2186            (k >= 18 && k <= 20) ||
2187            (k >= 33 && k <= 35) ||
2188            (k >= 36 && k <= 39) ||
2189            (k >= 44 && k <= 45);
2190        },
2191
2192        
2193        stopPropagation : function(){
2194            if(this.browserEvent){
2195                if(this.browserEvent.type == 'mousedown'){
2196                    Ext.EventManager.stoppedMouseDownEvent.fire(this);
2197                }
2198                E.stopPropagation(this.browserEvent);
2199            }
2200        },
2201
2202        
2203        getCharCode : function(){
2204            return this.charCode || this.keyCode;
2205        },
2206
2207        
2208        getKey : function(){
2209            var k = this.keyCode || this.charCode;
2210            return Ext.isSafari ? (safariKeys[k] || k) : k;
2211        },
2212
2213        
2214        getPageX : function(){
2215            return this.xy[0];
2216        },
2217
2218        
2219        getPageY : function(){
2220            return this.xy[1];
2221        },
2222
2223        
2224        getTime : function(){
2225            if(this.browserEvent){
2226                return E.getTime(this.browserEvent);
2227            }
2228            return null;
2229        },
2230
2231        
2232        getXY : function(){
2233            return this.xy;
2234        },
2235
2236        
2237        getTarget : function(selector, maxDepth, returnEl){
2238            return selector ? Ext.fly(this.target).findParent(selector, maxDepth, returnEl) : (returnEl ? Ext.get(this.target) : this.target);
2239        },
2240
2241        
2242        getRelatedTarget : function(){
2243            if(this.browserEvent){
2244                return E.getRelatedTarget(this.browserEvent);
2245            }
2246            return null;
2247        },
2248
2249        
2250        getWheelDelta : function(){
2251            var e = this.browserEvent;
2252            var delta = 0;
2253            if(e.wheelDelta){ 
2254                delta = e.wheelDelta/120;
2255            }else if(e.detail){ 
2256                delta = -e.detail/3;
2257            }
2258            return delta;
2259        },
2260
2261        
2262        hasModifier : function(){
2263            return ((this.ctrlKey || this.altKey) || this.shiftKey) ? true : false;
2264        },
2265
2266        
2267        within : function(el, related, allowEl){
2268            var t = this[related ? "getRelatedTarget" : "getTarget"]();
2269            return t && ((allowEl ? (t === Ext.getDom(el)) : false) || Ext.fly(el).contains(t));
2270        },
2271
2272        getPoint : function(){
2273            return new Ext.lib.Point(this.xy[0], this.xy[1]);
2274        }
2275    };
2276
2277    return new Ext.EventObjectImpl();
2278}();
2279
2280(function(){
2281var D = Ext.lib.Dom;
2282var E = Ext.lib.Event;
2283var A = Ext.lib.Anim;
2284
2285// local style camelizing for speed
2286var propCache = {};
2287var camelRe = /(-[a-z])/gi;
2288var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
2289var view = document.defaultView;
2290
2291Ext.Element = function(element, forceNew){
2292    var dom = typeof element == "string" ?
2293            document.getElementById(element) : element;
2294    if(!dom){ // invalid id/element
2295        return null;
2296    }
2297    var id = dom.id;
2298    if(forceNew !== true && id && Ext.Element.cache[id]){ // element object already exists
2299        return Ext.Element.cache[id];
2300    }
2301
2302    
2303    this.dom = dom;
2304
2305    
2306    this.id = id || Ext.id(dom);
2307};
2308
2309var El = Ext.Element;
2310
2311El.prototype = {
2312    
2313    originalDisplay : "",
2314
2315    visibilityMode : 1,
2316    
2317    defaultUnit : "px",
2318    
2319    setVisibilityMode : function(visMode){
2320        this.visibilityMode = visMode;
2321        return this;
2322    },
2323    
2324    enableDisplayMode : function(display){
2325        this.setVisibilityMode(El.DISPLAY);
2326        if(typeof display != "undefined") this.originalDisplay = display;
2327        return this;
2328    },
2329
2330    
2331    findParent : function(simpleSelector, maxDepth, returnEl){
2332        var p = this.dom, b = document.body, depth = 0, dq = Ext.DomQuery, stopEl;
2333        maxDepth = maxDepth || 50;
2334        if(typeof maxDepth != "number"){
2335            stopEl = Ext.getDom(maxDepth);
2336            maxDepth = 10;
2337        }
2338        while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
2339            if(dq.is(p, simpleSelector)){
2340                return returnEl ? Ext.get(p) : p;
2341            }
2342            depth++;
2343            p = p.parentNode;
2344        }
2345        return null;
2346    },
2347
2348
2349    
2350    findParentNode : function(simpleSelector, maxDepth, returnEl){
2351        var p = Ext.fly(this.dom.parentNode, '_internal');
2352        return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
2353    },
2354
2355    
2356    up : function(simpleSelector, maxDepth){
2357        return this.findParentNode(simpleSelector, maxDepth, true);
2358    },
2359
2360
2361
2362    
2363    is : function(simpleSelector){
2364        return Ext.DomQuery.is(this.dom, simpleSelector);
2365    },
2366
2367    
2368    animate : function(args, duration, onComplete, easing, animType){
2369        this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
2370        return this;
2371    },
2372
2373    
2374    anim : function(args, opt, animType, defaultDur, defaultEase, cb){
2375        animType = animType || 'run';
2376        opt = opt || {};
2377        var anim = Ext.lib.Anim[animType](
2378            this.dom, args,
2379            (opt.duration || defaultDur) || .35,
2380            (opt.easing || defaultEase) || 'easeOut',
2381            function(){
2382                Ext.callback(cb, this);
2383                Ext.callback(opt.callback, opt.scope || this, [this, opt]);
2384            },
2385            this
2386        );
2387        opt.anim = anim;
2388        return anim;
2389    },
2390
2391    // private legacy anim prep
2392    preanim : function(a, i){
2393        return !a[i] ? false : (typeof a[i] == "object" ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
2394    },
2395
2396    
2397    clean : function(forceReclean){
2398        if(this.isCleaned && forceReclean !== true){
2399            return this;
2400        }
2401        var ns = /\S/;
2402        var d = this.dom, n = d.firstChild, ni = -1;
2403 	    while(n){
2404 	        var nx = n.nextSibling;
2405 	        if(n.nodeType == 3 && !ns.test(n.nodeValue)){
2406 	            d.removeChild(n);
2407 	        }else{
2408 	            n.nodeIndex = ++ni;
2409 	        }
2410 	        n = nx;
2411 	    }
2412 	    this.isCleaned = true;
2413 	    return this;
2414 	},
2415
2416    
2417    scrollIntoView : function(container, hscroll){
2418        var c = Ext.getDom(container) || Ext.getBody().dom;
2419        var el = this.dom;
2420
2421        var o = this.getOffsetsTo(c),
2422            l = o[0] + c.scrollLeft,
2423            t = o[1] + c.scrollTop,
2424            b = t+el.offsetHeight,
2425            r = l+el.offsetWidth;
2426
2427        var ch = c.clientHeight;
2428        var ct = parseInt(c.scrollTop, 10);
2429        var cl = parseInt(c.scrollLeft, 10);
2430        var cb = ct + ch;
2431        var cr = cl + c.clientWidth;
2432
2433        if(el.offsetHeight > ch || t < ct){
2434        	c.scrollTop = t;
2435        }else if(b > cb){
2436            c.scrollTop = b-ch;
2437        }
2438        c.scrollTop = c.scrollTop; // corrects IE, other browsers will ignore
2439
2440        if(hscroll !== false){
2441			if(el.offsetWidth > c.clientWidth || l < cl){
2442                c.scrollLeft = l;
2443            }else if(r > cr){
2444                c.scrollLeft = r-c.clientWidth;
2445            }
2446            c.scrollLeft = c.scrollLeft;
2447        }
2448        return this;
2449    },
2450
2451    // private
2452    scrollChildIntoView : function(child, hscroll){
2453        Ext.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
2454    },
2455
2456    
2457    autoHeight : function(animate, duration, onComplete, easing){
2458        var oldHeight = this.getHeight();
2459        this.clip();
2460        this.setHeight(1); // force clipping
2461        setTimeout(function(){
2462            var height = parseInt(this.dom.scrollHeight, 10); // parseInt for Safari
2463            if(!animate){
2464                this.setHeight(height);
2465                this.unclip();
2466                if(typeof onComplete == "function"){
2467                    onComplete();
2468                }
2469            }else{
2470                this.setHeight(oldHeight); // restore original height
2471                this.setHeight(height, animate, duration, function(){
2472                    this.unclip();
2473                    if(typeof onComplete == "function") onComplete();
2474                }.createDelegate(this), easing);
2475            }
2476        }.createDelegate(this), 0);
2477        return this;
2478    },
2479
2480    
2481    contains : function(el){
2482        if(!el){return false;}
2483        return D.isAncestor(this.dom, el.dom ? el.dom : el);
2484    },
2485
2486    
2487    isVisible : function(deep) {
2488        var vis = !(this.getStyle("visibility") == "hidden" || this.get
2488Style("display") == "none");
2489        if(deep !== true || !vis){
2490            return vis;
2491        }
2492        var p = this.dom.parentNode;
2493        while(p && p.tagName.toLowerCase() != "body"){
2494            if(!Ext.fly(p, '_isVisible').isVisible()){
2495                return false;
2496            }
2497            p = p.parentNode;
2498        }
2499        return true;
2500    },
2501
2502    
2503    select : function(selector, unique){
2504        return El.select(selector, unique, this.dom);
2505    },
2506
2507    
2508    query : function(selector){
2509        return Ext.DomQuery.select(selector, this.dom);
2510    },
2511
2512    
2513    child : function(selector, returnDom){
2514        var n = Ext.DomQuery.selectNode(selector, this.dom);
2515        return returnDom ? n : Ext.get(n);
2516    },
2517
2518    
2519    down : function(selector, returnDom){
2520        var n = Ext.DomQuery.selectNode(" > " + selector, this.dom);
2521        return returnDom ? n : Ext.get(n);
2522    },
2523
2524    
2525    initDD : function(group, config, overrides){
2526        var dd = new Ext.dd.DD(Ext.id(this.dom), group, config);
2527        return Ext.apply(dd, overrides);
2528    },
2529
2530    
2531    initDDProxy : function(group, config, overrides){
2532        var dd = new Ext.dd.DDProxy(Ext.id(this.dom), group, config);
2533        return Ext.apply(dd, overrides);
2534    },
2535
2536    
2537    initDDTarget : function(group, config, overrides){
2538        var dd = new Ext.dd.DDTarget(Ext.id(this.dom), group, config);
2539        return Ext.apply(dd, overrides);
2540    },
2541
2542    
2543     setVisible : function(visible, animate){
2544        if(!animate || !A){
2545            if(this.visibilityMode == El.DISPLAY){
2546                this.setDisplayed(visible);
2547            }else{
2548                this.fixDisplay();
2549                this.dom.style.visibility = visible ? "visible" : "hidden";
2550            }
2551        }else{
2552            // closure for composites
2553            var dom = this.dom;
2554            var visMode = this.visibilityMode;
2555            if(visible){
2556                this.setOpacity(.01);
2557                this.setVisible(true);
2558            }
2559            this.anim({opacity: { to: (visible?1:0) }},
2560                  this.preanim(arguments, 1),
2561                  null, .35, 'easeIn', function(){
2562                     if(!visible){
2563                         if(visMode == El.DISPLAY){
2564                             dom.style.display = "none";
2565                         }else{
2566                             dom.style.visibility = "hidden";
2567                         }
2568                         Ext.get(dom).setOpacity(1);
2569                     }
2570                 });
2571        }
2572        return this;
2573    },
2574
2575    
2576    isDisplayed : function() {
2577        return this.getStyle("display") != "none";
2578    },
2579
2580    
2581    toggle : function(animate){
2582        this.setVisible(!this.isVisible(), this.preanim(arguments, 0));
2583        return this;
2584    },
2585
2586    
2587    setDisplayed : function(value) {
2588        if(typeof value == "boolean"){
2589           value = value ? this.originalDisplay : "none";
2590        }
2591        this.setStyle("display", value);
2592        return this;
2593    },
2594
2595    
2596    focus : function() {
2597        try{
2598            this.dom.focus();
2599        }catch(e){}
2600        return this;
2601    },
2602
2603    
2604    blur : function() {
2605        try{
2606            this.dom.blur();
2607        }catch(e){}
2608        return this;
2609    },
2610
2611    
2612    addClass : function(className){
2613        if(Ext.isArray(className)){
2614            for(var i = 0, len = className.length; i < len; i++) {
2615            	this.addClass(className[i]);
2616            }
2617        }else{
2618            if(className && !this.hasClass(className)){
2619                this.dom.className = this.dom.className + " " + className;
2620            }
2621        }
2622        return this;
2623    },
2624
2625    
2626    radioClass : function(className){
2627        var siblings = this.dom.parentNode.childNodes;
2628        for(var i = 0; i < siblings.length; i++) {
2629        	var s = siblings[i];
2630        	if(s.nodeType == 1){
2631        	    Ext.get(s).removeClass(className);
2632        	}
2633        }
2634        this.addClass(className);
2635        return this;
2636    },
2637
2638    
2639    removeClass : function(className){
2640        if(!className || !this.dom.className){
2641            return this;
2642        }
2643        if(Ext.isArray(className)){
2644            for(var i = 0, len = className.length; i < len; i++) {
2645            	this.removeClass(className[i]);
2646            }
2647        }else{
2648            if(this.hasClass(className)){
2649                var re = this.classReCache[className];
2650                if (!re) {
2651                   re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");
2652                   this.classReCache[className] = re;
2653                }
2654                this.dom.className =
2655                    this.dom.className.replace(re, " ");
2656            }
2657        }
2658        return this;
2659    },
2660
2661    // private
2662    classReCache: {},
2663
2664    
2665    toggleClass : function(className){
2666        if(this.hasClass(className)){
2667            this.removeClass(className);
2668        }else{
2669            this.addClass(className);
2670        }
2671        return this;
2672    },
2673
2674    
2675    hasClass : function(className){
2676        return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
2677    },
2678
2679    
2680    replaceClass : function(oldClassName, newClassName){
2681        this.removeClass(oldClassName);
2682        this.addClass(newClassName);
2683        return this;
2684    },
2685
2686    
2687    getStyles : function(){
2688        var a = arguments, len = a.length, r = {};
2689        for(var i = 0; i < len; i++){
2690            r[a[i]] = this.getStyle(a[i]);
2691        }
2692        return r;
2693    },
2694
2695    
2696    getStyle : function(){
2697        return view && view.getComputedStyle ?
2698            function(prop){
2699                var el = this.dom, v, cs, camel;
2700                if(prop == 'float'){
2701                    prop = "cssFloat";
2702                }
2703                if(v = el.style[prop]){
2704                    return v;
2705                }
2706                if(cs = view.getComputedStyle(el, "")){
2707                    if(!(camel = propCache[prop])){
2708                        camel = propCache[prop] = prop.replace(camelRe, camelFn);
2709                    }
2710                    return cs[camel];
2711                }
2712                return null;
2713            } :
2714            function(prop){
2715                var el = this.dom, v, cs, camel;
2716                if(prop == 'opacity'){
2717                    if(typeof el.style.filter == 'string'){
2718                        var m = el.style.filter.match(/alpha\(opacity=(.*)\)/i);
2719                        if(m){
2720                            var fv = parseFloat(m[1]);
2721                            if(!isNaN(fv)){
2722                                return fv ? fv / 100 : 0;
2723                            }
2724                        }
2725                    }
2726                    return 1;
2727                }else if(prop == 'float'){
2728                    prop = "styleFloat";
2729                }
2730                if(!(camel = propCache[prop])){
2731                    camel = propCache[prop] = prop.replace(camelRe, camelFn);
2732                }
2733                if(v = el.style[camel]){
2734                    return v;
2735                }
2736                if(cs = el.currentStyle){
2737                    return cs[camel];
2738                }
2739                return null;
2740            };
2741    }(),
2742
2743    
2744    setStyle : function(prop, value){
2745        if(typeof prop == "string"){
2746            var camel;
2747            if(!(camel = propCache[prop])){
2748                camel = propCache[prop] = prop.replace(camelRe, camelFn);
2749            }
2750            if(camel == 'opacity') {
2751                this.setOpacity(value);
2752            }else{
2753                this.dom.style[camel] = value;
2754            }
2755        }else{
2756            for(var style in prop){
2757                if(typeof prop[style] != "function"){
2758                   this.setStyle(style, prop[style]);
2759                }
2760            }
2761        }
2762        return this;
2763    },
2764
2765    
2766    applyStyles : function(style){
2767        Ext.DomHelper.applyStyles(this.dom, style);
2768        return this;
2769    },
2770
2771    
2772    getX : function(){
2773        return D.getX(this.dom);
2774    },
2775
2776    
2777    getY : function(){
2778        return D.getY(this.dom);
2779    },
2780
2781    
2782    getXY : function(){
2783        return D.getXY(this.dom);
2784    },
2785
2786    
2787    getOffsetsTo : function(el){
2788        var o = this.getXY();
2789        var e = Ext.fly(el, '_internal').getXY();
2790        return [o[0]-e[0],o[1]-e[1]];
2791    },
2792
2793    
2794    setX : function(x, animate){
2795        if(!animate || !A){
2796            D.setX(this.dom, x);
2797        }else{
2798            this.setXY([x, this.getY()], this.preanim(arguments, 1));
2799        }
2800        return this;
2801    },
2802
2803    
2804    setY : function(y, animate){
2805        if(!animate || !A){
2806            D.setY(this.dom, y);
2807        }else{
2808            this.setXY([this.getX(), y], this.preanim(arguments, 1));
2809        }
2810        return this;
2811    },
2812
2813    
2814    setLeft : function(left){
2815        this.setStyle("left", this.addUnits(left));
2816        return this;
2817    },
2818
2819    
2820    setTop : function(top){
2821        this.setStyle("top", this.addUnits(top));
2822        return this;
2823    },
2824
2825    
2826    setRight : function(right){
2827        this.setStyle("right", this.addUnits(right));
2828        return this;
2829    },
2830
2831    
2832    setBottom : function(bottom){
2833        this.setStyle("bottom", this.addUnits(bottom));
2834        return this;
2835    },
2836
2837    
2838    setXY : function(pos, animate){
2839        if(!animate || !A){
2840            D.setXY(this.dom, pos);
2841        }else{
2842            this.anim({points: {to: pos}}, this.preanim(arguments, 1), 'motion');
2843        }
2844        return this;
2845    },
2846
2847    
2848    setLocation : function(x, y, animate){
2849        this.setXY([x, y], this.preanim(arguments, 2));
2850        return this;
2851    },
2852
2853    
2854    moveTo : function(x, y, animate){
2855        this.setXY([x, y], this.preanim(arguments, 2));
2856        return this;
2857    },
2858
2859    
2860    getRegion : function(){
2861        return D.getRegion(this.dom);
2862    },
2863
2864    
2865    getHeight : function(contentHeight){
2866        var h = this.dom.offsetHeight || 0;
2867        h = contentHeight !== true ? h : h-this.getBorderWidth("tb")-this.getPadding("tb");
2868        return h < 0 ? 0 : h;
2869    },
2870
2871    
2872    getWidth : function(contentWidth){
2873        var w = this.dom.offsetWidth || 0;
2874        w = contentWidth !== true ? w : w-this.getBorderWidth("lr")-this.getPadding("lr");
2875        return w < 0 ? 0 : w;
2876    },
2877
2878    
2879    getComputedHeight : function(){
2880        var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);
2881        if(!h){
2882            h = parseInt(this.getStyle('height'), 10) || 0;
2883            if(!this.isBorderBox()){
2884                h += this.getFrameWidth('tb');
2885            }
2886        }
2887        return h;
2888    },
2889
2890    
2891    getComputedWidth : function(){
2892        var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
2893        if(!w){
2894            w = parseInt(this.getStyle('width'), 10) || 0;
2895            if(!this.isBorderBox()){
2896                w += this.getFrameWidth('lr');
2897            }
2898        }
2899        return w;
2900    },
2901
2902    
2903    getSize : function(contentSize){
2904        return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
2905    },
2906
2907    getStyleSize : function(){
2908        var w, h, d = this.dom, s = d.style;
2909        if(s.width && s.width != 'auto'){
2910            w = parseInt(s.width, 10);
2911            if(Ext.isBorderBox){
2912               w -= this.getFrameWidth('lr');
2913            }
2914        }
2915        if(s.height && s.height != 'auto'){
2916            h = parseInt(s.height, 10);
2917            if(Ext.isBorderBox){
2918               h -= this.getFrameWidth('tb');
2919            }
2920        }
2921        return {width: w || this.getWidth(true), height: h || this.getHeight(true)};
2922
2923    },
2924
2925    
2926    getViewSize : function(){
2927        var d = this.dom, doc = document, aw = 0, ah = 0;
2928        if(d == doc || d == doc.body){
2929            return {width : D.getViewWidth(), height: D.getViewHeight()};
2930        }else{
2931            return {
2932                width : d.clientWidth,
2933                height: d.clientHeight
2934            };
2935        }
2936    },
2937
2938    
2939    getValue : function(asNumber){
2940        return asNumber ? parseInt(this.dom.value, 10) : this.dom.value;
2941    },
2942
2943    // private
2944    adjustWidth : function(width){
2945        if(typeof width == "number"){
2946            if(this.autoBoxAdjust && !this.isBorderBox()){
2947               width -= (this.getBorderWidth("lr") + this.getPadding("lr"));
2948            }
2949            if(width < 0){
2950                width = 0;
2951            }
2952        }
2953        return width;
2954    },
2955
2956    // private
2957    adjustHeight : function(height){
2958        if(typeof height == "number"){
2959           if(this.autoBoxAdjust && !this.isBorderBox()){
2960               height -= (this.getBorderWidth("tb") + this.getPadding("tb"));
2961           }
2962           if(height < 0){
2963               height = 0;
2964           }
2965        }
2966        return height;
2967    },
2968
2969    
2970    setWidth : function(width, animate){
2971        width = this.adjustWidth(width);
2972        if(!animate || !A){
2973            this.dom.style.width = this.addUnits(width);
2974        }else{
2975            this.anim({width: {to: width}}, this.preanim(arguments, 1));
2976        }
2977        return this;
2978    },
2979
2980    
2981     setHeight : function(height, animate){
2982        height = this.adjustHeight(height);
2983        if(!animate || !A){
2984            this.dom.style.height = this.addUnits(height);
2985        }else{
2986            this.anim({height: {to: height}}, this.preanim(arguments, 1));
2987        }
2988        return this;
2989    },
2990
2991    
2992     setSize : function(width, height, animate){
2993        if(typeof width == "object"){ // in case of object from getSize()
2994            height = width.height; width = width.width;
2995        }
2996        width = this.adjustWidth(width); height = this.adjustHeight(height);
2997        if(!animate || !A){
2998            this.dom.style.width = this.addUnits(width);
2999            this.dom.style.height = this.addUnits(height);
3000        }else{
3001            this.anim({width: {to: width}, height: {to: height}}, this.preanim(arguments, 2));
3002        }
3003        return this;
3004    },
3005
3006    
3007    setBounds : function(x, y, width, height, animate){
3008        if(!animate || !A){
3009            this.setSize(width, height);
3010            this.setLocation(x, y);
3011        }else{
3012            width = this.adjustWidth(width); height = this.adjustHeight(height);
3013            this.anim({points: {to: [x, y]}, width: {to: width}, height: {to: height}},
3014                          this.preanim(arguments, 4), 'motion');
3015        }
3016        return this;
3017    },
3018
3019    
3020    setRegion : function(region, animate){
3021        this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.preanim(arguments, 1));
3022        return this;
3023    },
3024
3025    
3026    addListener : function(eventName, fn, scope, options){
3027        Ext.EventManager.on(this.dom,  eventName, fn, scope || this, options);
3028    },
3029
3030    
3031    removeListener : function(eventName, fn, scope){
3032        Ext.EventManager.removeListener(this.dom,  eventName, fn, scope || this);
3033        return this;
3034    },
3035
3036    
3037    removeAllListeners : function(){
3038        Ext.EventManager.removeAll(this.dom);
3039        return this;
3040    },
3041
3042    
3043    relayEvent : function(eventName, observable){
3044        this.on(eventName, function(e){
3045            observable.fireEvent(eventName, e);
3046        });
3047    },
3048
3049    
3050     setOpacity : function(opacity, animate){
3051        if(!animate || !A){
3052            var s = this.dom.style;
3053            if(Ext.isIE){
3054                s.zoom = 1;
3055                s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +
3056                           (opacity == 1 ? "" : " alpha(opacity=" + opacity * 100 + ")");
3057            }else{
3058                s.opacity = opacity;
3059            }
3060        }else{
3061            this.anim({opacity: {to: opacity}}, this.preanim(arguments, 1), null, .35, 'easeIn');
3062        }
3063        return this;
3064    },
3065
3066    
3067    getLeft : function(local){
3068        if(!local){
3069            return this.getX();
3070        }else{
3071            return parseInt(this.getStyle("left"), 10) || 0;
3072        }
3073    },
3074
3075    
3076    getRight : function(local){
3077        if(!local){
3078            return this.getX() + this.getWidth();
3079        }else{
3080            return (this.getLeft(true) + this.getWidth()) || 0;
3081        }
3082    },
3083
3084    
3085    getTop : function(local) {
3086        if(!local){
3087            return this.getY();
3088        }else{
3089            return parseInt(this.getStyle("top"), 10) || 0;
3090        }
3091    },
3092
3093    
3094    getBottom : function(local){
3095        if(!local){
3096            return this.getY() + this.getHeight();
3097        }else{
3098            return (this.getTop(true) + this.getHeight()) || 0;
3099        }
3100    },
3101
3102    
3103    position : function(pos, zIndex, x, y){
3104        if(!pos){
3105           if(this.getStyle('position') == 'static'){
3106               this.setStyle('position', 'relative');
3107           }
3108        }else{
3109            this.setStyle("position", pos);
3110        }
3111        if(zIndex){
3112            this.setStyle("z-index", zIndex);
3113        }
3114        if(x !== undefined && y !== undefined){
3115            this.setXY([x, y]);
3116        }else if(x !== undefined){
3117            this.setX(x);
3118        }else if(y !== undefined){
3119            this.setY(y);
3120        }
3121    },
3122
3123    
3124    clearPositioning : function(value){
3125        value = value ||'';
3126        this.setStyle({
3127            "left": value,
3128            "right": value,
3129            "top": value,
3130            "bottom": value,
3131            "z-index": "",
3132            "position" : "static"
3133        });
3134        return this;
3135    },
3136
3137    
3138    getPositioning : function(){
3139        var l = this.getStyle("left");
3140        var t = this.getStyle("top");
3141        return {
3142            "position" : this.getStyle("position"),
3143            "left" : l,
3144            "right" : l ? "" : this.getStyle("right"),
3145            "top" : t,
3146            "bottom" : t ? "" : this.getStyle("bottom"),
3147            "z-index" : this.getStyle("z-index")
3148        };
3149    },
3150
3151    
3152    getBorderWidth : function(side){
3153        return this.addStyles(side, El.borders);
3154    },
3155
3156    
3157    getPadding : function(side){
3158        return this.addStyles(side, El.paddings);
3159    },
3160
3161    
3162    setPositioning : function(pc){
3163        this.applyStyles(pc);
3164        if(pc.right == "auto"){
3165            this.dom.style.right = "";
3166        }
3167        if(pc.bottom == "auto"){
3168            this.dom.style.bottom = "";
3169        }
3170        return this;
3171    },
3172
3173    // private
3174    fixDisplay : function(){
3175        if(this.getStyle("display") == "none"){
3176            this.setStyle("visibility", "hidden");
3177            this.setStyle("display", this.originalDisplay); // first try reverting to default
3178            if(this.getStyle("display") == "none"){ // if that fails, default to block
3179                this.setStyle("display", "block");
3180            }
3181        }
3182    },
3183
3184    // private
3185	setOverflow : function(v){
3186    	if(v=='auto' && Ext.isMac && Ext.isGecko2){ // work around stupid FF 2.0/Mac scroll bar bug
3187    		this.dom.style.overflow = 'hidden';
3188        	(function(){this.dom.style.overflow = 'auto';}).defer(1, this);
3189    	}else{
3190    		this.dom.style.overflow = v;
3191    	}
3192	},
3193
3194    
3195     setLeftTop : function(left, top){
3196        this.dom.style.left = this.addUnits(left);
3197        this.dom.style.top = this.addUnits(top);
3198        return this;
3199    },
3200
3201    
3202     move : function(direction, distance, animate){
3203        var xy = this.getXY();
3204        direction = direction.toLowerCase();
3205        switch(direction){
3206            case "l":
3207            case "left":
3208                this.moveTo(xy[0]-distance, xy[1], this.preanim(arguments, 2));
3209                break;
3210           case "r":
3211           case "right":
3212                this.moveTo(xy[0]+distance, xy[1], this.preanim(arguments, 2));
3213                break;
3214           case "t":
3215           case "top":
3216           case "up":
3217                this.moveTo(xy[0], xy[1]-distance, this.preanim(arguments, 2));
3218                break;
3219           case "b":
3220           case "bottom":
3221           case "down":
3222                this.moveTo(xy[0], xy[1]+distance, this.preanim(arguments, 2));
3223                break;
3224        }
3225        return this;
3226    },
3227
3228    
3229    clip : function(){
3230        if(!this.isClipped){
3231           this.isClipped = true;
3232           this.originalClip = {
3233               "o": this.getStyle("overflow"),
3234               "x": this.getStyle("overflow-x"),
3235               "y": this.getStyle("overflow-y")
3236           };
3237           this.setStyle("overflow", "hidden");
3238           this.setStyle("overflow-x", "hidden");
3239           this.setStyle("overflow-y", "hidden");
3240        }
3241        return this;
3242    },
3243
3244    
3245    unclip : function(){
3246        if(this.isClipped){
3247            this.isClipped = false;
3248            var o = this.originalClip;
3249            if(o.o){this.setStyle("overflow", o.o);}
3250            if(o.x){this.setStyle("overflow-x", o.x);}
3251            if(o.y){this.setStyle("overflow-y", o.y);}
3252        }
3253        return this;
3254    },
3255
3256
3257    
3258    getAnchorXY : function(anchor, local, s){
3259        //Passing a different size is useful for pre-calculating anchors,
3260        //especially for anchored animations that change the el size.
3261
3262        var w, h, vp = false;
3263        if(!s){
3264            var d = this.dom;
3265            if(d == document.body || d == document){
3266                vp = true;
3267                w = D.getViewWidth(); h = D.getViewHeight();
3268            }else{
3269                w = this.getWidth(); h = this.getHeight();
3270            }
3271        }else{
3272            w = s.width;  h = s.height;
3273        }
3274        var x = 0, y = 0, r = Math.round;
3275        switch((anchor || "tl").toLowerCase()){
3276            case "c":
3277                x = r(w*.5);
3278                y = r(h*.5);
3279            break;
3280            case "t":
3281                x = r(w*.5);
3282                y = 0;
3283            break;
3284            case "l":
3285                x = 0;
3286                y = r(h*.5);
3287            break;
3288            case "r":
3289                x = w;
3290                y = r(h*.5);
3291            break;
3292            case "b":
3293                x = r(w*.5);
3294                y = h;
3295            break;
3296            case "tl":
3297                x = 0;
3298                y = 0;
3299            break;
3300            case "bl":
3301                x = 0;
3302                y = h;
3303            break;
3304            case "br":
3305                x = w;
3306                y = h;
3307            break;
3308            case "tr":
3309                x = w;
3310                y = 0;
3311            break;
3312        }
3313        if(local === true){
3314            return [x, y];
3315        }
3316        if(vp){
3317            var sc = this.getScroll();
3318            return [x + sc.left, y + sc.top];
3319        }
3320        //Add the element's offset xy
3321        var o = this.getXY();
3322        return [x+o[0], y+o[1]];
3323    },
3324
3325    
3326    getAlignToXY : function(el, p, o){
3327        el = Ext.get(el);
3328        if(!el || !el.dom){
3329            throw "Element.alignToXY with an element that doesn't exist";
3330        }
3331        var d = this.dom;
3332        var c = false; //constrain to viewport
3333        var p1 = "", p2 = "";
3334        o = o || [0,0];
3335
3336        if(!p){
3337            p = "tl-bl";
3338        }else if(p == "?"){
3339            p = "tl-bl?";
3340        }else if(p.indexOf("-") == -1){
3341            p = "tl-" + p;
3342        }
3343        p = p.toLowerCase();
3344        var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
3345        if(!m){
3346           throw "Element.alignTo with an invalid alignment " + p;
3347        }
3348        p1 = m[1]; p2 = m[2]; c = !!m[3];
3349
3350        //Subtract the aligned el's internal xy from the target's offset xy
3351        //plus custom offset to get the aligned el's new offset xy
3352        var a1 = this.getAnchorXY(p1, true);
3353        var a2 = el.getAnchorXY(p2, false);
3354
3355        var x = a2[0] - a1[0] + o[0];
3356        var y = a2[1] - a1[1] + o[1];
3357
3358        if(c){
3359            //constrain the aligned el to viewport if necessary
3360            var w = this.getWidth(), h = this.getHeight(), r = el.getRegion();
3361            // 5px of margin for ie
3362            var dw = D.getViewWidth()-5, dh = D.getViewHeight()-5;
3363
3364            //If we are at a viewport boundary and the aligned el is anchored on a target border that is
3365            //perpendicular to the vp border, allow the aligned el to slide on that border,
3366            //otherwise swap the aligned el to the opposite border of the target.
3367            var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);
3368           var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);
3369           var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
3370           var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
3371
3372           var doc = document;
3373           var scrollX = (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0)+5;
3374           var scrollY = (doc.documentElement.scrollTop || doc.body.scrollTop || 0)+5;
3375
3376           if((x+w) > dw + scrollX){
3377                x = swapX ? r.left-w : dw+scrollX-w;
3378            }
3379           if(x < scrollX){
3380               x = swapX ? r.right : scrollX;
3381           }
3382           if((y+h) > dh + scrollY){
3383                y = swapY ? r.top-h : dh+scrollY-h;
3384            }
3385           if (y < scrollY){
3386               y = swapY ? r.bottom : scrollY;
3387           }
3388        }
3389        return [x,y];
3390    },
3391
3392    // private
3393    getConstrainToXY : function(){
3394        var os = {top:0, left:0, bottom:0, right: 0};
3395
3396        return function(el, local, offsets, proposedXY){
3397            el = Ext.get(el);
3398            offsets = offsets ? Ext.applyIf(offsets, os) : os;
3399
3400            var vw, vh, vx = 0, vy = 0;
3401            if(el.dom == document.body || el.dom == document){
3402                vw = Ext.lib.Dom.getViewWidth();
3403                vh = Ext.lib.Dom.getViewHeight();
3404            }else{
3405                vw = el.dom.clientWidth;
3406                vh = el.dom.clientHeight;
3407                if(!local){
3408                    var vxy = el.getXY();
3409                    vx = vxy[0];
3410                    vy = vxy[1];
3411                }
3412            }
3413
3414            var s = el.getScroll();
3415
3416            vx += offsets.left + s.left;
3417            vy += offsets.top + s.top;
3418
3419            vw -= offsets.right;
3420            vh -= offsets.bottom;
3421
3422            var vr = vx+vw;
3423            var vb = vy+vh;
3424
3425            var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
3426            var x = xy[0], y = xy[1];
3427            var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
3428
3429            // only move it if it needs it
3430            var moved = false;
3431
3432            // first validate right/bottom
3433            if((x + w) > vr){
3434                x = vr - w;
3435                moved = true;
3436            }
3437            if((y + h) > vb){
3438                y = vb - h;
3439                moved = true;
3440            }
3441            // then make sure top/left isn't negative
3442            if(x < vx){
3443                x = vx;
3444                moved = true;
3445            }
3446            if(y < vy){
3447                y = vy;
3448                moved = true;
3449            }
3450            return moved ? [x, y] : false;
3451        };
3452    }(),
3453
3454    // private
3455    adjustForConstraints : function(xy, parent, offsets){
3456        return this.getConstrainToXY(parent || document, false, offsets, xy) ||  xy;
3457    },
3458
3459    
3460    alignTo : function(element, position, offsets, animate){
3461        var xy = this.getAlignToXY(element, position, offsets);
3462        this.setXY(xy, this.preanim(arguments, 3));
3463        return this;
3464    },
3465
3466    
3467    anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
3468        var action = function(){
3469            this.alignTo(el, alignment, offsets, animate);
3470            Ext.callback(callback, this);
3471        };
3472        Ext.EventManager.onWindowResize(action, this);
3473        var tm = typeof monitorScroll;
3474        if(tm != 'undefined'){
3475            Ext.EventManager.on(window, 'scroll', action, this,
3476                {buffer: tm == 'number' ? monitorScroll : 50});
3477        }
3478        action.call(this); // align immediately
3479        return this;
3480    },
3481    
3482    clearOpacity : function(){
3483        if (window.ActiveXObject) {
3484            if(typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)){
3485                this.dom.style.filter = "";
3486            }
3487        } else {
3488            this.dom.style.opacity = "";
3489            this.dom.style["-moz-opacity"] = "";
3490            this.dom.style["-khtml-opacity"] = "";
3491        }
3492        return this;
3493    },
3494
3495    
3496    hide : function(animate){
3497        this.setVisible(false, this.preanim(arguments, 0));
3498        return this;
3499    },
3500
3501    
3502    show : function(animate){
3503        this.setVisible(true, this.preanim(arguments, 0));
3504        return this;
3505    },
3506
3507    
3508    addUnits : function(size){
3509        return Ext.Element.addUnits(size, this.defaultUnit);
3510    },
3511
3512    
3513    update : function(html, loadScripts, callback){
3514        if(typeof html == "undefined"){
3515            html = "";
3516        }
3517        if(loadScripts !== true){
3518            this.dom.innerHTML = html;
3519            if(typeof callback == "function"){
3520                callback();
3521            }
3522            return this;
3523        }
3524        var id = Ext.id();
3525        var dom = this.dom;
3526
3527        html += '<span id="' + id + '"></span>';
3528
3529        E.onAvailable(id, function(){
3530            var hd = document.getElementsByTagName("head")[0];
3531            var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
3532            var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
3533            var typeRe = /\stype=([\'\"])(.*?)\1/i;
3534
3535            var match;
3536            while(match = re.exec(html)){
3537                var attrs = match[1];
3538                var srcMatch = attrs ? attrs.match(srcRe) : false;
3539                if(srcMatch && srcMatch[2]){
3540                   var s = document.createElement("script");
3541                   s.src = srcMatch[2];
3542                   var typeMatch = attrs.match(typeRe);
3543                   if(typeMatch && typeMatch[2]){
3544                       s.type = typeMatch[2];
3545                   }
3546                   hd.appendChild(s);
3547                }else if(match[2] && match[2].length > 0){
3548                    if(window.execScript) {
3549                       window.execScript(match[2]);
3550                    } else {
3551                       window.eval(match[2]);
3552                    }
3553                }
3554            }
3555            var el = document.getElementById(id);
3556            if(el){Ext.removeNode(el);}
3557            if(typeof callback == "function"){
3558                callback();
3559            }
3560        });
3561        dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
3562        return this;
3563    },
3564
3565    
3566    load : function(){
3567        var um = this.getUpdater();
3568        um.update.apply(um, arguments);
3569        return this;
3570    },
3571
3572    
3573    getUpdater : function(){
3574        if(!this.updateManager){
3575            this.updateManager = new Ext.Updater(this);
3576        }
3577        return this.updateManager;
3578    },
3579
3580    
3581    unselectable : function(){
3582        this.dom.unselectable = "on";
3583        this.swallowEvent("selectstart", true);
3584        this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
3585        this.addClass("x-unselectable");
3586        return this;
3587    },
3588
3589    
3590    getCenterXY : function(){
3591        return this.getAlignToXY(document, 'c-c');
3592    },
3593
3594    
3595    center : function(centerIn){
3596        this.alignTo(centerIn || document, 'c-c');
3597        return this;
3598    },
3599
3600    
3601    isBorderBox : function(){
3602        return noBoxAdjust[this.dom.tagName.toLowerCase()] || Ext.isBorderBox;
3603    },
3604
3605    
3606    getBox : function(contentBox, local){
3607        var xy;
3608        if(!local){
3609            xy = this.getXY();
3610        }else{
3611            var left = parseInt(this.getStyle("left"), 10) || 0;
3612            var top = parseInt(this.getStyle("top"), 10) || 0;
3613            xy = [left, top];
3614        }
3615        var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
3616        if(!contentBox){
3617            bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
3618        }else{
3619            var l = this.getBorderWidth("l")+this.getPadding("l");
3620            var r = this.getBorderWidth("r")+this.getPadding("r");
3621            var t = this.getBorderWidth("t")+this.getPadding("t");
3622            var b = this.getBorderWidth("b")+this.getPadding("b");
3623            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)};
3624        }
3625        bx.right = bx.x + bx.width;
3626        bx.bottom = bx.y + bx.height;
3627        return bx;
3628    },
3629
3630    
3631    getFrameWidth : function(sides, onlyContentBox){
3632        return onlyContentBox && Ext.isBorderBox ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
3633    },
3634
3635    
3636    setBox : function(box, adjust, animate){
3637        var w = box.width, h = box.height;
3638        if((adjust && !this.autoBoxAdjust) && !this.isBorderBox()){
3639           w -= (this.getBorderWidth("lr") + this.getPadding("lr"));
3640           h -= (this.getBorderWidth("tb") + this.getPadding("tb"));
3641        }
3642        this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));
3643        return this;
3644    },
3645
3646    
3647     repaint : function(){
3648        var dom = this.dom;
3649        this.addClass("x-repaint");
3650        setTimeout(function(){
3651            Ext.get(dom).removeClass("x-repaint");
3652        }, 1);
3653        return this;
3654    },
3655
3656    
3657    getMargins : function(side){
3658        if(!side){
3659            return {
3660                top: parseInt(this.getStyle("margin-top"), 10) || 0,
3661                left: parseInt(this.getStyle("margin-left"), 10) || 0,
3662                bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,
3663                right: parseInt(this.getStyle("margin-right"), 10) || 0
3664            };
3665        }else{
3666            return this.addStyles(side, El.margins);
3667         }
3668    },
3669
3670    // private
3671    addStyles : function(sides, styles){
3672        var val = 0, v, w;
3673        for(var i = 0, len = sides.length; i < len; i++){
3674            v = this.getStyle(styles[sides.charAt(i)]);
3675            if(v){
3676                 w = parseInt(v, 10);
3677                 if(w){ val += (w >= 0 ? w : -1 * w); }
3678            }
3679        }
3680        return val;
3681    },
3682
3683    
3684    createProxy : function(config, renderTo, matchBox){
3685        config = typeof config == "object" ?
3686            config : {tag : "div", cls: config};
3687
3688        var proxy;
3689        if(renderTo){
3690            proxy = Ext.DomHelper.append(renderTo, config, true);
3691        }else {
3692            proxy = Ext.DomHelper.insertBefore(this.dom, config, true);
3693        }
3694        if(matchBox){
3695           proxy.setBox(this.getBox());
3696        }
3697        return proxy;
3698    },
3699
3700    
3701    mask : function(msg, msgCls){
3702        if(this.getStyle("position") == "static"){
3703            this.addClass("x-masked-relative");
3704        }
3705        if(this._maskMsg){
3706            this._maskMsg.remove();
3707        }
3708        if(this._mask){
3709            this._mask.remove();
3710        }
3711
3712        this._mask = Ext.DomHelper.append(this.dom, {cls:"ext-el-mask"}, true);
3713
3714        this.addClass("x-masked");
3715        this._mask.setDisplayed(true);
3716        if(typeof msg == 'string'){
3717            this._maskMsg = Ext.DomHelper.append(this.dom, {cls:"ext-el-mask-msg", cn:{tag:'div'}}, true);
3718            var mm = this._maskMsg;
3719            mm.dom.className = msgCls ? "ext-el-mask-msg " + msgCls : "ext-el-mask-msg";
3720            mm.dom.firstChild.innerHTML = msg;
3721            mm.setDisplayed(true);
3722            mm.center(this);
3723        }
3724        if(Ext.isIE && !(Ext.isIE7 && Ext.isStrict) && this.getStyle('height') == 'auto'){ // ie will not expand full height automatically
3725            this._mask.setSize(this.getWidth(), this.getHeight());
3726        }
3727        return this._mask;
3728    },
3729
3730    
3731    unmask : function(){
3732        if(this._mask){
3733            if(this._maskMsg){
3734                this._maskMsg.remove();
3735                delete this._maskMsg;
3736            }
3737            this._mask.remove();
3738            delete this._mask;
3739        }
3740        this.removeClass(["x-masked", "x-masked-relative"]);
3741    },
3742
3743    
3744    isMasked : function(){
3745        return this._mask && this._mask.isVisible();
3746    },
3747
3748    
3749    createShim : function(){
3750        var el = document.createElement('iframe');
3751        el.frameBorder = '0';
3752        el.className = 'ext-shim';
3753        if(Ext.isIE && Ext.isSecure){
3754            el.src = Ext.SSL_SECURE_URL;
3755        }
3756        var shim = Ext.get(this.dom.parentNode.insertBefore(el, this.dom));
3757        shim.autoBoxAdjust = false;
3758        return shim;
3759    },
3760
3761    
3762    remove : function(){
3763        Ext.removeNode(this.dom);
3764        delete El.cache[this.dom.id];
3765    },
3766
3767    
3768    hover : function(overFn, outFn, scope){
3769        var preOverFn = function(e){
3770            if(!e.within(this, true)){
3771                overFn.apply(scope || this, arguments);
3772            }
3773        };
3774        var preOutFn = function(e){
3775            if(!e.within(this, true)){
3776                outFn.apply(scope || this, arguments);
3777            }
3778        };
3779        this.on("mouseover", preOverFn, this.dom);
3780        this.on("mouseout", preOutFn, this.dom);
3781        return this;
3782    },
3783
3784    
3785    addClassOnOver : function(className){
3786        this.hover(
3787            function(){
3788                Ext.fly(this, '_internal').addClass(className);
3789            },
3790            function(){
3791                Ext.fly(this, '_internal').removeClass(className);
3792            }
3793        );
3794        return this;
3795    },
3796
3797    
3798    addClassOnFocus : function(className){
3799        this.on("focus", function(){
3800            Ext.fly(this, '_internal').addClass(className);
3801        }, this.dom);
3802        this.on("blur", function(){
3803            Ext.fly(this, '_internal').removeClass(className);
3804        }, this.dom);
3805        return this;
3806    },
3807    
3808    addClassOnClick : function(className){
3809        var dom = this.dom;
3810        this.on("mousedown", function(){
3811            Ext.fly(dom, '_internal').addClass(className);
3812            var d = Ext.getDoc();
3813            var fn = function(){
3814                Ext.fly(dom, '_internal').removeClass(className);
3815                d.removeListener("mouseup", fn);
3816            };
3817            d.on("mouseup", fn);
3818        });
3819        return this;
3820    },
3821
3822    
3823    swallowEvent : function(eventName, preventDefault){
3824        var fn = function(e){
3825            e.stopPropagation();
3826            if(preventDefault){
3827                e.preventDefault();
3828            }
3829        };
3830        if(Ext.isArray(eventName)){
3831            for(var i = 0, len = eventName.length; i < len; i++){
3832                 this.on(eventName[i], fn);
3833            }
3834            return this;
3835        }
3836        this.on(eventName, fn);
3837        return this;
3838    },
3839
3840    
3841    parent : function(selector, returnDom){
3842        return this.matchNode('parentNode', 'parentNode', selector, returnDom);
3843    },
3844
3845     
3846    next : function(selector, returnDom){
3847        return this.matchNode('nextSibling', 'nextSibling', selector, returnDom);
3848    },
3849
3850    
3851    prev : function(selector, returnDom){
3852        return this.matchNode('previousSibling', 'previousSibling', selector, returnDom);
3853    },
3854
3855
3856    
3857    first : function(selector, returnDom){
3858        return this.matchNode('nextSibling', 'firstChild', selector, returnDom);
3859    },
3860
3861    
3862    last : function(selector, returnDom){
3863        return this.matchNode('previousSibling', 'lastChild', selector, returnDom);
3864    },
3865
3866    matchNode : function(dir, start, selector, returnDom){
3867        var n = this.dom[start];
3868        while(n){
3869            if(n.nodeType == 1 && (!selector || Ext.DomQuery.is(n, selector))){
3870                return !returnDom ? Ext.get(n) : n;
3871            }
3872            n = n[dir];
3873        }
3874        return null;
3875    },
3876
3877    
3878    appendChild: function(el){
3879        el = Ext.get(el);
3880        el.appendTo(this);
3881        return this;
3882    },
3883
3884    
3885    createChild: function(config, insertBefore, returnDom){
3886        config = config || {tag:'div'};
3887        if(insertBefore){
3888            return Ext.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
3889        }
3890        return Ext.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config,  returnDom !== true);
3891    },
3892
3893    
3894    appendTo: function(el){
3895        el = Ext.getDom(el);
3896        el.appendChild(this.dom);
3897        return this;
3898    },
3899
3900    
3901    insertBefore: function(el){
3902        el = Ext.getDom(el);
3903        el.parentNode.insertBefore(this.dom, el);
3904        return this;
3905    },
3906
3907    
3908    insertAfter: function(el){
3909        el = Ext.getDom(el);
3910        el.parentNode.insertBefore(this.dom, el.nextSibling);
3911        return this;
3912    },
3913
3914    
3915    insertFirst: function(el, returnDom){
3916        el = el || {};
3917        if(typeof el == 'object' && !el.nodeType && !el.dom){ // dh config
3918            return this.createChild(el, this.dom.firstChild, returnDom);
3919        }else{
3920            el = Ext.getDom(el);
3921            this.dom.insertBefore(el, this.dom.firstChild);
3922            return !returnDom ? Ext.get(el) : el;
3923        }
3924    },
3925
3926    
3927    insertSibling: function(el, where, returnDom){
3928        var rt;
3929        if(Ext.isArray(el)){
3930            for(var i = 0, len = el.length; i < len; i++){
3931                rt = this.insertSibling(el[i], where, returnDom);
3932            }
3933            return rt;
3934        }
3935        where = where ? where.toLowerCase() : 'before';
3936        el = el || {};
3937        var refNode = where == 'before' ? this.dom : this.dom.nextSibling;
3938
3939        if(typeof el == 'object' && !el.nodeType && !el.dom){ // dh config
3940            if(where == 'after' && !this.dom.nextSibling){
3941                rt = Ext.DomHelper.append(this.dom.parentNode, el, !returnDom);
3942            }else{
3943                rt = Ext.DomHelper[where == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !returnDom);
3944            }
3945
3946        }else{
3947            rt = this.dom.parentNode.insertBefore(Ext.getDom(el), refNode);
3948            if(!returnDom){
3949                rt = Ext.get(rt);
3950            }
3951        }
3952        return rt;
3953    },
3954
3955    
3956    wrap: function(config, returnDom){
3957        if(!config){
3958            config = {tag: "div"};
3959        }
3960        var newEl = Ext.DomHelper.insertBefore(this.dom, config, !returnDom);
3961        newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
3962        return newEl;
3963    },
3964
3965    
3966    replace: function(el){
3967        el = Ext.get(el);
3968        this.insertBefore(el);
3969        el.remove();
3970        return this;
3971    },
3972
3973    
3974    replaceWith: function(el){
3975        if(typeof el == 'object' && !el.nodeType && !el.dom){ // dh config
3976            el = this.insertSibling(el, 'before');
3977        }else{
3978            el = Ext.getDom(el);
3979            this.dom.parentNode.insertBefore(el, this.dom);
3980        }
3981        El.uncache(this.id);
3982        Ext.removeNode(this.dom);
3983        this.dom = el;
3984        this.id = Ext.id(el);
3985        El.cache[this.id] = this;
3986        return this;
3987    },
3988
3989    
3990    insertHtml : function(where, html, returnEl){
3991        var el = Ext.DomHelper.insertHtml(where, this.dom, html);
3992        return returnEl ? Ext.get(el) : el;
3993    },
3994
3995    
3996    set : function(o, useSet){
3997        var el = this.dom;
3998        useSet = typeof useSet == 'undefined' ? (el.setAttribute ? true : false) : useSet;
3999        for(var attr in o){
4000            if(attr == "style" || typeof o[attr] == "function") continue;
4001            if(attr=="cls"){
4002                el.className = o["cls"];
4003            }else if(o.hasOwnProperty(attr)){
4004                if(useSet) el.setAttribute(attr, o[attr]);
4005                else el[attr] = o[attr];
4006            }
4007        }
4008        if(o.style){
4009            Ext.DomHelper.applyStyles(el, o.style);
4010        }
4011        return this;
4012    },
4013
4014    
4015    addKeyListener : function(key, fn, scope){
4016        var config;
4017        if(typeof key != "object" || Ext.isArray(key)){
4018            config = {
4019                key: key,
4020                fn: fn,
4021                scope: scope
4022            };
4023        }else{
4024            config = {
4025                key : key.key,
4026                shift : key.shift,
4027                ctrl : key.ctrl,
4028                alt : key.alt,
4029                fn: fn,
4030                scope: scope
4031            };
4032        }
4033        return new Ext.KeyMap(this, config);
4034    },
4035
4036    
4037    addKeyMap : function(config){
4038        return new Ext.KeyMap(this, config);
4039    },
4040
4041    
4042     isScrollable : function(){
4043        var dom = this.dom;
4044        return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
4045    },
4046
4047    
4048    scrollTo : function(side, value, animate){
4049        var prop = side.toLowerCase() == "left" ? "scrollLeft" : "scrollTop";
4050        if(!animate || !A){
4051            this.dom[prop] = value;
4052        }else{
4053            var to = prop == "scrollLeft" ? [value, this.dom.scrollTop] : [this.dom.scrollLeft, value];
4054            this.anim({scroll: {"to": to}}, this.preanim(arguments, 2), 'scroll');
4055        }
4056        return this;
4057    },
4058
4059    
4060     scroll : function(direction, distance, animate){
4061         if(!this.isScrollable()){
4062             return;
4063         }
4064         var el = this.dom;
4065         var l = el.scrollLeft, t = el.scrollTop;
4066         var w = el.scrollWidth, h = el.scrollHeight;
4067         var cw = el.clientWidth, ch = el.clientHeight;
4068         direction = direction.toLowerCase();
4069         var scrolled = false;
4070         var a = this.preanim(arguments, 2);
4071         switch(direction){
4072             case "l":
4073             case "left":
4074                 if(w - l > cw){
4075                     var v = Math.min(l + distance, w-cw);
4076                     this.scrollTo("left", v, a);
4077                     scrolled = true;
4078                 }
4079                 break;
4080            case "r":
4081            case "right":
4082                 if(l > 0){
4083                     var v = Math.max(l - distance, 0);
4084                     this.scrollTo("left", v, a);
4085                     scrolled = true;
4086                 }
4087                 break;
4088            case "t":
4089            case "top":
4090            case "up":
4091                 if(t > 0){
4092                     var v = Math.max(t - distance, 0);
4093                     this.scrollTo("top", v, a);
4094                     scrolled = true;
4095                 }
4096                 break;
4097            case "b":
4098            case "bottom":
4099            case "down":
4100                 if(h - t > ch){
4101                     var v = Math.min(t + distance, h-ch);
4102                     this.scrollTo("top", v, a);
4103                     scrolled = true;
4104                 }
4105                 break;
4106         }
4107         return scrolled;
4108    },
4109
4110    
4111    translatePoints : function(x, y){
4112        if(typeof x == 'object' || Ext.isArray(x)){
4113            y = x[1]; x = x[0];
4114        }
4115        var p = this.getStyle('position');
4116        var o = this.getXY();
4117
4118        var l = parseInt(this.getStyle('left'), 10);
4119        var t = parseInt(this.getStyle('top'), 10);
4120
4121        if(isNaN(l)){
4122            l = (p == "relative") ? 0 : this.dom.offsetLeft;
4123        }
4124        if(isNaN(t)){
4125            t = (p == "relative") ? 0 : this.dom.offsetTop;
4126        }
4127
4128        return {left: (x - o[0] + l), top: (y - o[1] + t)};
4129    },
4130
4131    
4132    getScroll : function(){
4133        var d = this.dom, doc = document;
4134        if(d == doc || d == doc.body){
4135            var l, t;
4136            if(Ext.isIE && Ext.isStrict){
4137                l = doc.documentElement.scrollLeft || (doc.body.scrollLeft || 0);
4138                t = doc.documentElement.scrollTop || (doc.body.scrollTop || 0);
4139            }else{
4140                l = window.pageXOffset || (doc.body.scrollLeft || 0);
4141                t = window.pageYOffset || (doc.body.scrollTop || 0);
4142            }
4143            return {left: l, top: t};
4144        }else{
4145            return {left: d.scrollLeft, top: d.scrollTop};
4146        }
4147    },
4148
4149    
4150    getColor : function(attr, defaultValue, prefix){
4151        var v = this.getStyle(attr);
4152        if(!v || v == "transparent" || v == "inherit") {
4153            return defaultValue;
4154        }
4155        var color = typeof prefix == "undefined" ? "#" : prefix;
4156        if(v.substr(0, 4) == "rgb("){
4157            var rvs = v.slice(4, v.length -1).split(",");
4158            for(var i = 0; i < 3; i++){
4159                var h = parseInt(rvs[i]);
4160                var s = h.toString(16);
4161                if(h < 16){
4162                    s = "0" + s;
4163                }
4164                color += s;
4165            }
4166        } else {
4167            if(v.substr(0, 1) == "#"){
4168                if(v.length == 4) {
4169                    for(var i = 1; i < 4; i++){
4170                        var c = v.charAt(i);
4171                        color +=  c + c;
4172                    }
4173                }else if(v.length == 7){
4174                    color += v.substr(1);
4175                }
4176            }
4177        }
4178        return(color.length > 5 ? color.toLowerCase() : defaultValue);
4179    },
4180
4181    
4182    boxWrap : function(cls){
4183        cls = cls || 'x-box';
4184        var el = Ext.get(this.insertHtml('beforeBegin', String.format('<div class="{0}">'+El.boxMarkup+'</div>', cls)));
4185        el.child('.'+cls+'-mc').dom.appendChild(this.dom);
4186        return el;
4187    },
4188
4189    
4190    getAttributeNS : Ext.isIE ? function(ns, name){
4191        var d = this.dom;
4192        var type = typeof d[ns+":"+name];
4193        if(type != 'undefined' && type != 'unknown'){
4194            return d[ns+":"+name];
4195        }
4196        return d[name];
4197    } : function(ns, name){
4198        var d = this.dom;
4199        return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];
4200    },
4201
4202    
4203    getTextWidth : function(text, min, max){
4204        return (Ext.util.TextMetrics.measure(this.dom, Ext.value(text, this.dom.innerHTML, true)).width).constrain(min || 0, max || 1000000);
4205    }
4206};
4207
4208var ep = El.prototype;
4209
4210
4211ep.on = ep.addListener;
4212    // backwards compat
4213ep.mon = ep.addListener;
4214
4215ep.getUpdateManager = ep.getUpdater;
4216
4217
4218ep.un = ep.removeListener;
4219
4220
4221ep.autoBoxAdjust = true;
4222
4223// private
4224El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
4225
4226// private
4227El.addUnits = function(v, defaultUnit){
4228    if(v === "" || v == "auto"){
4229        return v;
4230    }
4231    if(v === undefined){
4232        return '';
4233    }
4234    if(typeof v == "number" || !El.unitPattern.test(v)){
4235        return v + (defaultUnit || 'px');
4236    }
4237    return v;
4238};
4239
4240// special markup used throughout Ext when box wrapping elements
4241El.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>';
4242
4243El.VISIBILITY = 1;
4244
4245El.DISPLAY = 2;
4246
4247El.borders = {l: "border-left-width", r: "border-right-width", t: "border-top-width", b: "border-bottom-width"};
4248El.paddings = {l: "padding-left", r: "padding-right", t: "padding-top", b: "padding-bottom"};
4249El.margins = {l: "margin-left", r: "margin-right", t: "margin-top", b: "margin-bottom"};
4250
4251
4252
4253
4254El.cache = {};
4255
4256var docEl;
4257
4258
4259El.get = function(el){
4260    var ex, elm, id;
4261    if(!el){ return null; }
4262    if(typeof el == "string"){ // element id
4263        if(!(elm = document.getElementById(el))){
4264            return null;
4265        }
4266        if(ex = El.cache[el]){
4267            ex.dom = elm;
4268        }else{
4269            ex = El.cache[el] = new El(elm);
4270        }
4271        return ex;
4272    }else if(el.tagName){ // dom element
4273        if(!(id = el.id)){
4274            id = Ext.id(el);
4275        }
4276        if(ex = El.cache[id]){
4277            ex.dom = el;
4278        }else{
4279            ex = El.cache[id] = new El(el);
4280        }
4281        return ex;
4282    }else if(el instanceof El){
4283        if(el != docEl){
4284            el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
4285                                                          // catch case where it hasn't been appended
4286            El.cache[el.id] = el;
4286 // in case it was created directly with Element(), let's cache it
4287        }
4288        return el;
4289    }else if(el.isComposite){
4290        return el;
4291    }else if(Ext.isArray(el)){
4292        return El.select(el);
4293    }else if(el == document){
4294        // create a bogus element object representing the document object
4295        if(!docEl){
4296            var f = function(){};
4297            f.prototype = El.prototype;
4298            docEl = new f();
4299            docEl.dom = document;
4300        }
4301        return docEl;
4302    }
4303    return null;
4304};
4305
4306// private
4307El.uncache = function(el){
4308    for(var i = 0, a = arguments, len = a.length; i < len; i++) {
4309        if(a[i]){
4310            delete El.cache[a[i].id || a[i]];
4311        }
4312    }
4313};
4314
4315// private
4316// Garbage collection - uncache elements/purge listeners on orphaned elements
4317// so we don't hold a reference and cause the browser to retain them
4318El.garbageCollect = function(){
4319    if(!Ext.enableGarbageCollector){
4320        clearInterval(El.collectorThread);
4321        return;
4322    }
4323    for(var eid in El.cache){
4324        var el = El.cache[eid], d = el.dom;
4325        // -------------------------------------------------------
4326        // Determining what is garbage:
4327        // -------------------------------------------------------
4328        // !d
4329        // dom node is null, definitely garbage
4330        // -------------------------------------------------------
4331        // !d.parentNode
4332        // no parentNode == direct orphan, definitely garbage
4333        // -------------------------------------------------------
4334        // !d.offsetParent && !document.getElementById(eid)
4335        // display none elements have no offsetParent so we will
4336        // also try to look it up by it's id. However, check
4337        // offsetParent first so we don't do unneeded lookups.
4338        // This enables collection of elements that are not orphans
4339        // directly, but somewhere up the line they have an orphan
4340        // parent.
4341        // -------------------------------------------------------
4342        if(!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))){
4343            delete El.cache[eid];
4344            if(d && Ext.enableListenerCollection){
4345                Ext.EventManager.removeAll(d);
4346            }
4347        }
4348    }
4349}
4350El.collectorThreadId = setInterval(El.garbageCollect, 30000);
4351
4352var flyFn = function(){};
4353flyFn.prototype = El.prototype;
4354var _cls = new flyFn();
4355
4356// dom is optional
4357El.Flyweight = function(dom){
4358    this.dom = dom;
4359};
4360
4361El.Flyweight.prototype = _cls;
4362El.Flyweight.prototype.isFlyweight = true;
4363
4364El._flyweights = {};
4365
4366El.fly = function(el, named){
4367    named = named || '_global';
4368    el = Ext.getDom(el);
4369    if(!el){
4370        return null;
4371    }
4372    if(!El._flyweights[named]){
4373        El._flyweights[named] = new El.Flyweight();
4374    }
4375    El._flyweights[named].dom = el;
4376    return El._flyweights[named];
4377};
4378
4379
4380Ext.get = El.get;
4381
4382Ext.fly = El.fly;
4383
4384// speedy lookup for elements never to box adjust
4385var noBoxAdjust = Ext.isStrict ? {
4386    select:1
4387} : {
4388    input:1, select:1, textarea:1
4389};
4390if(Ext.isIE || Ext.isGecko){
4391    noBoxAdjust['button'] = 1;
4392}
4393
4394
4395Ext.EventManager.on(window, 'unload', function(){
4396    delete El.cache;
4397    delete El._flyweights;
4398});
4399})();
4400
4401//Notifies Element that fx methods are available
4402Ext.enableFx = true;
4403
4404
4405Ext.Fx = {
4406	
4407    slideIn : function(anchor, o){
4408        var el = this.getFxEl();
4409        o = o || {};
4410
4411        el.queueFx(o, function(){
4412
4413            anchor = anchor || "t";
4414
4415            // fix display to visibility
4416            this.fixDisplay();
4417
4418            // restore values after effect
4419            var r = this.getFxRestore();
4420            var b = this.getBox();
4421            // fixed size for slide
4422            this.setSize(b);
4423
4424            // wrap if needed
4425            var wrap = this.fxWrap(r.pos, o, "hidden");
4426
4427            var st = this.dom.style;
4428            st.visibility = "visible";
4429            st.position = "absolute";
4430
4431            // clear out temp styles after slide and unwrap
4432            var after = function(){
4433                el.fxUnwrap(wrap, r.pos, o);
4434                st.width = r.width;
4435                st.height = r.height;
4436                el.afterFx(o);
4437            };
4438            // time to calc the positions
4439            var a, pt = {to: [b.x, b.y]}, bw = {to: b.width}, bh = {to: b.height};
4440
4441            switch(anchor.toLowerCase()){
4442                case "t":
4443                    wrap.setSize(b.width, 0);
4444                    st.left = st.bottom = "0";
4445                    a = {height: bh};
4446                break;
4447                case "l":
4448                    wrap.setSize(0, b.height);
4449                    st.right = st.top = "0";
4450                    a = {width: bw};
4451                break;
4452                case "r":
4453                    wrap.setSize(0, b.height);
4454                    wrap.setX(b.right);
4455                    st.left = st.top = "0";
4456                    a = {width: bw, points: pt};
4457                break;
4458                case "b":
4459                    wrap.setSize(b.width, 0);
4460                    wrap.setY(b.bottom);
4461                    st.left = st.top = "0";
4462                    a = {height: bh, points: pt};
4463                break;
4464                case "tl":
4465                    wrap.setSize(0, 0);
4466                    st.right = st.bottom = "0";
4467                    a = {width: bw, height: bh};
4468                break;
4469                case "bl":
4470                    wrap.setSize(0, 0);
4471                    wrap.setY(b.y+b.height);
4472                    st.right = st.top = "0";
4473                    a = {width: bw, height: bh, points: pt};
4474                break;
4475                case "br":
4476                    wrap.setSize(0, 0);
4477                    wrap.setXY([b.right, b.bottom]);
4478                    st.left = st.top = "0";
4479                    a = {width: bw, height: bh, points: pt};
4480                break;
4481                case "tr":
4482                    wrap.setSize(0, 0);
4483                    wrap.setX(b.x+b.width);
4484                    st.left = st.bottom = "0";
4485                    a = {width: bw, height: bh, points: pt};
4486                break;
4487            }
4488            this.dom.style.visibility = "visible";
4489            wrap.show();
4490
4491            arguments.callee.anim = wrap.fxanim(a,
4492                o,
4493                'motion',
4494                .5,
4495                'easeOut', after);
4496        });
4497        return this;
4498    },
4499    
4500	
4501    slideOut : function(anchor, o){
4502        var el = this.getFxEl();
4503        o = o || {};
4504
4505        el.queueFx(o, function(){
4506
4507            anchor = anchor || "t";
4508
4509            // restore values after effect
4510            var r = this.getFxRestore();
4511            
4512            var b = this.getBox();
4513            // fixed size for slide
4514            this.setSize(b);
4515
4516            // wrap if needed
4517            var wrap = this.fxWrap(r.pos, o, "visible");
4518
4519            var st = this.dom.style;
4520            st.visibility = "visible";
4521            st.position = "absolute";
4522
4523            wrap.setSize(b);
4524
4525            var after = function(){
4526                if(o.useDisplay){
4527                    el.setDisplayed(false);
4528                }else{
4529                    el.hide();
4530                }
4531
4532                el.fxUnwrap(wrap, r.pos, o);
4533
4534                st.width = r.width;
4535                st.height = r.height;
4536
4537                el.afterFx(o);
4538            };
4539
4540            var a, zero = {to: 0};
4541            switch(anchor.toLowerCase()){
4542                case "t":
4543                    st.left = st.bottom = "0";
4544                    a = {height: zero};
4545                break;
4546                case "l":
4547                    st.right = st.top = "0";
4548                    a = {width: zero};
4549                break;
4550                case "r":
4551                    st.left = st.top = "0";
4552                    a = {width: zero, points: {to:[b.right, b.y]}};
4553                break;
4554                case "b":
4555                    st.left = st.top = "0";
4556                    a = {height: zero, points: {to:[b.x, b.bottom]}};
4557                break;
4558                case "tl":
4559                    st.right = st.bottom = "0";
4560                    a = {width: zero, height: zero};
4561                break;
4562                case "bl":
4563                    st.right = st.top = "0";
4564                    a = {width: zero, height: zero, points: {to:[b.x, b.bottom]}};
4565                break;
4566                case "br":
4567                    st.left = st.top = "0";
4568                    a = {width: zero, height: zero, points: {to:[b.x+b.width, b.bottom]}};
4569                break;
4570                case "tr":
4571                    st.left = st.bottom = "0";
4572                    a = {width: zero, height: zero, points: {to:[b.right, b.y]}};
4573                break;
4574            }
4575
4576            arguments.callee.anim = wrap.fxanim(a,
4577                o,
4578                'motion',
4579                .5,
4580                "easeOut", after);
4581        });
4582        return this;
4583    },
4584
4585	
4586    puff : function(o){
4587        var el = this.getFxEl();
4588        o = o || {};
4589
4590        el.queueFx(o, function(){
4591            this.clearOpacity();
4592            this.show();
4593
4594            // restore values after effect
4595            var r = this.getFxRestore();
4596            var st = this.dom.style;
4597
4598            var after = function(){
4599                if(o.useDisplay){
4600                    el.setDisplayed(false);
4601                }else{
4602                    el.hide();
4603                }
4604
4605                el.clearOpacity();
4606
4607                el.setPositioning(r.pos);
4608                st.width = r.width;
4609                st.height = r.height;
4610                st.fontSize = '';
4611                el.afterFx(o);
4612            };
4613
4614            var width = this.getWidth();
4615            var height = this.getHeight();
4616
4617            arguments.callee.anim = this.fxanim({
4618                    width : {to: this.adjustWidth(width * 2)},
4619                    height : {to: this.adjustHeight(height * 2)},
4620                    points : {by: [-(width * .5), -(height * .5)]},
4621                    opacity : {to: 0},
4622                    fontSize: {to:200, unit: "%"}
4623                },
4624                o,
4625                'motion',
4626                .5,
4627                "easeOut", after);
4628        });
4629        return this;
4630    },
4631
4632	
4633    switchOff : function(o){
4634        var el = this.getFxEl();
4635        o = o || {};
4636
4637        el.queueFx(o, function(){
4638            this.clearOpacity();
4639            this.clip();
4640
4641            // restore values after effect
4642            var r = this.getFxRestore();
4643            var st = this.dom.style;
4644
4645            var after = function(){
4646                if(o.useDisplay){
4647                    el.setDisplayed(false);
4648                }else{
4649                    el.hide();
4650                }
4651
4652                el.clearOpacity();
4653                el.setPositioning(r.pos);
4654                st.width = r.width;
4655                st.height = r.height;
4656
4657                el.afterFx(o);
4658            };
4659
4660            this.fxanim({opacity:{to:0.3}}, null, null, .1, null, function(){
4661                this.clearOpacity();
4662                (function(){
4663                    this.fxanim({
4664                        height:{to:1},
4665                        points:{by:[0, this.getHeight() * .5]}
4666                    }, o, 'motion', 0.3, 'easeIn', after);
4667                }).defer(100, this);
4668            });
4669        });
4670        return this;
4671    },
4672
4673    	
4674    highlight : function(color, o){
4675        var el = this.getFxEl();
4676        o = o || {};
4677
4678        el.queueFx(o, function(){
4679            color = color || "ffff9c";
4680            var attr = o.attr || "backgroundColor";
4681
4682            this.clearOpacity();
4683            this.show();
4684
4685            var origColor = this.getColor(attr);
4686            var restoreColor = this.dom.style[attr];
4687            var endColor = (o.endColor || origColor) || "ffffff";
4688
4689            var after = function(){
4690                el.dom.style[attr] = restoreColor;
4691                el.afterFx(o);
4692            };
4693
4694            var a = {};
4695            a[attr] = {from: color, to: endColor};
4696            arguments.callee.anim = this.fxanim(a,
4697                o,
4698                'color',
4699                1,
4700                'easeIn', after);
4701        });
4702        return this;
4703    },
4704
4705   
4706    frame : function(color, count, o){
4707        var el = this.getFxEl();
4708        o = o || {};
4709
4710        el.queueFx(o, function(){
4711            color = color || "#C3DAF9";
4712            if(color.length == 6){
4713                color = "#" + color;
4714            }
4715            count = count || 1;
4716            var duration = o.duration || 1;
4717            this.show();
4718
4719            var b = this.getBox();
4720            var animFn = function(){
4721                var proxy = Ext.getBody().createChild({
4722                     style:{
4723                        visbility:"hidden",
4724                        position:"absolute",
4725                        "z-index":"35000", // yee haw
4726                        border:"0px solid " + color
4727                     }
4728                  });
4729                var scale = Ext.isBorderBox ? 2 : 1;
4730                proxy.animate({
4731                    top:{from:b.y, to:b.y - 20},
4732                    left:{from:b.x, to:b.x - 20},
4733                    borderWidth:{from:0, to:10},
4734                    opacity:{from:1, to:0},
4735                    height:{from:b.height, to:(b.height + (20*scale))},
4736                    width:{from:b.width, to:(b.width + (20*scale))}
4737                }, duration, function(){
4738                    proxy.remove();
4739                    if(--count > 0){
4740                         animFn();
4741                    }else{
4742                        el.afterFx(o);
4743                    }
4744                });
4745            };
4746            animFn.call(this);
4747        });
4748        return this;
4749    },
4750
4751   
4752    pause : function(seconds){
4753        var el = this.getFxEl();
4754        var o = {};
4755
4756        el.queueFx(o, function(){
4757            setTimeout(function(){
4758                el.afterFx(o);
4759            }, seconds * 1000);
4760        });
4761        return this;
4762    },
4763
4764   
4765    fadeIn : function(o){
4766        var el = this.getFxEl();
4767        o = o || {};
4768        el.queueFx(o, function(){
4769            this.setOpacity(0);
4770            this.fixDisplay();
4771            this.dom.style.visibility = 'visible';
4772            var to = o.endOpacity || 1;
4773            arguments.callee.anim = this.fxanim({opacity:{to:to}},
4774                o, null, .5, "easeOut", function(){
4775                if(to == 1){
4776                    this.clearOpacity();
4777                }
4778                el.afterFx(o);
4779            });
4780        });
4781        return this;
4782    },
4783
4784   
4785    fadeOut : function(o){
4786        var el = this.getFxEl();
4787        o = o || {};
4788        el.queueFx(o, function(){
4789            var to = o.endOpacity || 0;
4790            arguments.callee.anim = this.fxanim({opacity:{to:to}},
4791                o, null, .5, "easeOut", function(){
4792                if(to === 0){
4793                    if(this.visibilityMode == Ext.Element.DISPLAY || o.useDisplay){
4794                         this.dom.style.display = "none";
4795                    }else{
4796                         this.dom.style.visibility = "hidden";
4797                    }
4798                    this.clearOpacity();
4799                }
4800                el.afterFx(o);
4801            });
4802        });
4803        return this;
4804    },
4805
4806   
4807    scale : function(w, h, o){
4808        this.shift(Ext.apply({}, o, {
4809            width: w,
4810            height: h
4811        }));
4812        return this;
4813    },
4814
4815   
4816    shift : function(o){
4817        var el = this.getFxEl();
4818        o = o || {};
4819        el.queueFx(o, function(){
4820            var a = {}, w = o.width, h = o.height, x = o.x, y = o.y,  op = o.opacity;
4821            if(w !== undefined){
4822                a.width = {to: this.adjustWidth(w)};
4823            }
4824            if(h !== undefined){
4825                a.height = {to: this.adjustHeight(h)};
4826            }
4827            if(o.left !== undefined){
4828                a.left = {to: o.left};
4829            }
4830            if(o.top !== undefined){
4831                a.top = {to: o.top};
4832            }
4833            if(o.right !== undefined){
4834                a.right = {to: o.right};
4835            }
4836            if(o.bottom !== undefined){
4837                a.bottom = {to: o.bottom};
4838            }
4839            if(x !== undefined || y !== undefined){
4840                a.points = {to: [
4841                    x !== undefined ? x : this.getX(),
4842                    y !== undefined ? y : this.getY()
4843                ]};
4844            }
4845            if(op !== undefined){
4846                a.opacity = {to: op};
4847            }
4848            if(o.xy !== undefined){
4849                a.points = {to: o.xy};
4850            }
4851            arguments.callee.anim = this.fxanim(a,
4852                o, 'motion', .35, "easeOut", function(){
4853                el.afterFx(o);
4854            });
4855        });
4856        return this;
4857    },
4858
4859	
4860    ghost : function(anchor, o){
4861        var el = this.getFxEl();
4862        o = o || {};
4863
4864        el.queueFx(o, function(){
4865            anchor = anchor || "b";
4866
4867            // restore values after effect
4868            var r = this.getFxRestore();
4869            var w = this.getWidth(),
4870                h = this.getHeight();
4871
4872            var st = this.dom.style;
4873
4874            var after = function(){
4875                if(o.useDisplay){
4876                    el.setDisplayed(false);
4877                }else{
4878                    el.hide();
4879                }
4880
4881                el.clearOpacity();
4882                el.setPositioning(r.pos);
4883                st.width = r.width;
4884                st.height = r.height;
4885
4886                el.afterFx(o);
4887            };
4888
4889            var a = {opacity: {to: 0}, points: {}}, pt = a.points;
4890            switch(anchor.toLowerCase()){
4891                case "t":
4892                    pt.by = [0, -h];
4893                break;
4894                case "l":
4895                    pt.by = [-w, 0];
4896                break;
4897                case "r":
4898                    pt.by = [w, 0];
4899                break;
4900                case "b":
4901                    pt.by = [0, h];
4902                break;
4903                case "tl":
4904                    pt.by = [-w, -h];
4905                break;
4906                case "bl":
4907                    pt.by = [-w, h];
4908                break;
4909                case "br":
4910                    pt.by = [w, h];
4911                break;
4912                case "tr":
4913                    pt.by = [w, -h];
4914                break;
4915            }
4916
4917            arguments.callee.anim = this.fxanim(a,
4918                o,
4919                'motion',
4920                .5,
4921                "easeOut", after);
4922        });
4923        return this;
4924    },
4925
4926	
4927    syncFx : function(){
4928        this.fxDefaults = Ext.apply(this.fxDefaults || {}, {
4929            block : false,
4930            concurrent : true,
4931            stopFx : false
4932        });
4933        return this;
4934    },
4935
4936	
4937    sequenceFx : function(){
4938        this.fxDefaults = Ext.apply(this.fxDefaults || {}, {
4939            block : false,
4940            concurrent : false,
4941            stopFx : false
4942        });
4943        return this;
4944    },
4945
4946	
4947    nextFx : function(){
4948        var ef = this.fxQueue[0];
4949        if(ef){
4950            ef.call(this);
4951        }
4952    },
4953
4954	
4955    hasActiveFx : function(){
4956        return this.fxQueue && this.fxQueue[0];
4957    },
4958
4959	
4960    stopFx : function(){
4961        if(this.hasActiveFx()){
4962            var cur = this.fxQueue[0];
4963            if(cur && cur.anim && cur.anim.isAnimated()){
4964                this.fxQueue = [cur]; // clear out others
4965                cur.anim.stop(true);
4966            }
4967        }
4968        return this;
4969    },
4970
4971	
4972    beforeFx : function(o){
4973        if(this.hasActiveFx() && !o.concurrent){
4974           if(o.stopFx){
4975               this.stopFx();
4976               return true;
4977           }
4978           return false;
4979        }
4980        return true;
4981    },
4982
4983	
4984    hasFxBlock : function(){
4985        var q = this.fxQueue;
4986        return q && q[0] && q[0].block;
4987    },
4988
4989	
4990    queueFx : function(o, fn){
4991        if(!this.fxQueue){
4992            this.fxQueue = [];
4993        }
4994        if(!this.hasFxBlock()){
4995            Ext.applyIf(o, this.fxDefaults);
4996            if(!o.concurrent){
4997                var run = this.beforeFx(o);
4998                fn.block = o.block;
4999                this.fxQueue.push(fn);
5000                if(run){
5001                    this.nextFx();
5002                }
5003            }else{
5004                fn.call(this);
5005            }
5006        }
5007        return this;
5008    },
5009
5010	
5011    fxWrap : function(pos, o, vis){
5012        var wrap;
5013        if(!o.wrap || !(wrap = Ext.get(o.wrap))){
5014            var wrapXY;
5015            if(o.fixPosition){
5016                wrapXY = this.getXY();
5017            }
5018            var div = document.createElement("div");
5019            div.style.visibility = vis;
5020            wrap = Ext.get(this.dom.parentNode.insertBefore(div, this.dom));
5021            wrap.setPositioning(pos);
5022            if(wrap.getStyle("position") == "static"){
5023                wrap.position("relative");
5024            }
5025            this.clearPositioning('auto');
5026            wrap.clip();
5027            wrap.dom.appendChild(this.dom);
5028            if(wrapXY){
5029                wrap.setXY(wrapXY);
5030            }
5031        }
5032        return wrap;
5033    },
5034
5035	
5036    fxUnwrap : function(wrap, pos, o){
5037        this.clearPositioning();
5038        this.setPositioning(pos);
5039        if(!o.wrap){
5040            wrap.dom.parentNode.insertBefore(this.dom, wrap.dom);
5041            wrap.remove();
5042        }
5043    },
5044
5045	
5046    getFxRestore : function(){
5047        var st = this.dom.style;
5048        return {pos: this.getPositioning(), width: st.width, height : st.height};
5049    },
5050
5051	
5052    afterFx : function(o){
5053        if(o.afterStyle){
5054            this.applyStyles(o.afterStyle);
5055        }
5056        if(o.afterCls){
5057            this.addClass(o.afterCls);
5058        }
5059        if(o.remove === true){
5060            this.remove();
5061        }
5062        Ext.callback(o.callback, o.scope, [this]);
5063        if(!o.concurrent){
5064            this.fxQueue.shift();
5065            this.nextFx();
5066        }
5067    },
5068
5069	
5070    getFxEl : function(){ // support for composite element fx
5071        return Ext.get(this.dom);
5072    },
5073
5074	
5075    fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
5076        animType = animType || 'run';
5077        opt = opt || {};
5078        var anim = Ext.lib.Anim[animType](
5079            this.dom, args,
5080            (opt.duration || defaultDur) || .35,
5081            (opt.easing || defaultEase) || 'easeOut',
5082            function(){
5083                Ext.callback(cb, this);
5084            },
5085            this
5086        );
5087        opt.anim = anim;
5088        return anim;
5089    }
5090};
5091
5092// backwords compat
5093Ext.Fx.resize = Ext.Fx.scale;
5094
5095//When included, Ext.Fx is automatically applied to Element so that all basic
5096//effects are available directly via the Element API
5097Ext.apply(Ext.Element.prototype, Ext.Fx);
5098
5099
5100Ext.CompositeElement = function(els){
5101    this.elements = [];
5102    this.addElements(els);
5103};
5104Ext.CompositeElement.prototype = {
5105    isComposite: true,
5106    addElements : function(els){
5107        if(!els) return this;
5108        if(typeof els == "string"){
5109            els = Ext.Element.selectorFunction(els);
5110        }
5111        var yels = this.elements;
5112        var index = yels.length-1;
5113        for(var i = 0, len = els.length; i < len; i++) {
5114        	yels[++index] = Ext.get(els[i]);
5115        }
5116        return this;
5117    },
5118
5119    
5120    fill : function(els){
5121        this.elements = [];
5122        this.add(els);
5123        return this;
5124    },
5125
5126    
5127    filter : function(selector){
5128        var els = [];
5129        this.each(function(el){
5130            if(el.is(selector)){
5131                els[els.length] = el.dom;
5132            }
5133        });
5134        this.fill(els);
5135        return this;
5136    },
5137
5138    invoke : function(fn, args){
5139        var els = this.elements;
5140        for(var i = 0, len = els.length; i < len; i++) {
5141        	Ext.Element.prototype[fn].apply(els[i], args);
5142        }
5143        return this;
5144    },
5145    
5146    add : function(els){
5147        if(typeof els == "string"){
5148            this.addElements(Ext.Element.selectorFunction(els));
5149        }else if(els.length !== undefined){
5150            this.addElements(els);
5151        }else{
5152            this.addElements([els]);
5153        }
5154        return this;
5155    },
5156    
5157    each : function(fn, scope){
5158        var els = this.elements;
5159        for(var i = 0, len = els.length; i < len; i++){
5160            if(fn.call(scope || els[i], els[i], this, i) === false) {
5161                break;
5162            }
5163        }
5164        return this;
5165    },
5166
5167    
5168    item : function(index){
5169        return this.elements[index] || null;
5170    },
5171
5172    
5173    first : function(){
5174        return this.item(0);
5175    },
5176
5177    
5178    last : function(){
5179        return this.item(this.elements.length-1);
5180    },
5181
5182    
5183    getCount : function(){
5184        return this.elements.length;
5185    },
5186
5187    
5188    contains : function(el){
5189        return this.indexOf(el) !== -1;
5190    },
5191
5192    
5193    indexOf : function(el){
5194        return this.elements.indexOf(Ext.get(el));
5195    },
5196
5197
5198    
5199    removeElement : function(el, removeDom){
5200        if(Ext.isArray(el)){
5201            for(var i = 0, len = el.length; i < len; i++){
5202                this.removeElement(el[i]);
5203            }
5204            return this;
5205        }
5206        var index = typeof el == 'number' ? el : this.indexOf(el);
5207        if(index !== -1 && this.elements[index]){
5208            if(removeDom){
5209                var d = this.elements[index];
5210                if(d.dom){
5211                    d.remove();
5212                }else{
5213                    Ext.removeNode(d);
5214                }
5215            }
5216            this.elements.splice(index, 1);
5217        }
5218        return this;
5219    },
5220
5221    
5222    replaceElement : function(el, replacement, domReplace){
5223        var index = typeof el == 'number' ? el : this.indexOf(el);
5224        if(index !== -1){
5225            if(domReplace){
5226                this.elements[index].replaceWith(replacement);
5227            }else{
5228                this.elements.splice(index, 1, Ext.get(replacement))
5229            }
5230        }
5231        return this;
5232    },
5233
5234    
5235    clear : function(){
5236        this.elements = [];
5237    }
5238};
5239(function(){
5240Ext.CompositeElement.createCall = function(proto, fnName){
5241    if(!proto[fnName]){
5242        proto[fnName] = function(){
5243            return this.invoke(fnName, arguments);
5244        };
5245    }
5246};
5247for(var fnName in Ext.Element.prototype){
5248    if(typeof Ext.Element.prototype[fnName] == "function"){
5249        Ext.CompositeElement.createCall(Ext.CompositeElement.prototype, fnName);
5250    }
5251};
5252})();
5253
5254
5255Ext.CompositeElementLite = function(els){
5256    Ext.CompositeElementLite.superclass.constructor.call(this, els);
5257    this.el = new Ext.Element.Flyweight();
5258};
5259Ext.extend(Ext.CompositeElementLite, Ext.CompositeElement, {
5260    addElements : function(els){
5261        if(els){
5262            if(Ext.isArray(els)){
5263                this.elements = this.elements.concat(els);
5264            }else{
5265                var yels = this.elements;
5266                var index = yels.length-1;
5267                for(var i = 0, len = els.length; i < len; i++) {
5268                    yels[++index] = els[i];
5269                }
5270            }
5271        }
5272        return this;
5273    },
5274    invoke : function(fn, args){
5275        var els = this.elements;
5276        var el = this.el;
5277        for(var i = 0, len = els.length; i < len; i++) {
5278            el.dom = els[i];
5279        	Ext.Element.prototype[fn].apply(el, args);
5280        }
5281        return this;
5282    },
5283    
5284    item : function(index){
5285        if(!this.elements[index]){
5286            return null;
5287        }
5288        this.el.dom = this.elements[index];
5289        return this.el;
5290    },
5291
5292    // fixes scope with flyweight
5293    addListener : function(eventName, handler, scope, opt){
5294        var els = this.elements;
5295        for(var i = 0, len = els.length; i < len; i++) {
5296            Ext.EventManager.on(els[i], eventName, handler, scope || els[i], opt);
5297        }
5298        return this;
5299    },
5300
5301    
5302    each : function(fn, scope){
5303        var els = this.elements;
5304        var el = this.el;
5305        for(var i = 0, len = els.length; i < len; i++){
5306            el.dom = els[i];
5307        	if(fn.call(scope || el, el, this, i) === false){
5308                break;
5309            }
5310        }
5311        return this;
5312    },
5313
5314    indexOf : function(el){
5315        return this.elements.indexOf(Ext.getDom(el));
5316    },
5317
5318    replaceElement : function(el, replacement, domReplace){
5319        var index = typeof el == 'number' ? el : this.indexOf(el);
5320        if(index !== -1){
5321            replacement = Ext.getDom(replacement);
5322            if(domReplace){
5323                var d = this.elements[index];
5324                d.parentNode.insertBefore(replacement, d);
5325                Ext.removeNode(d);
5326            }
5327            this.elements.splice(index, 1, replacement);
5328        }
5329        return this;
5330    }
5331});
5332Ext.CompositeElementLite.prototype.on = Ext.CompositeElementLite.prototype.addListener;
5333if(Ext.DomQuery){
5334    Ext.Element.selectorFunction = Ext.DomQuery.select;
5335}
5336
5337Ext.Element.select = function(selector, unique, root){
5338    var els;
5339    if(typeof selector == "string"){
5340        els = Ext.Element.selectorFunction(selector, root);
5341    }else if(selector.length !== undefined){
5342        els = selector;
5343    }else{
5344        throw "Invalid selector";
5345    }
5346    if(unique === true){
5347        return new Ext.CompositeElement(els);
5348    }else{
5349        return new Ext.CompositeElementLite(els);
5350    }
5351};
5352
5353Ext.select = Ext.Element.select;
5354
5355Ext.data.Connection = function(config){
5356    Ext.apply(this, config);
5357    this.addEvents(
5358        
5359        "beforerequest",
5360        
5361        "requestcomplete",
5362        
5363        "requestexception"
5364    );
5365    Ext.data.Connection.superclass.constructor.call(this);
5366};
5367
5368Ext.extend(Ext.data.Connection, Ext.util.Observable, {
5369    
5370    
5371    
5372    
5373    
5374    timeout : 30000,
5375    
5376    autoAbort:false,
5377
5378    
5379    disableCaching: true,
5380    
5381    
5382    disableCachingParam: '_dc',
5383    
5384
5385    
5386    request : function(o){
5387        if(this.fireEvent("beforerequest", this, o) !== false){
5388            var p = o.params;
5389
5390            if(typeof p == "function"){
5391                p = p.call(o.scope||window, o);
5392            }
5393            if(typeof p == "object"){
5394                p = Ext.urlEncode(p);
5395            }
5396            if(this.extraParams){
5397                var extras = Ext.urlEncode(this.extraParams);
5398                p = p ? (p + '&' + extras) : extras;
5399            }
5400
5401            var url = o.url || this.url;
5402            if(typeof url == 'function'){
5403                url = url.call(o.scope||window, o);
5404            }
5405
5406            if(o.form){
5407                var form = Ext.getDom(o.form);
5408                url = url || form.action;
5409
5410                var enctype = form.getAttribute("enctype");
5411                if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
5412                    return this.doFormUpload(o, p, url);
5413                }
5414                var f = Ext.lib.Ajax.serializeForm(form);
5415                p = p ? (p + '&' + f) : f;
5416            }
5417
5418            var hs = o.headers;
5419            if(this.defaultHeaders){
5420                hs = Ext.apply(hs || {}, this.defaultHeaders);
5421                if(!o.headers){
5422                    o.headers = hs;
5423                }
5424            }
5425
5426            var cb = {
5427                success: this.handleResponse,
5428                failure: this.handleFailure,
5429                scope: this,
5430                argument: {options: o},
5431                timeout : o.timeout || this.timeout
5432            };
5433
5434            var method = o.method||this.method||((p || o.xmlData || o.jsonData) ? "POST" : "GET");
5435
5436            if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
5437                var dcp = o.disableCachingParam || this.disableCachingParam;
5438                url += (url.indexOf('?') != -1 ? '&' : '?') + dcp + '=' + (new Date().getTime());
5439            }
5440
5441            if(typeof o.autoAbort == 'boolean'){ // options gets top priority
5442                if(o.autoAbort){
5443                    this.abort();
5444                }
5445            }else if(this.autoAbort !== false){
5446                this.abort();
5447            }
5448            if((method == 'GET' || o.xmlData || o.jsonData) && p){
5449                url += (url.indexOf('?') != -1 ? '&' : '?') + p;
5450                p = '';
5451            }
5452            this.transId = Ext.lib.Ajax.request(method, url, cb, p, o);
5453            return this.transId;
5454        }else{
5455            Ext.callback(o.callback, o.scope, [o, null, null]);
5456            return null;
5457        }
5458    },
5459
5460    
5461    isLoading : function(transId){
5462        if(transId){
5463            return Ext.lib.Ajax.isCallInProgress(transId);
5464        }else{
5465            return this.transId ? true : false;
5466        }
5467    },
5468
5469    
5470    abort : function(transId){
5471        if(transId || this.isLoading()){
5472            Ext.lib.Ajax.abort(transId || this.transId);
5473        }
5474    },
5475
5476    // private
5477    handleResponse : function(response){
5478        this.transId = false;
5479        var options = response.argument.options;
5480        response.argument = options ? options.argument : null;
5481        this.fireEvent("requestcomplete", this, response, options);
5482        Ext.callback(options.success, options.scope, [response, options]);
5483        Ext.callback(options.callback, options.scope, [options, true, response]);
5484    },
5485
5486    // private
5487    handleFailure : function(response, e){
5488        this.transId = false;
5489        var options = response.argument.options;
5490        response.argument = options ? options.argument : null;
5491        this.fireEvent("requestexception", this, response, options, e);
5492        Ext.callback(options.failure, options.scope, [response, options]);
5493        Ext.callback(options.callback, options.scope, [options, false, response]);
5494    },
5495
5496    // private
5497    doFormUpload : function(o, ps, url){
5498        var id = Ext.id();
5499        var frame = document.createElement('iframe');
5500        frame.id = id;
5501        frame.name = id;
5502        frame.className = 'x-hidden';
5503        if(Ext.isIE){
5504            frame.src = Ext.SSL_SECURE_URL;
5505        }
5506        document.body.appendChild(frame);
5507
5508        if(Ext.isIE){
5509           document.frames[id].name = id;
5510        }
5511
5512        var form = Ext.getDom(o.form);
5513        form.target = id;
5514        form.method = 'POST';
5515        form.enctype = form.encoding = 'multipart/form-data';
5516        if(url){
5517            form.action = url;
5518        }
5519
5520        var hiddens, hd;
5521        if(ps){ // add dynamic params
5522            hiddens = [];
5523            ps = Ext.urlDecode(ps, false);
5524            for(var k in ps){
5525                if(ps.hasOwnProperty(k)){
5526                    hd = document.createElement('input');
5527                    hd.type = 'hidden';
5528                    hd.name = k;
5529                    hd.value = ps[k];
5530                    form.appendChild(hd);
5531                    hiddens.push(hd);
5532                }
5533            }
5534        }
5535
5536        function cb(){
5537            var r = {  // bogus response object
5538                responseText : '',
5539                responseXML : null
5540            };
5541
5542            r.argument = o ? o.argument : null;
5543
5544            try { //
5545                var doc;
5546                if(Ext.isIE){
5547                    doc = frame.contentWindow.document;
5548                }else {
5549                    doc = (frame.contentDocument || window.frames[id].document);
5550                }
5551                if(doc && doc.body){
5552                    r.responseText = doc.body.innerHTML;
5553                }
5554                if(doc && doc.XMLDocument){
5555                    r.responseXML = doc.XMLDocument;
5556                }else {
5557                    r.responseXML = doc;
5558                }
5559            }
5560            catch(e) {
5561                // ignore
5562            }
5563
5564            Ext.EventManager.removeListener(frame, 'load', cb, this);
5565
5566            this.fireEvent("requestcomplete", this, r, o);
5567
5568            Ext.callback(o.success, o.scope, [r, o]);
5569            Ext.callback(o.callback, o.scope, [o, true, r]);
5570
5571            setTimeout(function(){Ext.removeNode(frame);}, 100);
5572        }
5573
5574        Ext.EventManager.on(frame, 'load', cb, this);
5575        form.submit();
5576
5577        if(hiddens){ // remove dynamic params
5578            for(var i = 0, len = hiddens.length; i < len; i++){
5579                Ext.removeNode(hiddens[i]);
5580            }
5581        }
5582    }
5583});
5584
5585
5586Ext.Ajax = new Ext.data.Connection({
5587    
5588    
5589    
5590    
5591    
5592    
5593
5594    
5595
5596    
5597    
5598    
5599    
5600    
5601    
5602
5603    
5604    autoAbort : false,
5605
5606    
5607    serializeForm : function(form){
5608        return Ext.lib.Ajax.serializeForm(form);
5609    }
5610});
5611
5612Ext.Updater = Ext.extend(Ext.util.Observable, {
5613    constructor: function(el, forceNew){
5614        el = Ext.get(el);
5615        if(!forceNew && el.updateManager){
5616            return el.updateManager;
5617        }
5618        
5619        this.el = el;
5620        
5621        this.defaultUrl = null;
5622
5623        this.addEvents(
5624            
5625            "beforeupdate",
5626            
5627            "update",
5628            
5629            "failure"
5630        );
5631        var d = Ext.Updater.defaults;
5632        
5633        this.sslBlankUrl = d.sslBlankUrl;
5634        
5635        this.disableCaching = d.disableCaching;
5636        
5637        this.indicatorText = d.indicatorText;
5638        
5639        this.showLoadIndicator = d.showLoadIndicator;
5640        
5641        this.timeout = d.timeout;
5642        
5643        this.loadScripts = d.loadScripts;
5644        
5645        this.transaction = null;
5646        
5647        this.refreshDelegate = this.refresh.createDelegate(this);
5648        
5649        this.updateDelegate = this.update.createDelegate(this);
5650        
5651        this.formUpdateDelegate = this.formUpdate.createDelegate(this);
5652
5653        if(!this.renderer){
5654         
5655        this.renderer = this.getDefaultRenderer();
5656        }
5657        Ext.Updater.superclass.constructor.call(this);
5658    },
5659    
5660    getDefaultRenderer: function() {
5661        return new Ext.Updater.BasicRenderer();
5662    },
5663    
5664    getEl : function(){
5665        return this.el;
5666    },
5667
5668    
5669    update : function(url, params, callback, discardUrl){
5670        if(this.fireEvent("beforeupdate", this.el, url, params) !== false){
5671            var cfg, callerScope;
5672            if(typeof url == "object"){ // must be config object
5673                cfg = url;
5674                url = cfg.url;
5675                params = params || cfg.params;
5676                callback = callback || cfg.callback;
5677                discardUrl = discardUrl || cfg.discardUrl;
5678                callerScope = cfg.scope;
5679                if(typeof cfg.nocache != "undefined"){this.disableCaching = cfg.nocache;};
5680                if(typeof cfg.text != "undefined"){this.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
5681                if(typeof cfg.scripts != "undefined"){this.loadScripts = cfg.scripts;};
5682                if(typeof cfg.timeout != "undefined"){this.timeout = cfg.timeout;};
5683            }
5684            this.showLoading();
5685
5686            if(!discardUrl){
5687                this.defaultUrl = url;
5688            }
5689            if(typeof url == "function"){
5690                url = url.call(this);
5691            }
5692
5693            var o = Ext.apply({}, {
5694                url : url,
5695                params: (typeof params == "function" && callerScope) ? params.createDelegate(callerScope) : params,
5696                success: this.processSuccess,
5697                failure: this.processFailure,
5698                scope: this,
5699                callback: undefined,
5700                timeout: (this.timeout*1000),
5701                disableCaching: this.disableCaching,
5702                argument: {
5703                    "options": cfg,
5704                    "url": url,
5705                    "form": null,
5706                    "callback": callback,
5707                    "scope": callerScope || window,
5708                    "params": params
5709                }
5710            }, cfg);
5711
5712            this.transaction = Ext.Ajax.request(o);
5713        }
5714    },
5715
5716    
5717    formUpdate : function(form, url, reset, callback){
5718        if(this.fireEvent("beforeupdate", this.el, form, url) !== false){
5719            if(typeof url == "function"){
5720                url = url.call(this);
5721            }
5722            form = Ext.getDom(form)
5723            this.transaction = Ext.Ajax.request({
5724                form: form,
5725                url:url,
5726                success: this.processSuccess,
5727                failure: this.processFailure,
5728                scope: this,
5729                timeout: (this.timeout*1000),
5730                argument: {
5731                    "url": url,
5732                    "form": form,
5733                    "callback": callback,
5734                    "reset": reset
5735                }
5736            });
5737            this.showLoading.defer(1, this);
5738        }
5739    },
5740
5741    
5742    refresh : function(callback){
5743        if(this.defaultUrl == null){
5744            return;
5745        }
5746        this.update(this.defaultUrl, null, callback, true);
5747    },
5748
5749    
5750    startAutoRefresh : function(interval, url, params, callback, refreshNow){
5751        if(refreshNow){
5752            this.update(url || this.defaultUrl, params, callback, true);
5753        }
5754        if(this.autoRefreshProcId){
5755            clearInterval(this.autoRefreshProcId);
5756        }
5757        this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [url || this.defaultUrl, params, callback, true]), interval*1000);
5758    },
5759
5760    
5761     stopAutoRefresh : function(){
5762        if(this.autoRefreshProcId){
5763            clearInterval(this.autoRefreshProcId);
5764            delete this.autoRefreshProcId;
5765        }
5766    },
5767
5768    
5769    isAutoRefreshing : function(){
5770       return this.autoRefreshProcId ? true : false;
5771    },
5772
5773    
5774    showLoading : function(){
5775        if(this.showLoadIndicator){
5776            this.el.update(this.indicatorText);
5777        }
5778    },
5779
5780    // private
5781    processSuccess : function(response){
5782        this.transaction = null;
5783        if(response.argument.form && response.argument.reset){
5784            try{ // put in try/catch since some older FF releases had problems with this
5785                response.argument.form.reset();
5786            }catch(e){}
5787        }
5788        if(this.loadScripts){
5789            this.renderer.render(this.el, response, this,
5790                this.updateComplete.createDelegate(this, [response]));
5791        }else{
5792            this.renderer.render(this.el, response, this);
5793            this.updateComplete(response);
5794        }
5795    },
5796
5797    // private
5798    updateComplete : function(response){
5799        this.fireEvent("update", this.el, response);
5800        if(typeof response.argument.callback == "function"){
5801            response.argument.callback.call(response.argument.scope, this.el, true, response, response.argument.options);
5802        }
5803    },
5804
5805    // private
5806    processFailure : function(response){
5807        this.transaction = null;
5808        this.fireEvent("failure", this.el, response);
5809        if(typeof response.argument.callback == "function"){
5810            response.argument.callback.call(response.argument.scope, this.el, false, response, response.argument.options);
5811        }
5812    },
5813
5814    
5815    setRenderer : function(renderer){
5816        this.renderer = renderer;
5817    },
5818
5819    
5820    getRenderer : function(){
5821       return this.renderer;
5822    },
5823
5824    
5825    setDefaultUrl : function(defaultUrl){
5826        this.defaultUrl = defaultUrl;
5827    },
5828
5829    
5830    abort : function(){
5831        if(this.transaction){
5832            Ext.Ajax.abort(this.transaction);
5833        }
5834    },
5835
5836    
5837    isUpdating : function(){
5838        if(this.transaction){
5839            return Ext.Ajax.isLoading(this.transaction);
5840        }
5841        return false;
5842    }
5843});
5844
5845
5846   Ext.Updater.defaults = {
5847       
5848         timeout : 30,
5849         
5850        loadScripts : false,
5851        
5852        sslBlankUrl : (Ext.SSL_SECURE_URL || "javascript:false"),
5853        
5854        disableCaching : false,
5855        
5856        showLoadIndicator : true,
5857        
5858        indicatorText : '<div class="loading-indicator">Loading...</div>'
5859   };
5860
5861
5862Ext.Updater.updateElement = function(el, url, params, options){
5863    var um = Ext.get(el).getUpdater();
5864    Ext.apply(um, options);
5865    um.update(url, params, options ? options.callback : null);
5866};
5867
5868Ext.Updater.BasicRenderer = function(){};
5869
5870Ext.Updater.BasicRenderer.prototype = {
5871    
5872     render : function(el, response, updateManager, callback){
5873        el.update(response.responseText, updateManager.loadScripts, callback);
5874    }
5875};
5876
5877Ext.UpdateManager = Ext.Updater;
5878
5879
5880
5881
5882
5883(function() {
5884
5885// create private copy of Ext's String.format() method
5886// - to remove unnecessary dependency
5887// - to resolve namespace conflict with M$-Ajax's implementation
5888function xf(format) {
5889    var args = Array.prototype.slice.call(arguments, 1);
5890    return format.replace(/\{(\d+)\}/g, function(m, i) {
5891        return args[i];
5892    });
5893}
5894
5895
5896// private
5897Date.formatCodeToRegex = function(character, currentGroup) {
5898    // Note: currentGroup - position in regex result array (see notes for Date.parseCodes below)
5899    var p = Date.parseCodes[character];
5900
5901    if (p) {
5902      p = Ext.type(p) == 'function'? p() : p;
5903      Date.parseCodes[character] = p; // reassign function result to prevent repeated execution
5904    }
5905
5906    return p? Ext.applyIf({
5907      c: p.c? xf(p.c, currentGroup || "{0}") : p.c
5908    }, p) : {
5909        g:0,
5910        c:null,
5911        s:Ext.escapeRe(character) // treat unrecognised characters as literals
5912    }
5913}
5914
5915// private shorthand for Date.formatCodeToRegex since we'll be using it fairly often
5916var $f = Date.formatCodeToRegex;
5917
5918Ext.apply(Date, {
5919    // private
5920    parseFunctions: {count:0},
5921    parseRegexes: [],
5922    formatFunctions: {count:0},
5923    daysInMonth : [31,28,31,30,31,30,31,31,30,31,30,31],
5924    y2kYear : 50,
5925
5926    
5927    MILLI : "ms",
5928
5929    
5930    SECOND : "s",
5931
5932    
5933    MINUTE : "mi",
5934
5935    
5936    HOUR : "h",
5937
5938    
5939    DAY : "d",
5940
5941    
5942    MONTH : "mo",
5943
5944    
5945    YEAR : "y",
5946
5947    
5948    dayNames : [
5949        "Sunday",
5950        "Monday",
5951        "Tuesday",
5952        "Wednesday",
5953        "Thursday",
5954        "Friday",
5955        "Saturday"
5956    ],
5957
5958    
5959    monthNames : [
5960        "January",
5961        "February",
5962        "March",
5963        "April",
5964        "May",
5965        "June",
5966        "July",
5967        "August",
5968        "September",
5969        "October",
5970        "November",
5971        "December"
5972    ],
5973
5974    
5975    monthNumbers : {
5976        Jan:0,
5977        Feb:1,
5978        Mar:2,
5979        Apr:3,
5980        May:4,
5981        Jun:5,
5982        Jul:6,
5983        Aug:7,
5984        Sep:8,
5985        Oct:9,
5986        Nov:10,
5987        Dec:11
5988    },
5989
5990    
5991    getShortMonthName : function(month) {
5992        return Date.monthNames[month].substring(0, 3);
5993    },
5994
5995    
5996    getShortDayName : function(day) {
5997        return Date.dayNames[day].substring(0, 3);
5998    },
5999
6000    
6001    getMonthNumber : function(name) {
6002        // handle camel casing for english month names (since the keys for the Date.monthNumbers hash are case sensitive)
6003        return Date.monthNumbers[name.substring(0, 1).toUpperCase() + name.substring(1, 3).toLowerCase()];
6004    },
6005
6006    
6007    formatCodes : {
6008        d: "String.leftPad(this.getDate(), 2, '0')",
6009        D: "Date.getShortDayName(this.getDay())", // get localised short day name
6010        j: "this.getDate()",
6011        l: "Date.dayNames[this.getDay()]",
6012        N: "(this.getDay() ? this.getDay() : 7)",
6013        S: "this.getSuffix()",
6014        w: "this.getDay()",
6015        z: "this.getDayOfYear()",
6016        W: "String.leftPad(this.getWeekOfYear(), 2, '0')",
6017        F: "Date.monthNames[this.getMonth()]",
6018        m: "String.leftPad(this.getMonth() + 1, 2, '0')",
6019        M: "Date.getShortMonthName(this.getMonth())", // get localised short month name
6020        n: "(this.getMonth() + 1)",
6021        t: "this.getDaysInMonth()",
6022        L: "(this.isLeapYear() ? 1 : 0)",
6023        o: "(this.getFullYear() + (this.getWeekOfYear() == 1 && this.getMonth() > 0 ? +1 : (this.getWeekOfYear() >= 52 && this.getMonth() < 11 ? -1 : 0)))",
6024        Y: "this.getFullYear()",
6025        y: "('' + this.getFullYear()).substring(2, 4)",
6026        a: "(this.getHours() < 12 ? 'am' : 'pm')",
6027        A: "(this.getHours() < 12 ? 'AM' : 'PM')",
6028        g: "((this.getHours() % 12) ? this.getHours() % 12 : 12)",
6029        G: "this.getHours()",
6030        h: "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0')",
6031        H: "String.leftPad(this.getHours(), 2, '0')",
6032        i: "String.leftPad(this.getMinutes(), 2, '0')",
6033        s: "String.leftPad(this.getSeconds(), 2, '0')",
6034        u: "String.leftPad(this.getMilliseconds(), 3, '0')",
6035        O: "this.getGMTOffset()",
6036        P: "this.getGMTOffset(true)",
6037        T: "this.getTimezone()",
6038        Z: "(this.getTimezoneOffset() * -60)",
6039        c: function() { // ISO-8601 -- GMT format
6040            for (var c = "Y-m-dTH:i:sP", code = [], i = 0, l = c.length; i < l; ++i) {
6041                var e = c.charAt(i);
6042                code.push(e == "T" ? "'T'" : Date.getFormatCode(e)); // treat T as a character literal
6043            }
6044            return code.join(" + ");
6045        },
6046        
6047        U: "Math.round(this.getTime() / 1000)"
6048    },
6049
6050    
6051    parseDate : function(input, format) {
6052        var p = Date.parseFunctions;
6053        if (p[format] == null) {
6054            Date.createParser(format);
6055        }
6056        var func = p[format];
6057        return Date[func](input);
6058    },
6059
6060    // private
6061    getFormatCode : function(character) {
6062        var f = Date.formatCodes[character];
6063
6064        if (f) {
6065          f = Ext.type(f) == 'function'? f() : f;
6066          Date.formatCodes[character] = f; // reassign function result to prevent repeated execution
6067        }
6068
6069        // note: unknown characters are treated as literals
6070        return f || ("'" + String.escape(character) + "'");
6071    },
6072
6073    // private
6074    createNewFormat : function(format) {
6075        var funcName = "format" + Date.formatFunctions.count++,
6076            code = "Date.prototype." + funcName + " = function(){return ",
6077            special = false,
6078            ch = '';
6079
6080        Date.formatFunctions[format] = funcName;
6081
6082        for (var i = 0; i < format.length; ++i) {
6083            ch = format.charAt(i);
6084            if (!special && ch == "\\") {
6085                special = true;
6086            }
6087            else if (special) {
6088                special = false;
6089                code += "'" + String.escape(ch) + "' + ";
6090            }
6091            else {
6092                code += Date.getFormatCode(ch) + " + ";
6093            }
6094        }
6095        eval(code.substring(0, code.length - 3) + ";}");
6096    },
6097
6098    // private
6099    createParser : function() {
6100        var code = [
6101            "Date.{0} = function(input){",
6102                "var y, m, d, h = 0, i = 0, s = 0, ms = 0, o, z, u, v;",
6103                "input = String(input);",
6104                "d = new Date();",
6105                "y = d.getFullYear();",
6106                "m = d.getMonth();",
6107                "d = d.getDate();",
6108                "var results = input.match(Date.parseRegexes[{1}]);",
6109                "if(results && results.length > 0){",
6110                    "{2}",
6111                    "if(u){",
6112                        "v = new Date(u * 1000);", // give top priority to UNIX time
6113                    "}else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0 && ms >= 0){",
6114                        "v = new Date(y, m, d, h, i, s, ms);",
6115                    "}else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0){",
6116                        "v = new Date(y, m, d, h, i, s);",
6117                    "}else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0){",
6118                        "v = new Date(y, m, d, h, i);",
6119                    "}else if (y >= 0 && m >= 0 && d > 0 && h >= 0){",
6120                        "v = new Date(y, m, d, h);",
6121                    "}else if (y >= 0 && m >= 0 && d > 0){",
6122                        "v = new Date(y, m, d);",
6123                    "}else if (y >= 0 && m >= 0){",
6124                        "v = new Date(y, m);",
6125                    "}else if (y >= 0){",
6126                        "v = new Date(y);",
6127                    "}",
6128                "}",
6129                "return (v && (z != null || o != null))?" // favour UTC offset over GMT offset
6130                    + " (Ext.type(z) == 'number' ? v.add(Date.SECOND, -v.getTimezoneOffset() * 60 - z) :" // reset to UTC, then add offset
6131                    + " v.add(Date.MINUTE, -v.getTimezoneOffset() + (sn == '+'? -1 : 1) * (hr * 60 + mn))) : v;", // reset to GMT, then add offset
6132            "}"
6133        ].join('\n');
6134
6135        return function(format) {
6136            var funcName = "parse" + Date.parseFunctions.count++,
6137                regexNum = Date.parseRegexes.length,
6138                currentGroup = 1,
6139                calc = "",
6140                regex = "",
6141                special = false,
6142                ch = "";
6143
6144            Date.parseFunctions[format] = funcName;
6145
6146            for (var i = 0; i < format.length; ++i) {
6147                ch = format.charAt(i);
6148                if (!special && ch == "\\") {
6149                    special = true;
6150                }
6151                else if (special) {
6152                    special = false;
6153                    regex += String.escape(ch);
6154                }
6155                else {
6156                    var obj = $f(ch, currentGroup);
6157                    currentGroup += obj.g;
6158                    regex += obj.s;
6159                    if (obj.g && obj.c) {
6160                        calc += obj.c;
6161                    }
6162                }
6163            }
6164
6165            Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$", "i");
6166            eval(xf(code, funcName, regexNum, calc));
6167        }
6168    }(),
6169
6170    // private
6171    parseCodes : {
6172        
6173        d: {
6174            g:1,
6175            c:"d = parseInt(results[{0}], 10);\n",
6176            s:"(\\d{2})" // day of month with leading zeroes (01 - 31)
6177        },
6178        j: {
6179            g:1,
6180            c:"d = parseInt(results[{0}], 10);\n",
6181            s:"(\\d{1,2})" // day of month without leading zeroes (1 - 31)
6182        },
6183        D: function() {
6184            for (var a = [], i = 0; i < 7; a.push(Date.getShortDayName(i)), ++i);
6184 // get localised short day names
6185            return {
6186                g:0,
6187                c:null,
6188                s:"(?:" + a.join("|") +")"
6189            }
6190        },
6191        l: function() {
6192            return {
6193                g:0,
6194                c:null,
6195                s:"(?:" + Date.dayNames.join("|") + ")"
6196            }
6197        },
6198        N: {
6199            g:0,
6200            c:null,
6201            s:"[1-7]" // ISO-8601 day number (1 (monday) - 7 (sunday))
6202        },
6203        S: {
6204            g:0,
6205            c:null,
6206            s:"(?:st|nd|rd|th)"
6207        },
6208        w: {
6209            g:0,
6210            c:null,
6211            s:"[0-6]" // javascript day number (0 (sunday) - 6 (saturday))
6212        },
6213        z: {
6214            g:0,
6215            c:null,
6216            s:"(?:\\d{1,3})" // day of the year (0 - 364 (365 in leap years))
6217        },
6218        W: {
6219            g:0,
6220            c:null,
6221            s:"(?:\\d{2})" // ISO-8601 week number (with leading zero)
6222        },
6223        F: function() {
6224            return {
6225                g:1,
6226                c:"m = parseInt(Date.getMonthNumber(results[{0}]), 10);\n", // get localised month number
6227                s:"(" + Date.monthNames.join("|") + ")"
6228            }
6229        },
6230        M: function() {
6231            for (var a = [], i = 0; i < 12; a.push(Date.getShortMonthName(i)), ++i); // get localised short month names
6232            return Ext.applyIf({
6233                s:"(" + a.join("|") + ")"
6234            }, $f("F"));
6235        },
6236        m: {
6237            g:1,
6238            c:"m = parseInt(results[{0}], 10) - 1;\n",
6239            s:"(\\d{2})" // month number with leading zeros (01 - 12)
6240        },
6241        n: {
6242            g:1,
6243            c:"m = parseInt(results[{0}], 10) - 1;\n",
6244            s:"(\\d{1,2})" // month number without leading zeros (1 - 12)
6245        },
6246        t: {
6247            g:0,
6248            c:null,
6249            s:"(?:\\d{2})" // no. of days in the month (28 - 31)
6250        },
6251        L: {
6252            g:0,
6253            c:null,
6254            s:"(?:1|0)"
6255        },
6256        o: function() {
6257            return $f("Y");
6258        },
6259        Y: {
6260            g:1,
6261            c:"y = parseInt(results[{0}], 10);\n",
6262            s:"(\\d{4})" // 4-digit year
6263        },
6264        y: {
6265            g:1,
6266            c:"var ty = parseInt(results[{0}], 10);\n"
6267                + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n", // 2-digit year
6268            s:"(\\d{1,2})"
6269        },
6270        a: {
6271            g:1,
6272            c:"if (results[{0}] == 'am') {\n"
6273                + "if (h == 12) { h = 0; }\n"
6274                + "} else { if (h < 12) { h += 12; }}",
6275            s:"(am|pm)"
6276        },
6277        A: {
6278            g:1,
6279            c:"if (results[{0}] == 'AM') {\n"
6280                + "if (h == 12) { h = 0; }\n"
6281                + "} else { if (h < 12) { h += 12; }}",
6282            s:"(AM|PM)"
6283        },
6284        g: function() {
6285            return $f("G");
6286        },
6287        G: {
6288            g:1,
6289            c:"h = parseInt(results[{0}], 10);\n",
6290            s:"(\\d{1,2})" // 24-hr format of an hour without leading zeroes (0 - 23)
6291        },
6292        h: function() {
6293            return $f("H");
6294        },
6295        H: {
6296            g:1,
6297            c:"h = parseInt(results[{0}], 10);\n",
6298            s:"(\\d{2})" //  24-hr format of an hour with leading zeroes (00 - 23)
6299        },
6300        i: {
6301            g:1,
6302            c:"i = parseInt(results[{0}], 10);\n",
6303            s:"(\\d{2})" // minutes with leading zeros (00 - 59)
6304        },
6305        s: {
6306            g:1,
6307            c:"s = parseInt(results[{0}], 10);\n",
6308            s:"(\\d{2})" // seconds with leading zeros (00 - 59)
6309        },
6310        u: {
6311            g:1,
6312            c:"ms = results[{0}]; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n",
6313            s:"(\\d+)" // decimal fraction of a second (minimum = 1 digit, maximum = unlimited)
6314        },
6315        O: {
6316            g:1,
6317            c:[
6318                "o = results[{0}];",
6319                "var sn = o.substring(0,1);", // get + / - sign
6320                "var hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60);", // get hours (performs minutes-to-hour conversion also, just in case)
6321                "var mn = o.substring(3,5) % 60;", // get minutes
6322                "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n" // -12hrs <= GMT offset <= 14hrs
6323            ].join("\n"),
6324            s: "([+\-]\\d{4})" // GMT offset in hrs and mins
6325        },
6326        P: {
6327            g:1,
6328            c:[
6329                "o = results[{0}];",
6330                "var sn = o.substring(0,1);", // get + / - sign
6331                "var hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60);", // get hours (performs minutes-to-hour conversion also, just in case)
6332                "var mn = o.substring(4,6) % 60;", // get minutes
6333                "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n" // -12hrs <= GMT offset <= 14hrs
6334            ].join("\n"),
6335            s: "([+\-]\\d{2}:\\d{2})" // GMT offset in hrs and mins (with colon separator)
6336        },
6337        T: {
6338            g:0,
6339            c:null,
6340            s:"[A-Z]{1,4}" // timezone abbrev. may be between 1 - 4 chars
6341        },
6342        Z: {
6343            g:1,
6344            c:"z = results[{0}] * 1;\n" // -43200 <= UTC offset <= 50400
6345                  + "z = (-43200 <= z && z <= 50400)? z : null;\n",
6346            s:"([+\-]?\\d{1,5})" // leading '+' sign is optional for UTC offset
6347        },
6348        c: function() {
6349            var calc = [],
6350                arr = [
6351                    $f("Y", 1), // year
6352                    $f("m", 2), // month
6353                    $f("d", 3), // day
6354                    $f("h", 4), // hour
6355                    $f("i", 5), // minute
6356                    $f("s", 6), // second
6357                    {c:"ms = (results[7] || '.0').substring(1); ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n"}, // decimal fraction of a second (minimum = 1 digit, maximum = unlimited)
6358                    {c:[ // allow both "Z" (i.e. UTC) and "+08:00" (i.e. UTC offset) time zone delimiters
6359                        "if(results[9] == 'Z'){",
6360                            "z = 0;",
6361                        "}else{",
6362                            $f("P", 9).c,
6363                        "}"
6364                    ].join('\n')}
6365                ];
6366
6367            for (var i = 0, l = arr.length; i < l; ++i) {
6368                calc.push(arr[i].c);
6369            }
6370
6371            return {
6372                g:1,
6373                c:calc.join(""),
6374                s:arr[0].s + "-" + arr[1].s + "-" + arr[2].s + "T" + arr[3].s + ":" + arr[4].s + ":" + arr[5].s
6375                      + "((\.|,)\\d+)?" // decimal fraction of a second (e.g. ",998465" or ".998465")
6376                      + "(Z|([+\-]\\d{2}:\\d{2}))" // "Z" (UTC) or "+08:00" (UTC offset)
6377            }
6378        },
6379        U: {
6380            g:1,
6381            c:"u = parseInt(results[{0}], 10);\n",
6382            s:"(-?\\d+)" // leading minus sign indicates seconds before UNIX epoch
6383        }
6384    }
6385});
6386
6387}());
6388
6389Ext.apply(Date.prototype, {
6390    // private
6391    dateFormat : function(format) {
6392        if (Date.formatFunctions[format] == null) {
6393            Date.createNewFormat(format);
6394        }
6395        var func = Date.formatFunctions[format];
6396        return this[func]();
6397    },
6398
6399    
6400    getTimezone : function() {
6401        // the following list shows the differences between date strings from different browsers on a WinXP SP2 machine from an Asian locale:
6402        //
6403        // Opera  : "Thu, 25 Oct 2007 22:53:45 GMT+0800" -- shortest (weirdest) date string of the lot
6404        // Safari : "Thu Oct 25 2007 22:55:35 GMT+0800 (Malay Peninsula Standard Time)" -- value in parentheses always gives the correct timezone (same as FF)
6405        // FF     : "Thu Oct 25 2007 22:55:35 GMT+0800 (Malay Peninsula Standard Time)" -- value in parentheses always gives the correct timezone
6406        // IE     : "Thu Oct 25 22:54:35 UTC+0800 2007" -- (Asian system setting) look for 3-4 letter timezone abbrev
6407        // IE     : "Thu Oct 25 17:06:37 PDT 2007" -- (American system setting) look for 3-4 letter timezone abbrev
6408        //
6409        // this crazy regex attempts to guess the correct timezone abbreviation despite these differences.
6410        // step 1: (?:\((.*)\) -- find timezone in parentheses
6411        // step 2: ([A-Z]{1,4})(?:[\-+][0-9]{4})?(?: -?\d+)?) -- if nothing was found in step 1, find timezone from timezone offset portion of date string
6412        // step 3: remove all non uppercase characters found in step 1 and 2
6413        return this.toString().replace(/^.* (?:\((.*)\)|([A-Z]{1,4})(?:[\-+][0-9]{4})?(?: -?\d+)?)$/, "$1$2").replace(/[^A-Z]/g, "");
6414    },
6415
6416    
6417    getGMTOffset : function(colon) {
6418        return (this.getTimezoneOffset() > 0 ? "-" : "+")
6419            + String.leftPad(Math.floor(Math.abs(this.getTimezoneOffset()) / 60), 2, "0")
6420            + (colon ? ":" : "")
6421            + String.leftPad(Math.abs(this.getTimezoneOffset() % 60), 2, "0");
6422    },
6423
6424    
6425    getDayOfYear : function() {
6426        var num = 0;
6427        Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
6428        for (var i = 0; i < this.getMonth(); ++i) {
6429            num += Date.daysInMonth[i];
6430        }
6431        return num + this.getDate() - 1;
6432    },
6433
6434    
6435    getWeekOfYear : function() {
6436        // adapted from http://www.merlyn.demon.co.uk/weekcalc.htm
6437        var ms1d = 864e5, // milliseconds in a day
6438            ms7d = 7 * ms1d; // milliseconds in a week
6439
6440        return function() { // return a closure so constants get calculated only once
6441            var DC3 = Date.UTC(this.getFullYear(), this.getMonth(), this.getDate() + 3) / ms1d, // an Absolute Day Number
6442                AWN = Math.floor(DC3 / 7), // an Absolute Week Number
6443                Wyr = new Date(AWN * ms7d).getUTCFullYear();
6444
6445            return AWN - Math.floor(Date.UTC(Wyr, 0, 7) / ms7d) + 1;
6446        }
6447    }(),
6448
6449    
6450    isLeapYear : function() {
6451        var year = this.getFullYear();
6452        return !!((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
6453    },
6454
6455    
6456    getFirstDayOfMonth : function() {
6457        var day = (this.getDay() - (this.getDate() - 1)) % 7;
6458        return (day < 0) ? (day + 7) : day;
6459    },
6460
6461    
6462    getLastDayOfMonth : function() {
6463        var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
6464        return (day < 0) ? (day + 7) : day;
6465    },
6466
6467
6468    
6469    getFirstDateOfMonth : function() {
6470        return new Date(this.getFullYear(), this.getMonth(), 1);
6471    },
6472
6473    
6474    getLastDateOfMonth : function() {
6475        return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
6476    },
6477
6478    
6479    getDaysInMonth : function() {
6480        Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
6481        return Date.daysInMonth[this.getMonth()];
6482    },
6483
6484    
6485    getSuffix : function() {
6486        switch (this.getDate()) {
6487            case 1:
6488            case 21:
6489            case 31:
6490                return "st";
6491            case 2:
6492            case 22:
6493                return "nd";
6494            case 3:
6495            case 23:
6496                return "rd";
6497            default:
6498                return "th";
6499        }
6500    },
6501
6502    
6503    clone : function() {
6504        return new Date(this.getTime());
6505    },
6506
6507    
6508    clearTime : function(clone){
6509        if(clone){
6510            return this.clone().clearTime();
6511        }
6512        this.setHours(0);
6513        this.setMinutes(0);
6514        this.setSeconds(0);
6515        this.setMilliseconds(0);
6516        return this;
6517    },
6518
6519    
6520    add : function(interval, value){
6521        var d = this.clone();
6522        if (!interval || value === 0) return d;
6523
6524        switch(interval.toLowerCase()){
6525            case Date.MILLI:
6526                d.setMilliseconds(this.getMilliseconds() + value);
6527                break;
6528            case Date.SECOND:
6529                d.setSeconds(this.getSeconds() + value);
6530                break;
6531            case Date.MINUTE:
6532                d.setMinutes(this.getMinutes() + value);
6533                break;
6534            case Date.HOUR:
6535                d.setHours(this.getHours() + value);
6536                break;
6537            case Date.DAY:
6538                d.setDate(this.getDate() + value);
6539                break;
6540            case Date.MONTH:
6541                var day = this.getDate();
6542                if(day > 28){
6543                    day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
6544                }
6545                d.setDate(day);
6546                d.setMonth(this.getMonth() + value);
6547                break;
6548            case Date.YEAR:
6549                d.setFullYear(this.getFullYear() + value);
6550                break;
6551        }
6552        return d;
6553    },
6554
6555    
6556    between : function(start, end){
6557        var t = this.getTime();
6558        return start.getTime() <= t && t <= end.getTime();
6559    }
6560});
6561
6562
6563
6564Date.prototype.format = Date.prototype.dateFormat;
6565
6566
6567// private
6568// safari setMonth is broken
6569if(Ext.isSafari){
6570    Date.brokenSetMonth = Date.prototype.setMonth;
6571    Date.prototype.setMonth = function(num){
6572        if(num <= -1){
6573            var n = Math.ceil(-num);
6574            var back_year = Math.ceil(n/12);
6575            var month = (n % 12) ? 12 - n % 12 : 0 ;
6576            this.setFullYear(this.getFullYear() - back_year);
6577            return Date.brokenSetMonth.call(this, month);
6578        } else {
6579            return Date.brokenSetMonth.apply(this, arguments);
6580        }
6581    };
6582}
6583
6584Ext.util.DelayedTask = function(fn, scope, args){
6585    var id = null, d, t;
6586
6587    var call = function(){
6588        var now = new Date().getTime();
6589        if(now - t >= d){
6590            clearInterval(id);
6591            id = null;
6592            fn.apply(scope, args || []);
6593        }
6594    };
6595    
6596    this.delay = function(delay, newFn, newScope, newArgs){
6597        if(id && delay != d){
6598            this.cancel();
6599        }
6600        d = delay;
6601        t = new Date().getTime();
6602        fn = newFn || fn;
6603        scope = newScope || scope;
6604        args = newArgs || args;
6605        if(!id){
6606            id = setInterval(call, d);
6607        }
6608    };
6609
6610    
6611    this.cancel = function(){
6612        if(id){
6613            clearInterval(id);
6614            id = null;
6615        }
6616    };
6617};
6618
6619Ext.util.TaskRunner = function(interval){
6620    interval = interval || 10;
6621    var tasks = [], removeQueue = [];
6622    var id = 0;
6623    var running = false;
6624
6625    // private
6626    var stopThread = function(){
6627        running = false;
6628        clearInterval(id);
6629        id = 0;
6630    };
6631
6632    // private
6633    var startThread = function(){
6634        if(!running){
6635            running = true;
6636            id = setInterval(runTasks, interval);
6637        }
6638    };
6639
6640    // private
6641    var removeTask = function(t){
6642        removeQueue.push(t);
6643        if(t.onStop){
6644            t.onStop.apply(t.scope || t);
6645        }
6646    };
6647
6648    // private
6649    var runTasks = function(){
6650        if(removeQueue.length > 0){
6651            for(var i = 0, len = removeQueue.length; i < len; i++){
6652                tasks.remove(removeQueue[i]);
6653            }
6654            removeQueue = [];
6655            if(tasks.length < 1){
6656                stopThread();
6657                return;
6658            }
6659        }
6660        var now = new Date().getTime();
6661        for(var i = 0, len = tasks.length; i < len; ++i){
6662            var t = tasks[i];
6663            var itime = now - t.taskRunTime;
6664            if(t.interval <= itime){
6665                var rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
6666                t.taskRunTime = now;
6667                if(rt === false || t.taskRunCount === t.repeat){
6668                    removeTask(t);
6669                    return;
6670                }
6671            }
6672            if(t.duration && t.duration <= (now - t.taskStartTime)){
6673                removeTask(t);
6674            }
6675        }
6676    };
6677
6678    
6679    this.start = function(task){
6680        tasks.push(task);
6681        task.taskStartTime = new Date().getTime();
6682        task.taskRunTime = 0;
6683        task.taskRunCount = 0;
6684        startThread();
6685        return task;
6686    };
6687
6688    
6689    this.stop = function(task){
6690        removeTask(task);
6691        return task;
6692    };
6693
6694    
6695    this.stopAll = function(){
6696        stopThread();
6697        for(var i = 0, len = tasks.length; i < len; i++){
6698            if(tasks[i].onStop){
6699                tasks[i].onStop();
6700            }
6701        }
6702        tasks = [];
6703        removeQueue = [];
6704    };
6705};
6706
6707
6708Ext.TaskMgr = new Ext.util.TaskRunner();
6709
6710Ext.util.MixedCollection = function(allowFunctions, keyFn){
6711    this.items = [];
6712    this.map = {};
6713    this.keys = [];
6714    this.length = 0;
6715    this.addEvents(
6716        
6717        "clear",
6718        
6719        "add",
6720        
6721        "replace",
6722        
6723        "remove",
6724        "sort"
6725    );
6726    this.allowFunctions = allowFunctions === true;
6727    if(keyFn){
6728        this.getKey = keyFn;
6729    }
6730    Ext.util.MixedCollection.superclass.constructor.call(this);
6731};
6732
6733Ext.extend(Ext.util.MixedCollection, Ext.util.Observable, {
6734    allowFunctions : false,
6735
6736
6737    add : function(key, o){
6738        if(arguments.length == 1){
6739            o = arguments[0];
6740            key = this.getKey(o);
6741        }
6742        if(typeof key == "undefined" || key === null){
6743            this.length++;
6744            this.items.push(o);
6745            this.keys.push(null);
6746        }else{
6747            var old = this.map[key];
6748            if(old){
6749                return this.replace(key, o);
6750            }
6751            this.length++;
6752            this.items.push(o);
6753            this.map[key] = o;
6754            this.keys.push(key);
6755        }
6756        this.fireEvent("add", this.length-1, o, key);
6757        return o;
6758    },
6759
6760
6761    getKey : function(o){
6762         return o.id;
6763    },
6764
6765
6766    replace : function(key, o){
6767        if(arguments.length == 1){
6768            o = arguments[0];
6769            key = this.getKey(o);
6770        }
6771        var old = this.item(key);
6772        if(typeof key == "undefined" || key === null || typeof old == "undefined"){
6773             return this.add(key, o);
6774        }
6775        var index = this.indexOfKey(key);
6776        this.items[index] = o;
6777        this.map[key] = o;
6778        this.fireEvent("replace", key, old, o);
6779        return o;
6780    },
6781
6782
6783    addAll : function(objs){
6784        if(arguments.length > 1 || Ext.isArray(objs)){
6785            var args = arguments.length > 1 ? arguments : objs;
6786            for(var i = 0, len = args.length; i < len; i++){
6787                this.add(args[i]);
6788            }
6789        }else{
6790            for(var key in objs){
6791                if(this.allowFunctions || typeof objs[key] != "function"){
6792                    this.add(key, objs[key]);
6793                }
6794            }
6795        }
6796    },
6797
6798
6799    each : function(fn, scope){
6800        var items = [].concat(this.items); // each safe for removal
6801        for(var i = 0, len = items.length; i < len; i++){
6802            if(fn.call(scope || items[i], items[i], i, len) === false){
6803                break;
6804            }
6805        }
6806    },
6807
6808
6809    eachKey : function(fn, scope){
6810        for(var i = 0, len = this.keys.length; i < len; i++){
6811            fn.call(scope || window, this.keys[i], this.items[i], i, len);
6812        }
6813    },
6814
6815    
6816    find : function(fn, scope){
6817        for(var i = 0, len = this.items.length; i < len; i++){
6818            if(fn.call(scope || window, this.items[i], this.keys[i])){
6819                return this.items[i];
6820            }
6821        }
6822        return null;
6823    },
6824
6825
6826    insert : function(index, key, o){
6827        if(arguments.length == 2){
6828            o = arguments[1];
6829            key = this.getKey(o);
6830        }
6831        if(index >= this.length){
6832            return this.add(key, o);
6833        }
6834        this.length++;
6835        this.items.splice(index, 0, o);
6836        if(typeof key != "undefined" && key != null){
6837            this.map[key] = o;
6838        }
6839        this.keys.splice(index, 0, key);
6840        this.fireEvent("add", index, o, key);
6841        return o;
6842    },
6843
6844
6845    remove : function(o){
6846        return this.removeAt(this.indexOf(o));
6847    },
6848
6849
6850    removeAt : function(index){
6851        if(index < this.length && index >= 0){
6852            this.length--;
6853            var o = this.items[index];
6854            this.items.splice(index, 1);
6855            var key = this.keys[index];
6856            if(typeof key != "undefined"){
6857                delete this.map[key];
6858            }
6859            this.keys.splice(index, 1);
6860            this.fireEvent("remove", o, key);
6861            return o;
6862        }
6863        return false;
6864    },
6865
6866
6867    removeKey : function(key){
6868        return this.removeAt(this.indexOfKey(key));
6869    },
6870
6871
6872    getCount : function(){
6873        return this.length;
6874    },
6875
6876
6877    indexOf : function(o){
6878        return this.items.indexOf(o);
6879    },
6880
6881
6882    indexOfKey : function(key){
6883        return this.keys.indexOf(key);
6884    },
6885
6886
6887    item : function(key){
6888        var item = typeof this.map[key] != "undefined" ? this.map[key] : this.items[key];
6889        return typeof item != 'function' || this.allowFunctions ? item : null; // for prototype!
6890    },
6891
6892
6893    itemAt : function(index){
6894        return this.items[index];
6895    },
6896
6897
6898    key : function(key){
6899        return this.map[key];
6900    },
6901
6902
6903    contains : function(o){
6904        return this.indexOf(o) != -1;
6905    },
6906
6907
6908    containsKey : function(key){
6909        return typeof this.map[key] != "undefined";
6910    },
6911
6912
6913    clear : function(){
6914        this.length = 0;
6915        this.items = [];
6916        this.keys = [];
6917        this.map = {};
6918        this.fireEvent("clear");
6919    },
6920
6921
6922    first : function(){
6923        return this.items[0];
6924    },
6925
6926
6927    last : function(){
6928        return this.items[this.length-1];
6929    },
6930
6931    // private
6932    _sort : function(property, dir, fn){
6933        var dsc = String(dir).toUpperCase() == "DESC" ? -1 : 1;
6934        fn = fn || function(a, b){
6935            return a-b;
6936        };
6937        var c = [], k = this.keys, items = this.items;
6938        for(var i = 0, len = items.length; i < len; i++){
6939            c[c.length] = {key: k[i], value: items[i], index: i};
6940        }
6941        c.sort(function(a, b){
6942            var v = fn(a[property], b[property]) * dsc;
6943            if(v == 0){
6944                v = (a.index < b.index ? -1 : 1);
6945            }
6946            return v;
6947        });
6948        for(var i = 0, len = c.length; i < len; i++){
6949            items[i] = c[i].value;
6950            k[i] = c[i].key;
6951        }
6952        this.fireEvent("sort", this);
6953    },
6954
6955    
6956    sort : function(dir, fn){
6957        this._sort("value", dir, fn);
6958    },
6959
6960    
6961    keySort : function(dir, fn){
6962        this._sort("key", dir, fn || function(a, b){
6963            var v1 = String(a).toUpperCase(), v2 = String(b).toUpperCase();
6964            return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
6965        });
6966    },
6967
6968    
6969    getRange : function(start, end){
6970        var items = this.items;
6971        if(items.length < 1){
6972            return [];
6973        }
6974        start = start || 0;
6975        end = Math.min(typeof end == "undefined" ? this.length-1 : end, this.length-1);
6976        var r = [];
6977        if(start <= end){
6978            for(var i = start; i <= end; i++) {
6979        	    r[r.length] = items[i];
6980            }
6981        }else{
6982            for(var i = start; i >= end; i--) {
6983        	    r[r.length] = items[i];
6984            }
6985        }
6986        return r;
6987    },
6988
6989    
6990    filter : function(property, value, anyMatch, caseSensitive){
6991        if(Ext.isEmpty(value, false)){
6992            return this.clone();
6993        }
6994        value = this.createValueMatcher(value, anyMatch, caseSensitive);
6995        return this.filterBy(function(o){
6996            return o && value.test(o[property]);
6997        });
6998	},
6999
7000    
7001    filterBy : function(fn, scope){
7002        var r = new Ext.util.MixedCollection();
7003        r.getKey = this.getKey;
7004        var k = this.keys, it = this.items;
7005        for(var i = 0, len = it.length; i < len; i++){
7006            if(fn.call(scope||this, it[i], k[i])){
7007				r.add(k[i], it[i]);
7008			}
7009        }
7010        return r;
7011    },
7012
7013    
7014    findIndex : function(property, value, start, anyMatch, caseSensitive){
7015        if(Ext.isEmpty(value, false)){
7016            return -1;
7017        }
7018        value = this.createValueMatcher(value, anyMatch, caseSensitive);
7019        return this.findIndexBy(function(o){
7020            return o && value.test(o[property]);
7021        }, null, start);
7022	},
7023
7024    
7025    findIndexBy : function(fn, scope, start){
7026        var k = this.keys, it = this.items;
7027        for(var i = (start||0), len = it.length; i < len; i++){
7028            if(fn.call(scope||this, it[i], k[i])){
7029				return i;
7030            }
7031        }
7032        if(typeof start == 'number' && start > 0){
7033            for(var i = 0; i < start; i++){
7034                if(fn.call(scope||this, it[i], k[i])){
7035                    return i;
7036                }
7037            }
7038        }
7039        return -1;
7040    },
7041
7042    // private
7043    createValueMatcher : function(value, anyMatch, caseSensitive){
7044        if(!value.exec){ // not a regex
7045            value = String(value);
7046            value = new RegExp((anyMatch === true ? '' : '^') + Ext.escapeRe(value), caseSensitive ? '' : 'i');
7047        }
7048        return value;
7049    },
7050
7051    
7052    clone : function(){
7053        var r = new Ext.util.MixedCollection();
7054        var k = this.keys, it = this.items;
7055        for(var i = 0, len = it.length; i < len; i++){
7056            r.add(k[i], it[i]);
7057        }
7058        r.getKey = this.getKey;
7059        return r;
7060    }
7061});
7062
7063Ext.util.MixedCollection.prototype.get = Ext.util.MixedCollection.prototype.item;
7064
7065Ext.util.JSON = new (function(){
7066    var useHasOwn = !!{}.hasOwnProperty;
7067
7068    // crashes Safari in some instances
7069    //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
7070
7071    var pad = function(n) {
7072        return n < 10 ? "0" + n : n;
7073    };
7074
7075    var m = {
7076        "\b": '\\b',
7077        "\t": '\\t',
7078        "\n": '\\n',
7079        "\f": '\\f',
7080        "\r": '\\r',
7081        '"' : '\\"',
7082        "\\": '\\\\'
7083    };
7084
7085    var encodeString = function(s){
7086        if (/["\\\x00-\x1f]/.test(s)) {
7087            return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
7088                var c = m[b];
7089                if(c){
7090                    return c;
7091                }
7092                c = b.charCodeAt();
7093                return "\\u00" +
7094                    Math.floor(c / 16).toString(16) +
7095                    (c % 16).toString(16);
7096            }) + '"';
7097        }
7098        return '"' + s + '"';
7099    };
7100
7101    var encodeArray = function(o){
7102        var a = ["["], b, i, l = o.length, v;
7103            for (i = 0; i < l; i += 1) {
7104                v = o[i];
7105                switch (typeof v) {
7106                    case "undefined":
7107                    case "function":
7108                    case "unknown":
7109                        break;
7110                    default:
7111                        if (b) {
7112                            a.push(',');
7113                        }
7114                        a.push(v === null ? "null" : Ext.util.JSON.encode(v));
7115                        b = true;
7116                }
7117            }
7118            a.push("]");
7119            return a.join("");
7120    };
7121
7122    this.encodeDate = function(o){
7123        return '"' + o.getFullYear() + "-" +
7124                pad(o.getMonth() + 1) + "-" +
7125                pad(o.getDate()) + "T" +
7126                pad(o.getHours()) + ":" +
7127                pad(o.getMinutes()) + ":" +
7128                pad(o.getSeconds()) + '"';
7129    };
7130
7131    
7132    this.encode = function(o){
7133        if(typeof o == "undefined" || o === null){
7134            return "null";
7135        }else if(Ext.isArray(o)){
7136            return encodeArray(o);
7137        }else if(Ext.isDate(o)){
7138            return Ext.util.JSON.encodeDate(o);
7139        }else if(typeof o == "string"){
7140            return encodeString(o);
7141        }else if(typeof o == "number"){
7142            return isFinite(o) ? String(o) : "null";
7143        }else if(typeof o == "boolean"){
7144            return String(o);
7145        }else {
7146            var a = ["{"], b, i, v;
7147            for (i in o) {
7148                if(!useHasOwn || o.hasOwnProperty(i)) {
7149                    v = o[i];
7150                    switch (typeof v) {
7151                    case "undefined":
7152                    case "function":
7153                    case "unknown":
7154                        break;
7155                    default:
7156                        if(b){
7157                            a.push(',');
7158                        }
7159                        a.push(this.encode(i), ":",
7160                                v === null ? "null" : this.encode(v));
7161                        b = true;
7162                    }
7163                }
7164            }
7165            a.push("}");
7166            return a.join("");
7167        }
7168    };
7169
7170    
7171    this.decode = function(json){
7172        return eval("(" + json + ')');
7173    };
7174})();
7175
7176Ext.encode = Ext.util.JSON.encode;
7177
7178Ext.decode = Ext.util.JSON.decode;
7179
7180
7181Ext.util.Format = function(){
7182    var trimRe = /^\s+|\s+$/g;
7183    return {
7184        
7185        ellipsis : function(value, len){
7186            if(value && value.length > len){
7187                return value.substr(0, len-3)+"...";
7188            }
7189            return value;
7190        },
7191
7192        
7193        undef : function(value){
7194            return value !== undefined ? value : "";
7195        },
7196
7197        
7198        defaultValue : function(value, defaultValue){
7199            return value !== undefined && value !== '' ? value : defaultValue;
7200        },
7201
7202        
7203        htmlEncode : function(value){
7204            return !value ? value : String(value).replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/</g, "&lt;").replace(/"/g, "&quot;");
7205        },
7206
7207        
7208        htmlDecode : function(value){
7209            return !value ? value : String(value).replace(/&gt;/g, ">").replace(/&lt;/g, "<").replace(/&quot;/g, '"').replace(/&amp;/g, "&");
7210        },
7211
7212        
7213        trim : function(value){
7214            return String(value).replace(trimRe, "");
7215        },
7216
7217        
7218        substr : function(value, start, length){
7219            return String(value).substr(start, length);
7220        },
7221
7222        
7223        lowercase : function(value){
7224            return String(value).toLowerCase();
7225        },
7226
7227        
7228        uppercase : function(value){
7229            return String(value).toUpperCase();
7230        },
7231
7232        
7233        capitalize : function(value){
7234            return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
7235        },
7236
7237        // private
7238        call : function(value, fn){
7239            if(arguments.length > 2){
7240                var args = Array.prototype.slice.call(arguments, 2);
7241                args.unshift(value);
7242                return eval(fn).apply(window, args);
7243            }else{
7244                return eval(fn).call(window, value);
7245            }
7246        },
7247
7248        
7249        usMoney : function(v){
7250            v = (Math.round((v-0)*100))/100;
7251            v = (v == Math.floor(v)) ? v + ".00" : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
7252            v = String(v);
7253            var ps = v.split('.');
7254            var whole = ps[0];
7255            var sub = ps[1] ? '.'+ ps[1] : '.00';
7256            var r = /(\d+)(\d{3})/;
7257            while (r.test(whole)) {
7258                whole = whole.replace(r, '$1' + ',' + '$2');
7259            }
7260            v = whole + sub;
7261            if(v.charAt(0) == '-'){
7262                return '-$' + v.substr(1);
7263            }
7264            return "$" +  v;
7265        },
7266
7267        
7268        date : function(v, format){
7269            if(!v){
7270                return "";
7271            }
7272            if(!Ext.isDate(v)){
7273                v = new Date(Date.parse(v));
7274            }
7275            return v.dateFormat(format || "m/d/Y");
7276        },
7277
7278        
7279        dateRenderer : function(format){
7280            return function(v){
7281                return Ext.util.Format.date(v, format);
7282            };
7283        },
7284
7285        // private
7286        stripTagsRE : /<\/?[^>]+>/gi,
7287        
7288        
7289        stripTags : function(v){
7290            return !v ? v : String(v).replace(this.stripTagsRE, "");
7291        },
7292
7293        // private
7294        stripScriptsRe : /(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig,
7295
7296        
7297        stripScripts : function(v){
7298            return !v ? v : String(v).replace(this.stripScriptsRe, "");
7299        },
7300
7301        
7302        fileSize : function(size){
7303            if(size < 1024) {
7304                return size + " bytes";
7305            } else if(size < 1048576) {
7306                return (Math.round(((size*10) / 1024))/10) + " KB";
7307            } else {
7308                return (Math.round(((size*10) / 1048576))/10) + " MB";
7309            }
7310        },
7311
7312        math : function(){
7313            var fns = {};
7314            return function(v, a){
7315                if(!fns[a]){
7316                    fns[a] = new Function('v', 'return v ' + a + ';');
7317                }
7318                return fns[a](v);
7319            }
7320        }(),
7321
7322		
7323        nl2br : function(v){
7324            return v === undefined || v === null ? '' : v.replace(/\n/g, '<br/>');
7325        }
7326    };
7327}();
7328
7329Ext.XTemplate = function(){
7330    Ext.XTemplate.superclass.constructor.apply(this, arguments);
7331    var s = this.html;
7332
7333    s = ['<tpl>', s, '</tpl>'].join('');
7334
7335    var re = /<tpl\b[^>]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/;
7336
7337    var nameRe = /^<tpl\b[^>]*?for="(.*?)"/;
7338    var ifRe = /^<tpl\b[^>]*?if="(.*?)"/;
7339    var execRe = /^<tpl\b[^>]*?exec="(.*?)"/;
7340    var m, id = 0;
7341    var tpls = [];
7342
7343    while(m = s.match(re)){
7344       var m2 = m[0].match(nameRe);
7345       var m3 = m[0].match(ifRe);
7346       var m4 = m[0].match(execRe);
7347       var exp = null, fn = null, exec = null;
7348       var name = m2 && m2[1] ? m2[1] : '';
7349       if(m3){
7350           exp = m3 && m3[1] ? m3[1] : null;
7351           if(exp){
7352               fn = new Function('values', 'parent', 'xindex', 'xcount', 'with(values){ return '+(Ext.util.Format.htmlDecode(exp))+'; }');
7353           }
7354       }
7355       if(m4){
7356           exp = m4 && m4[1] ? m4[1] : null;
7357           if(exp){
7358               exec = new Function('values', 'parent', 'xindex', 'xcount', 'with(values){ '+(Ext.util.Format.htmlDecode(exp))+'; }');
7359           }
7360       }
7361       if(name){
7362           switch(name){
7363               case '.': name = new Function('values', 'parent', 'with(values){ return values; }'); break;
7364               case '..': name = new Function('values', 'parent', 'with(values){ return parent; }'); break;
7365               default: name = new Function('values', 'parent', 'with(values){ return '+name+'; }');
7366           }
7367       }
7368       tpls.push({
7369            id: id,
7370            target: name,
7371            exec: exec,
7372            test: fn,
7373            body: m[1]||''
7374        });
7375       s = s.replace(m[0], '{xtpl'+ id + '}');
7376       ++id;
7377    }
7378    for(var i = tpls.length-1; i >= 0; --i){
7379        this.compileTpl(tpls[i]);
7380    }
7381    this.master = tpls[tpls.length-1];
7382    this.tpls = tpls;
7383};
7384Ext.extend(Ext.XTemplate, Ext.Template, {
7385    // private
7386    re : /\{([\w-\.\#]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?(\s?[\+\-\*\\]\s?[\d\.\+\-\*\\\(\)]+)?\}/g,
7387    // private
7388    codeRe : /\{\[((?:\\\]|.|\n)*?)\]\}/g,
7389
7390    // private
7391    applySubTemplate : function(id, values, parent, xindex, xcount){
7392        var t = this.tpls[id];
7393        if(t.test && !t.test.call(this, values, parent, xindex, xcount)){
7394            return '';
7395        }
7396        if(t.exec && t.exec.call(this, values, parent, xindex, xcount)){
7397            return '';
7398        }
7399        var vs = t.target ? t.target.call(this, values, parent) : values;
7400        parent = t.target ? values : parent;
7401        if(t.target && Ext.isArray(vs)){
7402            var buf = [];
7403            for(var i = 0, len = vs.length; i < len; i++){
7404                buf[buf.length] = t.compiled.call(this, vs[i], parent, i+1, len);
7405            }
7406            return buf.join('');
7407        }
7408        return t.compiled.call(this, vs, parent, xindex, xcount);
7409    },
7410
7411    // private
7412    compileTpl : function(tpl){
7413        var fm = Ext.util.Format;
7414        var useF = this.disableFormats !== true;
7415        var sep = Ext.isGecko ? "+" : ",";
7416        var fn = function(m, name, format, args, math){
7417            if(name.substr(0, 4) == 'xtpl'){
7418                return "'"+ sep +'this.applySubTemplate('+name.substr(4)+', values, parent, xindex, xcount)'+sep+"'";
7419            }
7420            var v;
7421            if(name === '.'){
7422                v = 'values';
7423            }else if(name === '#'){
7424                v = 'xindex';
7425            }else if(name.indexOf('.') != -1){
7426                v = name;
7427            }else{
7428                v = "values['" + name + "']";
7429            }
7430            if(math){
7431                v = '(' + v + math + ')';
7432            }
7433            if(format && useF){
7434                args = args ? ',' + args : "";
7435                if(format.substr(0, 5) != "this."){
7436                    format = "fm." + format + '(';
7437                }else{
7438                    format = 'this.call("'+ format.substr(5) + '", ';
7439                    args = ", values";
7440                }
7441            }else{
7442                args= ''; format = "("+v+" === undefined ? '' : ";
7443            }
7444            return "'"+ sep + format + v + args + ")"+sep+"'";
7445        };
7446        var codeFn = function(m, code){
7447            return "'"+ sep +'('+code+')'+sep+"'";
7448        };
7449
7450        var body;
7451        // branched to use + in gecko and [].join() in others
7452        if(Ext.isGecko){
7453            body = "tpl.compiled = function(values, parent, xindex, xcount){ return '" +
7454                   tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn).replace(this.codeRe, codeFn) +
7455                    "';};";
7456        }else{
7457            body = ["tpl.compiled = function(values, parent, xindex, xcount){ return ['"];
7458            body.push(tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn).replace(this.codeRe, codeFn));
7459            body.push("'].join('');};");
7460            body = body.join('');
7461        }
7462        eval(body);
7463        return this;
7464    },
7465
7466    
7467    applyTemplate : function(values){
7468        return this.master.compiled.call(this, values, {}, 1, 1);
7469    },
7470
7471    
7472    compile : function(){return this;}
7473
7474    
7475    
7476    
7477
7478});
7479
7480Ext.XTemplate.prototype.apply = Ext.XTemplate.prototype.applyTemplate;
7481
7482
7483Ext.XTemplate.from = function(el){
7484    el = Ext.getDom(el);
7485    return new Ext.XTemplate(el.value || el.innerHTML);
7486};
7487
7488Ext.util.CSS = function(){
7489	var rules = null;
7490   	var doc = document;
7491
7492    var camelRe = /(-[a-z])/gi;
7493    var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
7494
7495   return {
7496   
7497   createStyleSheet : function(cssText, id){
7498       var ss;
7499       var head = doc.getElementsByTagName("head")[0];
7500       var rules = doc.createElement("style");
7501       rules.setAttribute("type", "text/css");
7502       if(id){
7503           rules.setAttribute("id", id);
7504       }
7505       if(Ext.isIE){
7506           head.appendChild(rules);
7507           ss = rules.styleSheet;
7508           ss.cssText = cssText;
7509       }else{
7510           try{
7511                rules.appendChild(doc.createTextNode(cssText));
7512           }catch(e){
7513               rules.cssText = cssText;
7514           }
7515           head.appendChild(rules);
7516           ss = rules.styleSheet ? rules.styleSheet : (rules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
7517       }
7518       this.cacheStyleSheet(ss);
7519       return ss;
7520   },
7521
7522   
7523   removeStyleSheet : function(id){
7524       var existing = doc.getElementById(id);
7525       if(existing){
7526           existing.parentNode.removeChild(existing);
7527       }
7528   },
7529
7530   
7531   swapStyleSheet : function(id, url){
7532       this.removeStyleSheet(id);
7533       var ss = doc.createElement("link");
7534       ss.setAttribute("rel", "stylesheet");
7535       ss.setAttribute("type", "text/css");
7536       ss.setAttribute("id", id);
7537       ss.setAttribute("href", url);
7538       doc.getElementsByTagName("head")[0].appendChild(ss);
7539   },
7540   
7541   
7542   refreshCache : function(){
7543       return this.getRules(true);
7544   },
7545
7546   // private
7547   cacheStyleSheet : function(ss){
7548       if(!rules){
7549           rules = {};
7550       }
7551       try{// try catch for cross domain access issue
7552           var ssRules = ss.cssRules || ss.rules;
7553           for(var j = ssRules.length-1; j >= 0; --j){
7554               rules[ssRules[j].selectorText] = ssRules[j];
7555           }
7556       }catch(e){}
7557   },
7558   
7559   
7560   getRules : function(refreshCache){
7561   		if(rules == null || refreshCache){
7562   			rules = {};
7563   			var ds = doc.styleSheets;
7564   			for(var i =0, len = ds.length; i < len; i++){
7565   			    try{
7566    		        this.cacheStyleSheet(ds[i]);
7567    		    }catch(e){} 
7568	        }
7569   		}
7570   		return rules;
7571   	},
7572   	
7573   	
7574   getRule : function(selector, refreshCache){
7575   		var rs = this.getRules(refreshCache);
7576   		if(!Ext.isArray(selector)){
7577   		    return rs[selector];
7578   		}
7579   		for(var i = 0; i < selector.length; i++){
7580			if(rs[selector[i]]){
7581				return rs[selector[i]];
7582			}
7583		}
7584		return null;
7585   	},
7586   	
7587   	
7588   	
7589   updateRule : function(selector, property, value){
7590   		if(!Ext.isArray(selector)){
7591   			var rule = this.getRule(selector);
7592   			if(rule){
7593   				rule.style[property.replace(camelRe, camelFn)] = value;
7594   				return true;
7595   			}
7596   		}else{
7597   			for(var i = 0; i < selector.length; i++){
7598   				if(this.updateRule(selector[i], property, value)){
7599   					return true;
7600   				}
7601   			}
7602   		}
7603   		return false;
7604   	}
7605   };	
7606}();
7607
7608Ext.util.ClickRepeater = function(el, config)
7609{
7610    this.el = Ext.get(el);
7611    this.el.unselectable();
7612
7613    Ext.apply(this, config);
7614
7615    this.addEvents(
7616    
7617        "mousedown",
7618    
7619        "click",
7620    
7621        "mouseup"
7622    );
7623
7624    this.el.on("mousedown", this.handleMouseDown, this);
7625    if(this.preventDefault || this.stopDefault){
7626        this.el.on("click", function(e){
7627            if(this.preventDefault){
7628                e.preventDefault();
7629            }
7630            if(this.stopDefault){
7631                e.stopEvent();
7632            }
7633        }, this);
7634    }
7635
7636    // allow inline handler
7637    if(this.handler){
7638        this.on("click", this.handler,  this.scope || this);
7639    }
7640
7641    Ext.util.ClickRepeater.superclass.constructor.call(this);
7642};
7643
7644Ext.extend(Ext.util.ClickRepeater, Ext.util.Observable, {
7645    interval : 20,
7646    delay: 250,
7647    preventDefault : true,
7648    stopDefault : false,
7649    timer : 0,
7650
7651    // private
7652    destroy : function() {
7653        Ext.destroy(this.el);
7654        this.purgeListeners();
7655    },
7656    
7657    // private
7658    handleMouseDown : function(){
7659        clearTimeout(this.timer);
7660        this.el.blur();
7661        if(this.pressClass){
7662            this.el.addClass(this.pressClass);
7663        }
7664        this.mousedownTime = new Date();
7665
7666        Ext.getDoc().on("mouseup", this.handleMouseUp, this);
7667        this.el.on("mouseout", this.handleMouseOut, this);
7668
7669        this.fireEvent("mousedown", this);
7670        this.fireEvent("click", this);
7671
7672//      Do not honor delay or interval if acceleration wanted.
7673        if (this.accelerate) {
7674            this.delay = 400;
7675	    }
7676        this.timer = this.click.defer(this.delay || this.interval, this);
7677    },
7678
7679    // private
7680    click : function(){
7681        this.fireEvent("click", this);
7682        this.timer = this.click.defer(this.accelerate ?
7683            this.easeOutExpo(this.mousedownTime.getElapsed(),
7684                400,
7685                -390,
7686                12000) :
7687            this.interval, this);
7688    },
7689
7690    easeOutExpo : function (t, b, c, d) {
7691        return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
7692    },
7693
7694    // private
7695    handleMouseOut : function(){
7696        clearTimeout(this.timer);
7697        if(this.pressClass){
7698            this.el.removeClass(this.pressClass);
7699        }
7700        this.el.on("mouseover", this.handleMouseReturn, this);
7701    },
7702
7703    // private
7704    handleMouseReturn : function(){
7705        this.el.un("mouseover", this.handleMouseReturn, this);
7706        if(this.pressClass){
7707            this.el.addClass(this.pressClass);
7708        }
7709        this.click();
7710    },
7711
7712    // private
7713    handleMouseUp : function(){
7714        clearTimeout(this.timer);
7715        this.el.un("mouseover", this.handleMouseReturn, this);
7716        this.el.un("mouseout", this.handleMouseOut, this);
7717        Ext.getDoc().un("mouseup", this.handleMouseUp, this);
7718        this.el.removeClass(this.pressClass);
7719        this.fireEvent("mouseup", this);
7720    }
7721});
7722
7723Ext.KeyNav = function(el, config){
7724    this.el = Ext.get(el);
7725    Ext.apply(this, config);
7726    if(!this.disabled){
7727        this.disabled = true;
7728        this.enable();
7729    }
7730};
7731
7732Ext.KeyNav.prototype = {
7733    
7734    disabled : false,
7735    
7736    defaultEventAction: "stopEvent",
7737    
7738    forceKeyDown : false,
7739
7740    // private
7741    prepareEvent : function(e){
7742        var k = e.getKey();
7743        var h = this.keyToHandler[k];
7744        //if(h && this[h]){
7745        //    e.stopPropagation();
7746        //}
7747        if(Ext.isSafari2 && h && k >= 37 && k <= 40){
7748            e.stopEvent();
7749        }
7750    },
7751
7752    // private
7753    relay : function(e){
7754        var k = e.getKey();
7755        var h = this.keyToHandler[k];
7756        if(h && this[h]){
7757            if(this.doRelay(e, this[h], h) !== true){
7758                e[this.defaultEventAction]();
7759            }
7760        }
7761    },
7762
7763    // private
7764    doRelay : function(e, h, hname){
7765        return h.call(this.scope || this, e);
7766    },
7767
7768    // possible handlers
7769    enter : false,
7770    left : false,
7771    right : false,
7772    up : false,
7773    down : false,
7774    tab : false,
7775    esc : false,
7776    pageUp : false,
7777    pageDown : false,
7778    del : false,
7779    home : false,
7780    end : false,
7781
7782    // quick lookup hash
7783    keyToHandler : {
7784        37 : "left",
7785        39 : "right",
7786        38 : "up",
7787        40 : "down",
7788        33 : "pageUp",
7789        34 : "pageDown",
7790        46 : "del",
7791        36 : "home",
7792        35 : "end",
7793        13 : "enter",
7794        27 : "esc",
7795        9  : "tab"
7796    },
7797
7798	
7799	enable: function(){
7800		if(this.disabled){
7801            if(this.forceKeyDown || Ext.isIE || Ext.isSafari3 || Ext.isAir){
7802                this.el.on("keydown", this.relay,  this);
7803            }else{
7804                this.el.on("keydown", this.prepareEvent,  this);
7805                this.el.on("keypress", this.relay,  this);
7806            }
7807		    this.disabled = false;
7808		}
7809	},
7810
7811	
7812	disable: function(){
7813		if(!this.disabled){
7814		    if(this.forceKeyDown || Ext.isIE || Ext.isSafari3 || Ext.isAir){
7815                this.el.un("keydown", this.relay, this);
7816            }else{
7817                this.el.un("keydown", this.prepareEvent, this);
7818                this.el.un("keypress", this.relay, this);
7819            }
7820		    this.disabled = true;
7821		}
7822	}
7823};
7824
7825Ext.KeyMap = function(el, config, eventName){
7826    this.el  = Ext.get(el);
7827    this.eventName = eventName || "keydown";
7828    this.bindings = [];
7829    if(config){
7830        this.addBinding(config);
7831    }
7832    this.enable();
7833};
7834
7835Ext.KeyMap.prototype = {
7836    
7837    stopEvent : false,
7838
7839    
7840	addBinding : function(config){
7841        if(Ext.isArray(config)){
7842            for(var i = 0, len = config.length; i < len; i++){
7843                this.addBinding(config[i]);
7844            }
7845            return;
7846        }
7847        var keyCode = config.key,
7848            shift = config.shift,
7849            ctrl = config.ctrl,
7850            alt = config.alt,
7851            fn = config.fn || config.handler,
7852            scope = config.scope;
7853	
7854	if (config.stopEvent) {
7855	    this.stopEvent = config.stopEvent;    
7856	}	
7857
7858        if(typeof keyCode == "string"){
7859            var ks = [];
7860            var keyString = keyCode.toUpperCase();
7861            for(var j = 0, len = keyString.length; j < len; j++){
7862                ks.push(keyString.charCodeAt(j));
7863            }
7864            keyCode = ks;
7865        }
7866        var keyArray = Ext.isArray(keyCode);
7867        
7868        var handler = function(e){
7869            if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) &&  (!alt || e.altKey)){
7870                var k = e.getKey();
7871                if(keyArray){
7872                    for(var i = 0, len = keyCode.length; i < len; i++){
7873                        if(keyCode[i] == k){
7874                          if(this.stopEvent){
7875                              e.stopEvent();
7876                          }
7877                          fn.call(scope || window, k, e);
7878                          return;
7879                        }
7880                    }
7881                }else{
7882                    if(k == keyCode){
7883                        if(this.stopEvent){
7884                           e.stopEvent();
7885                        }
7886                        fn.call(scope || window, k, e);
7887                    }
7888                }
7889            }
7890        };
7891        this.bindings.push(handler);
7892	},
7893
7894    
7895    on : function(key, fn, scope){
7896        var keyCode, shift, ctrl, alt;
7897        if(typeof key == "object" && !Ext.isArray(key)){
7898            keyCode = key.key;
7899            shift = key.shift;
7900            ctrl = key.ctrl;
7901            alt = key.alt;
7902        }else{
7903            keyCode = key;
7904        }
7905        this.addBinding({
7906            key: keyCode,
7907            shift: shift,
7908            ctrl: ctrl,
7909            alt: alt,
7910            fn: fn,
7911            scope: scope
7912        })
7913    },
7914
7915    // private
7916    handleKeyDown : function(e){
7917	    if(this.enabled){ //just in case
7918    	    var b = this.bindings;
7919    	    for(var i = 0, len = b.length; i < len; i++){
7920    	        b[i].call(this, e);
7921    	    }
7922	    }
7923	},
7924
7925	
7926	isEnabled : function(){
7927	    return this.enabled;
7928	},
7929
7930	
7931	enable: function(){
7932		if(!this.enabled){
7933		    this.el.on(this.eventName, this.handleKeyDown, this);
7934		    this.enabled = true;
7935		}
7936	},
7937
7938	
7939	disable: function(){
7940		if(this.enabled){
7941		    this.el.removeListener(this.eventName, this.handleKeyDown, this);
7942		    this.enabled = false;
7943		}
7944	}
7945};
7946
7947Ext.util.TextMetrics = function(){
7948    var shared;
7949    return {
7950        
7951        measure : function(el, text, fixedWidth){
7952            if(!shared){
7953                shared = Ext.util.TextMetrics.Instance(el, fixedWidth);
7954            }
7955            shared.bind(el);
7956            shared.setFixedWidth(fixedWidth || 'auto');
7957            return shared.getSize(text);
7958        },
7959
7960        
7961        createInstance : function(el, fixedWidth){
7962            return Ext.util.TextMetrics.Instance(el, fixedWidth);
7963        }
7964    };
7965}();
7966
7967Ext.util.TextMetrics.Instance = function(bindTo, fixedWidth){
7968    var ml = new Ext.Element(document.createElement('div'));
7969    document.body.appendChild(ml.dom);
7970    ml.position('absolute');
7971    ml.setLeftTop(-1000, -1000);
7972    ml.hide();
7973
7974    if(fixedWidth){
7975        ml.setWidth(fixedWidth);
7976    }
7977
7978    var instance = {
7979        
7980        getSize : function(text){
7981            ml.update(text);
7982            var s = ml.getSize();
7983            ml.update('');
7984            return s;
7985        },
7986
7987        
7988        bind : function(el){
7989            ml.setStyle(
7990                Ext.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height', 'text-transform', 'letter-spacing')
7991            );
7992        },
7993
7994        
7995        setFixedWidth : function(width){
7996            ml.setWidth(width);
7997        },
7998
7999        
8000        getWidth : function(text){
8001            ml.dom.style.width = 'auto';
8002            return this.getSize(text).width;
8003        },
8004
8005        
8006        getHeight : function(text){
8007            return this.getSize(text).height;
8008        }
8009    };
8010
8011    instance.bind(bindTo);
8012
8013    return instance;
8014};
8015
8016// backwards compat
8017Ext.Element.measureText = Ext.util.TextMetrics.measure;
8018
8019
8020(function() {
8021
8022var Event=Ext.EventManager;
8023var Dom=Ext.lib.Dom;
8024
8025
8026Ext.dd.DragDrop = function(id, sGroup, config) {
8027    if(id) {
8028        this.init(id, sGroup, config);
8029    }
8030};
8031
8032Ext.dd.DragDrop.prototype = {
8033
8034    
8035    id: null,
8036
8037    
8038    config: null,
8039
8040    
8041    dragElId: null,
8042
8043    
8044    handleElId: null,
8045
8046    
8047    invalidHandleTypes: null,
8048
8049    
8050    invalidHandleIds: null,
8051
8052    
8053    invalidHandleClasses: null,
8054
8055    
8056    startPageX: 0,
8057
8058    
8059    startPageY: 0,
8060
8061    
8062    groups: null,
8063
8064    
8065    locked: false,
8066
8067    
8068    lock: function() { this.locked = true; },
8069
8070    
8071    moveOnly: false,
8072
8073    
8074    unlock: function() { this.locked = false; },
8075
8076    
8077    isTarget: true,
8078
8079    
8080    padding: null,
8081
8082    
8083    _domRef: null,
8084
8085    
8086    __ygDragDrop: true,
8087
8088    
8089    constrainX: false,
8090
8091    
8092    constrainY: false,
8093
8094    
8095    minX: 0,
8096
8097    
8098    maxX: 0,
8099
8100    
8101    minY: 0,
8102
8103    
8104    maxY: 0,
8105
8106    
8107    maintainOffset: false,
8108
8109    
8110    xTicks: null,
8111
8112    
8113    yTicks: null,
8114
8115    
8116    primaryButtonOnly: true,
8117
8118    
8119    available: false,
8120
8121    
8122    hasOuterHandles: false,
8123
8124    
8125    b4StartDrag: function(x, y) { },
8126
8127    
8128    startDrag: function(x, y) {  },
8129
8130    
8131    b4Drag: function(e) { },
8132
8133    
8134    onDrag: function(e) {  },
8135
8136    
8137    onDragEnter: function(e, id) {  },
8138
8139    
8140    b4DragOver: function(e) { },
8141
8142    
8143    onDragOver: function(e, id) {  },
8144
8145    
8146    b4DragOut: function(e) { },
8147
8148    
8149    onDragOut: function(e, id) {  },
8150
8151    
8152    b4DragDrop: function(e) { },
8153
8154    
8155    onDragDrop: function(e, id) {  },
8156
8157    
8158    onInvalidDrop: function(e) {  },
8159
8160    
8161    b4EndDrag: function(e) { },
8162
8163    
8164    endDrag: function(e) {  },
8165
8166    
8167    b4MouseDown: function(e) {  },
8168
8169    
8170    onMouseDown: function(e) {  },
8171
8172    
8173    onMouseUp: function(e) {  },
8174
8175    
8176    onAvailable: function () {
8177    },
8178
8179    
8180    defaultPadding : {left:0, right:0, top:0, bottom:0},
8181
8182    
8183    constrainTo : function(constrainTo, pad, inContent){
8184        if(typeof pad == "number"){
8185            pad = {left: pad, right:pad, top:pad, bottom:pad};
8186        }
8187        pad = pad || this.defaultPadding;
8188        var b = Ext.get(this.getEl()).getBox();
8189        var ce = Ext.get(constrainTo);
8190        var s = ce.getScroll();
8191        var c, cd = ce.dom;
8192        if(cd == document.body){
8193            c = { x: s.left, y: s.top, width: Ext.lib.Dom.getViewWidth(), height: Ext.lib.Dom.getViewHeight()};
8194        }else{
8195            var xy = ce.getXY();
8196            c = {x : xy[0]+s.left, y: xy[1]+s.top, width: cd.clientWidth, height: cd.clientHeight};
8197        }
8198
8199
8200        var topSpace = b.y - c.y;
8201        var leftSpace = b.x - c.x;
8202
8203        this.resetConstraints();
8204        this.setXConstraint(leftSpace - (pad.left||0), // left
8205                c.width - leftSpace - b.width - (pad.right||0), //right
8206				this.xTickSize
8207        );
8208        this.setYConstraint(topSpace - (pad.top||0), //top
8209                c.height - topSpace - b.height - (pad.bottom||0), //bottom
8210				this.yTickSize
8211        );
8212    },
8213
8214    
8215    getEl: function() {
8216        if (!this._domRef) {
8217            this._domRef = Ext.getDom(this.id);
8218        }
8219
8220        return this._domRef;
8221    },
8222
8223    
8224    getDragEl: function() {
8225        return Ext.getDom(this.dragElId);
8226    },
8227
8228    
8229    init: function(id, sGroup, config) {
8230        this.initTarget(id, sGroup, config);
8231        Event.on(this.id, "mousedown", this.handleMouseDown, this);
8232        // Event.on(this.id, "selectstart", Event.preventDefault);
8233    },
8234
8235    
8236    initTarget: function(id, sGroup, config) {
8237
8238        // configuration attributes
8239        this.config = config || {};
8240
8241        // create a local reference to the drag and drop manager
8242        this.DDM = Ext.dd.DDM;
8243        // initialize the groups array
8244        this.groups = {};
8245
8246        // assume that we have an element reference instead of an id if the
8247        // parameter is not a string
8248        if (typeof id !== "string") {
8249            id = Ext.id(id);
8250        }
8251
8252        // set the id
8253        this.id = id;
8254
8255        // add to an interaction group
8256        this.addToGroup((sGroup) ? sGroup : "default");
8257
8258        // We don't want to register this as the handle with the manager
8259        // so we just set the id rather than calling the setter.
8260        this.handleElId = id;
8261
8262        // the linked element is the element that gets dragged by default
8263        this.setDragElId(id);
8264
8265        // by default, clicked anchors will not start drag operations.
8266        this.invalidHandleTypes = { A: "A" };
8267        this.invalidHandleIds = {};
8268        this.invalidHandleClasses = [];
8269
8270        this.applyConfig();
8271
8272        this.handleOnAvailable();
8273    },
8274
8275    
8276    applyConfig: function() {
8277
8278        // configurable properties:
8279        //    padding, isTarget, maintainOffset, primaryButtonOnly
8280        this.padding           = this.config.padding || [0, 0, 0, 0];
8281        this.isTarget          = (this.config.isTarget !== false);
8282        this.maintainOffset    = (this.config.maintainOffset);
8283        this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
8284
8285    },
8286
8287    
8288    handleOnAvailable: function() {
8289        this.available = true;
8290        this.resetConstraints();
8291        this.onAvailable();
8292    },
8293
8294     
8295    setPadding: function(iTop, iRight, iBot, iLeft) {
8296        // this.padding = [iLeft, iRight, iTop, iBot];
8297        if (!iRight && 0 !== iRight) {
8298            this.padding = [iTop, iTop, iTop, iTop];
8299        } else if (!iBot && 0 !== iBot) {
8300            this.padding = [iTop, iRight, iTop, iRight];
8301        } else {
8302            this.padding = [iTop, iRight, iBot, iLeft];
8303        }
8304    },
8305
8306    
8307    setInitPosition: function(diffX, diffY) {
8308        var el = this.getEl();
8309
8310        if (!this.DDM.verifyEl(el)) {
8311            return;
8312        }
8313
8314        var dx = diffX || 0;
8315        var dy = diffY || 0;
8316
8317        var p = Dom.getXY( el );
8318
8319        this.initPageX = p[0] - dx;
8320        this.initPageY = p[1] - dy;
8321
8322        this.lastPageX = p[0];
8323        this.lastPageY = p[1];
8324
8325
8326        this.setStartPosition(p);
8327    },
8328
8329    
8330    setStartPosition: function(pos) {
8331        var p = pos || Dom.getXY( this.getEl() );
8332        this.deltaSetXY = null;
8333
8334        this.startPageX = p[0];
8335        this.startPageY = p[1];
8336    },
8337
8338    
8339    addToGroup: function(sGroup) {
8340        this.groups[sGroup] = true;
8341        this.DDM.regDragDrop(this, sGroup);
8342    },
8343
8344    
8345    removeFromGroup: function(sGroup) {
8346        if (this.groups[sGroup]) {
8347            delete this.groups[sGroup];
8348        }
8349
8350        this.DDM.removeDDFromGroup(this, sGroup);
8351    },
8352
8353    
8354    setDragElId: function(id) {
8355        this.dragElId = id;
8356    },
8357
8358    
8359    setHandleElId: function(id) {
8360        if (typeof id !== "string") {
8361            id = Ext.id(id);
8362        }
8363        this.handleElId = id;
8364        this.DDM.regHandle(this.id, id);
8365    },
8366
8367    
8368    setOuterHandleElId: function(id) {
8369        if (typeof id !== "string") {
8370            id = Ext.id(id);
8371        }
8372        Event.on(id, "mousedown",
8373                this.handleMouseDown, this);
8374        this.setHandleElId(id);
8375
8376        this.hasOuterHandles = true;
8377    },
8378
8379    
8380    unreg: function() {
8381        Event.un(this.id, "mousedown",
8382                this.handleMouseDown);
8383        this._domRef = null;
8384        this.DDM._remove(this);
8385    },
8386
8387    destroy : function(){
8388        this.unreg();
8389    },
8390
8391    
8392    isLocked: function() {
8393        return (this.DDM.isLocked() || this.locked);
8394    },
8395
8396    
8397    handleMouseDown: function(e, oDD){
8398        if (this.primaryButtonOnly && e.button != 0) {
8399            return;
8400        }
8401
8402        if (this.isLocked()) {
8403            return;
8404        }
8405
8406        this.DDM.refreshCache(this.groups);
8407
8408        var pt = new Ext.lib.Point(Ext.lib.Event.getPageX(e), Ext.lib.Event.getPageY(e));
8409        if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) )  {
8410        } else {
8411            if (this.clickValidator(e)) {
8412
8413                // set the initial element position
8414                this.setStartPosition();
8415
8416
8417                this.b4MouseDown(e);
8418                this.onMouseDown(e);
8419
8420                this.DDM.handleMouseDown(e, this);
8421
8422                this.DDM.stopEvent(e);
8423            } else {
8424
8425
8426            }
8427        }
8428    },
8429
8430    clickValidator: function(e) {
8431        var target = e.getTarget();
8432        return ( this.isValidHandleChild(target) &&
8433                    (this.id == this.handleElId ||
8434                        this.DDM.handleWasClicked(target, this.id)) );
8435    },
8436
8437    
8438    addInvalidHandleType: function(tagName) {
8439        var type = tagName.toUpperCase();
8440        this.invalidHandleTypes[type] = type;
8441    },
8442
8443    
8444    addInvalidHandleId: function(id) {
8445        if (typeof id !== "string") {
8446            id = Ext.id(id);
8447        }
8448        this.invalidHandleIds[id] = id;
8449    },
8450
8451    
8452    addInvalidHandleClass: function(cssClass) {
8453        this.invalidHandleClasses.push(cssClass);
8454    },
8455
8456    
8457    removeInvalidHandleType: function(tagName) {
8458        var type = tagName.toUpperCase();
8459        // this.invalidHandleTypes[type] = null;
8460        delete this.invalidHandleTypes[type];
8461    },
8462
8463    
8464    removeInvalidHandleId: function(id) {
8465        if (typeof id !== "string") {
8466            id = Ext.id(id);
8467        }
8468        delete this.invalidHandleIds[id];
8469    },
8470
8471    
8472    removeInvalidHandleClass: function(cssClass) {
8473        for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {
8474            if (this.invalidHandleClasses[i] == cssClass) {
8475                delete this.invalidHandleClasses[i];
8476            }
8477        }
8478    },
8479
8480    
8481    isValidHandleChild: function(node) {
8482
8483        var valid = true;
8484        // var n = (node.nodeName == "#text") ? node.parentNode : node;
8485        var nodeName;
8486        try {
8487            nodeName = node.nodeName.toUpperCase();
8488        } catch(e) {
8489            nodeName = node.nodeName;
8490        }
8491        valid = valid && !this.invalidHandleTypes[nodeName];
8492        valid = valid && !this.invalidHandleIds[node.id];
8493
8494        for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {
8495            valid = !Ext.fly(node).hasClass(this.invalidHandleClasses[i]);
8496        }
8497
8498
8499        return valid;
8500
8501    },
8502
8503    
8504    setXTicks: function(iStartX, iTickSize) {
8505        this.xTicks = [];
8506        this.xTickSize = iTickSize;
8507
8508        var tickMap = {};
8509
8510        for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
8511            if (!tickMap[i]) {
8512                this.xTicks[this.xTicks.length] = i;
8513                tickMap[i] = true;
8514            }
8515        }
8516
8517        for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
8518            if (!tickMap[i]) {
8519                this.xTicks[this.xTicks.length] = i;
8520                tickMap[i] = true;
8521            }
8522        }
8523
8524        this.xTicks.sort(this.DDM.numericSort) ;
8525    },
8526
8527    
8528    setYTicks: function(iStartY, iTickSize) {
8529        this.yTicks = [];
8530        this.yTickSize = iTickSize;
8531
8532        var tickMap = {};
8533
8534        for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
8535            if (!tickMap[i]) {
8536                this.yTicks[this.yTicks.length] = i;
8537                tickMap[i] = true;
8538            }
8539        }
8540
8541        for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
8542            if (!tickMap[i]) {
8543                this.yTicks[this.yTicks.length] = i;
8544                tickMap[i] = true;
8545            }
8546        }
8547
8548        this.yTicks.sort(this.DDM.numericSort) ;
8549    },
8550
8551    
8552    setXConstraint: function(iLeft, iRight, iTickSize) {
8553        this.leftConstraint = iLeft;
8554        this.rightConstraint = iRight;
8555
8556        this.minX = this.initPageX - iLeft;
8557        this.maxX = this.initPageX + iRight;
8558        if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
8559
8560        this.constrainX = true;
8561    },
8562
8563    
8564    clearConstraints: function() {
8565        this.constrainX = false;
8566        this.constrainY = false;
8567        this.clearTicks();
8568    },
8569
8570    
8571    clearTicks: function() {
8572        this.xTicks = null;
8573        this.yTicks = null;
8574        this.xTickSize = 0;
8575        this.yTickSize = 0;
8576    },
8577
8578    
8579    setYConstraint: function(iUp, iDown, iTickSize) {
8580        this.topConstraint = iUp;
8581        this.bottomConstraint = iDown;
8582
8583        this.minY = this.initPageY - iUp;
8584        this.maxY = this.initPageY + iDown;
8585        if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
8586
8587        this.constrainY = true;
8588
8589    },
8590
8591    
8592    resetConstraints: function() {
8593
8594
8595        // Maintain offsets if necessary
8596        if (this.initPageX || this.initPageX === 0) {
8597            // figure out how much this thing has moved
8598            var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
8599            var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
8600
8601            this.setInitPosition(dx, dy);
8602
8603        // This is the first time we have detected the element's position
8604        } else {
8605            this.setInitPosition();
8606        }
8607
8608        if (this.constrainX) {
8609            this.setXConstraint( this.leftConstraint,
8610                                 this.rightConstraint,
8611                                 this.xTickSize        );
8612        }
8613
8614        if (this.constrainY) {
8615            this.setYConstraint( this.topConstraint,
8616                                 this.bottomConstraint,
8617                                 this.yTickSize         );
8618        }
8619    },
8620
8621    
8622    getTick: function(val, tickArray) {
8623
8624        if (!tickArray) {
8625            // If tick interval is not defined, it is effectively 1 pixel,
8626            // so we return the value passed to us.
8627            return val;
8628        } else if (tickArray[0] >= val) {
8629            // The value is lower than the first tick, so we return the first
8630            // tick.
8631            return tickArray[0];
8632        } else {
8633            for (var i=0, len=tickArray.length; i<len; ++i) {
8634                var next = i + 1;
8635                if (tickArray[next] && tickArray[next] >= val) {
8636                    var diff1 = val - tickArray[i];
8637                    var diff2 = tickArray[next] - val;
8638                    return (diff2 > diff1) ? tickArray[i] : tickArray[next];
8639                }
8640            }
8641
8642            // The value is larger than the last tick, so we return the last
8643            // tick.
8644            return tickArray[tickArray.length - 1];
8645        }
8646    },
8647
8648    
8649    toString: function() {
8650        return ("DragDrop " + this.id);
8651    }
8652
8653};
8654
8655})();
8656
8657
8658// Only load the library once.  Rewriting the manager class would orphan
8659// existing drag and drop instances.
8660if (!Ext.dd.DragDropMgr) {
8661
8662
8663Ext.dd.DragDropMgr = function() {
8664
8665    var Event = Ext.EventManager;
8666
8667    return {
8668
8669        
8670        ids: {},
8671
8672        
8673        handleIds: {},
8674
8675        
8676        dragCurrent: null,
8677
8678        
8679        dragOvers: {},
8680
8681        
8682        deltaX: 0,
8683
8684        
8685        deltaY: 0,
8686
8687        
8688        preventDefault: true,
8689
8690        
8691        stopPropagation: true,
8692
8693        
8694        initialized: false,
8695
8696        
8697        locked: false,
8698
8699        
8700        init: function() {
8701            this.initialized = true;
8702        },
8703
8704        
8705        POINT: 0,
8706
8707        
8708        INTERSECT: 1,
8709
8710        
8711        mode: 0,
8712
8713        
8714        _execOnAll: function(sMethod, args) {
8715            for (var i in this.ids) {
8716                for (var j in this.ids[i]) {
8717                    var oDD = this.ids[i][j];
8718                    if (! this.isTypeOfDD(oDD)) {
8719                        continue;
8720                    }
8721                    oDD[sMethod].apply(oDD, args);
8722                }
8723            }
8724        },
8725
8726        
8727        _onLoad: function() {
8728
8729            this.init();
8730
8731
8732            Event.on(document, "mouseup",   this.handleMouseUp, this, true);
8733            Event.on(document, "mousemove", this.handleMouseMove, this, true);
8734            Event.on(window,   "unload",    this._onUnload, this, true);
8735            Event.on(window,   "resize",    this._onResize, this, true);
8736            // Event.on(window,   "mouseout",    this._test);
8737
8738        },
8739
8740        
8741        _onResize: function(e) {
8742            this._execOnAll("resetConstraints", []);
8743        },
8744
8745        
8746        lock: function() { this.locked = true; },
8747
8748        
8749        unlock: function() { this.locked = false; },
8750
8751        
8752        isLocked: function() { return this.locked; },
8753
8754        
8755        locationCache: {},
8756
8757        
8758        useCache: true,
8759
8760        
8761        clickPixelThresh: 3,
8762
8763        
8764        clickTimeThresh: 350,
8765
8766        
8767        dragThreshMet: false,
8768
8769        
8770        clickTimeout: null,
8771
8772        
8773        startX: 0,
8774
8775        
8776        startY: 0,
8777
8778        
8779        regDragDrop: function(oDD, sGroup) {
8780            if (!this.initialized) { this.init(); }
8781
8782            if (!this.ids[sGroup]) {
8783                this.ids[sGroup] = {};
8784            }
8785            this.ids[sGroup][oDD.id] = oDD;
8786        },
8787
8788        
8789        removeDDFromGroup: function(oDD, sGroup) {
8790            if (!this.ids[sGroup]) {
8791                this.ids[sGroup] = {};
8792            }
8793
8794            var obj = this.ids[sGroup];
8795            if (obj && obj[oDD.id]) {
8796                delete obj[oDD.id];
8797            }
8798        },
8799
8800        
8801        _remove: function(oDD) {
8802            for (var g in oDD.groups) {
8803                if (g && this.ids[g] && this.ids[g][oDD.id]) {
8804                    delete this.ids[g][oDD.id];
8805                }
8806            }
8807            delete this.handleIds[oDD.id];
8808        },
8809
8810        
8811        regHandle: function(sDDId, sHandleId) {
8812            if (!this.handleIds[sDDId]) {
8813                this.handleIds[sDDId] = {};
8814            }
8815            this.handleIds[sDDId][sHandleId] = sHandleId;
8816        },
8817
8818        
8819        isDragDrop: function(id) {
8820            return ( this.getDDById(id) ) ? true : false;
8821        },
8822
8823        
8824        getRelated: function(p_oDD, bTargetsOnly) {
8825            var oDDs = [];
8826            for (var i in p_oDD.groups) {
8827                for (j in this.ids[i]) {
8828                    var dd = this.ids[i][j];
8829                    if (! this.isTypeOfDD(dd)) {
8830                        continue;
8831                    }
8832                    if (!bTargetsOnly || dd.isTarget) {
8833                        oDDs[oDDs.length] = dd;
8834                    }
8835                }
8836            }
8837
8838            return oDDs;
8839        },
8840
8841        
8842        isLegalTarget: function (oDD, oTargetDD) {
8843            var targets = this.getRelated(oDD, true);
8844            for (var i=0, len=targets.length;i<len;++i) {
8845                if (targets[i].id == oTargetDD.id) {
8846                    return true;
8847                }
8848            }
8849
8850            return false;
8851        },
8852
8853        
8854        isTypeOfDD: function (oDD) {
8855            return (oDD && oDD.__ygDragDrop);
8856        },
8857
8858        
8859        isHandle: function(sDDId, sHandleId) {
8860            return ( this.handleIds[sDDId] &&
8861                            this.handleIds[sDDId][sHandleId] );
8862        },
8863
8864        
8865        getDDById: function(id) {
8866            for (var i in this.ids) {
8867                if (this.ids[i][id]) {
8868                    return this.ids[i][id];
8869                }
8870            }
8871            return null;
8872        },
8873
8874        
8875        handleMouseDown: function(e, oDD) {
8876            if(Ext.QuickTips){
8877                Ext.QuickTips.disable();
8878            }
8879            if(this.dragCurrent){
8880                // the original browser mouseup wasn't handled (e.g. outside FF browser window)
8881                // so clean up first to avoid breaking the next drag
8882                this.handleMouseUp(e);
8883            }
8884            
8885            this.currentTarget = e.getTarget();
8886            this.dragCurrent = oDD;
8887
8888            var el = oDD.getEl();
8889
8890            // track start position
8891            this.startX = e.getPageX();
8892            this.startY = e.getPageY();
8893
8894            this.deltaX = this.startX - el.offsetLeft;
8895            this.deltaY = this.startY - el.offsetTop;
8896
8897            this.dragThreshMet = false;
8898
8899            this.clickTimeout = setTimeout(
8900                    function() {
8901                        var DDM = Ext.dd.DDM;
8902                        DDM.startDrag(DDM.startX, DDM.startY);
8903                    },
8904                    this.clickTimeThresh );
8905        },
8906
8907        
8908        startDrag: function(x, y) {
8909            clearTimeout(this.clickTimeout);
8910            if (this.dragCurrent) {
8911                this.dragCurrent.b4StartDrag(x, y);
8912                this.dragCurrent.startDrag(x, y);
8913            }
8914            this.dragThreshMet = true;
8915        },
8916
8917        
8918        handleMouseUp: function(e) {
8919
8920            if(Ext.QuickTips){
8921                Ext.QuickTips.enable();
8922            }
8923            if (! this.dragCurrent) {
8924                return;
8925            }
8926
8927            clearTimeout(this.clickTimeout);
8928
8929            if (this.dragThreshMet) {
8930                this.fireEvents(e, true);
8931            } else {
8932            }
8933
8934            this.stopDrag(e);
8935
8936            this.stopEvent(e);
8937        },
8938
8939        
8940        stopEvent: function(e){
8941            if(this.stopPropagation) {
8942                e.stopPropagation();
8943            }
8944
8945            if (this.preventDefault) {
8946                e.preventDefault();
8947            }
8948        },
8949
8950        
8951        stopDrag: function(e) {
8952            // Fire the drag end event for the item that was dragged
8953            if (this.dragCurrent) {
8954                if (this.dragThreshMet) {
8955                    this.dragCurrent.b4EndDrag(e);
8956                    this.dragCurrent.endDrag(e);
8957                }
8958
8959                this.dragCurrent.onMouseUp(e);
8960            }
8961
8962            this.dragCurrent = null;
8963            this.dragOvers = {};
8964        },
8965
8966        
8967        handleMouseMove: function(e) {
8968            if (! this.dragCurrent) {
8969                return true;
8970            }
8971
8972            // var button = e.which || e.button;
8973
8974            // check for IE mouseup outside of page boundary
8975            if (Ext.isIE && (e.button !== 0 && e.button !== 1 && e.button !== 2)) {
8976                this.stopEvent(e);
8977                return this.handleMouseUp(e);
8978            }
8979
8980            if (!this.dragThreshMet) {
8981                var diffX = Math.abs(this.startX - e.getPageX());
8982                var diffY = Math.abs(this.startY - e.getPageY());
8983                if (diffX > this.clickPixelThresh ||
8984                            diffY > this.clickPixelThresh) {
8985                    this.startDrag(this.startX, this.startY);
8986                }
8987            }
8988
8989            if (this.dragThreshMet) {
8990                this.dragCurrent.b4Drag(e);
8991                this.dragCurrent.onDrag(e);
8992                if(!this.dragCurrent.moveOnly){
8993                    this.fireEvents(e, false);
8994                }
8995            }
8996
8997            this.stopEvent(e);
8998
8999            return true;
9000        },
9001
9002        
9003        fireEvents: function(e, isDrop) {
9004            var dc = this.dragCurrent;
9005
9006            // If the user did the mouse up outside of the window, we could
9007            // get here even though we have ended the drag.
9008            if (!dc || dc.isLocked()) {
9009                return;
9010            }
9011
9012            var pt = e.getPoint();
9013
9014            // cache the previous dragOver array
9015            var oldOvers = [];
9016
9017            var outEvts   = [];
9018            var overEvts  = [];
9019            var dropEvts  = [];
9020            var enterEvts = [];
9021
9022            // Check to see if the object(s) we were hovering over is no longer
9023            // being hovered over so we can fire the onDragOut event
9024            for (var i in this.dragOvers) {
9025
9026                var ddo = this.dragOvers[i];
9027
9028                if (! this.isTypeOfDD(ddo)) {
9029                    continue;
9030                }
9031
9032                if (! this.isOverTarget(pt, ddo, this.mode)) {
9033                    outEvts.push( ddo );
9034                }
9035
9036                oldOvers[i] = true;
9037                delete this.dragOvers[i];
9038            }
9039
9040            for (var sGroup in dc.groups) {
9041
9042                if ("string" != typeof sGroup) {
9043                    continue;
9044                }
9045
9046                for (i in this.ids[sGroup]) {
9047                    var oDD = this.ids[sGroup][i];
9048                    if (! this.isTypeOfDD(oDD)) {
9049                        continue;
9050                    }
9051
9052                    if (oDD.isTarget && !oDD.isLocked() && oDD != dc) {
9053                        if (this.isOverTarget(pt, oDD, this.mode)) {
9054                            // look for drop interactions
9055                            if (isDrop) {
9056                                dropEvts.push( oDD );
9057                            // look for drag enter and drag over interactions
9058                            } else {
9059
9060                                // initial drag over: dragEnter fires
9061                                if (!oldOvers[oDD.id]) {
9062                                    enterEvts.push( oDD );
9063                                // subsequent drag overs: dragOver fires
9064                                } else {
9065                                    overEvts.push( oDD );
9066                                }
9067
9068                                this.dragOvers[oDD.id] = oDD;
9069                            }
9070                        }
9071                    }
9072                }
9073            }
9074
9075            if (this.mode) {
9076                if (outEvts.length) {
9077                    dc.b4DragOut(e, outEvts);
9078                    dc.onDragOut(e, outEvts);
9079                }
9080
9081                if (enterEvts.length) {
9082                    dc.onDragEnter(e, enterEvts);
9083                }
9084
9085                if (overEvts.length) {
9086                    dc.b4DragOver(e, overEvts);
9087                    dc.onDragOver(e, overEvts);
9088                }
9089
9090                if (dropEvts.length) {
9091                    dc.b4DragDrop(e, dropEvts);
9092                    dc.onDragDrop(e, dropEvts);
9093                }
9094
9095            } else {
9096                // fire dragout events
9097                var len = 0;
9098                for (i=0, len=outEvts.length; i<len; ++i) {
9099                    dc.b4DragOut(e, outEvts[i].id);
9100                    dc.onDragOut(e, outEvts[i].id);
9101                }
9102
9103                // fire enter events
9104                for (i=0,len=enterEvts.length; i<len; ++i) {
9105                    // dc.b4DragEnter(e, oDD.id);
9106                    dc.onDragEnter(e, enterEvts[i].id);
9107                }
9108
9109                // fire over events
9110                for (i=0,len=overEvts.length; i<len; ++i) {
9111                    dc.b4DragOver(e, overEvts[i].id);
9112                    dc.onDragOver(e, overEvts[i].id);
9113                }
9114
9115                // fire drop events
9116                for (i=0, len=dropEvts.length; i<len; ++i) {
9117                    dc.b4DragDrop(e, dropEvts[i].id);
9118                    dc.onDragDrop(e, dropEvts[i].id);
9119                }
9120
9121            }
9122
9123            // notify about a drop that did not find a target
9124            if (isDrop && !dropEvts.length) {
9125                dc.onInvalidDrop(e);
9126            }
9127
9128        },
9129
9130        
9131        getBestMatch: function(dds) {
9132            var winner = null;
9133            // Return null if the input is not what we expect
9134            //if (!dds || !dds.length || dds.length == 0) {
9135               // winner = null;
9136            // If there is only one item, it wins
9137            //} else if (dds.length == 1) {
9138
9139            var len = dds.length;
9140
9141            if (len == 1) {
9142                winner = dds[0];
9143            } else {
9144                // Loop through the targeted items
9145                for (var i=0; i<len; ++i) {
9146                    var dd = dds[i];
9147                    // If the cursor is over the object, it wins.  If the
9148                    // cursor is over multiple matches, the first one we come
9149                    // to wins.
9150                    if (dd.cursorIsOver) {
9151                        winner = dd;
9152                        break;
9153                    // Otherwise the object with the most overlap wins
9154                    } else {
9155                        if (!winner ||
9156                            winner.overlap.getArea() < dd.overlap.getArea()) {
9157                            winner = dd;
9158                        }
9159                    }
9160                }
9161            }
9162
9163            return winner;
9164        },
9165
9166        
9167        refreshCache: function(groups) {
9168            for (var sGroup in groups) {
9169                if ("string" != typeof sGroup) {
9170                    continue;
9171                }
9172                for (var i in this.ids[sGroup]) {
9173                    var oDD = this.ids[sGroup][i];
9174
9175                    if (this.isTypeOfDD(oDD)) {
9176                    // if (this.isTypeOfDD(oDD) && oDD.isTarget) {
9177                        var loc = this.getLocation(oDD);
9178                        if (loc) {
9179                            this.locationCache[oDD.id] = loc;
9180                        } else {
9181                            delete this.locationCache[oDD.id];
9182                            // this will unregister the drag and drop object if
9183                            // the element is not in a usable state
9184                            // oDD.unreg();
9185                        }
9186                    }
9187                }
9188            }
9189        },
9190
9191        
9192        verifyEl: function(el) {
9193            if (el) {
9194                var parent;
9195                if(Ext.isIE){
9196                    try{
9197                        parent = el.offsetParent;
9198                    }catch(e){}
9199                }else{
9200                    parent = el.offsetParent;
9201                }
9202                if (parent) {
9203                    return true;
9204                }
9205            }
9206
9207            return false;
9208        },
9209
9210        
9211        getLocation: function(oDD) {
9212            if (! this.isTypeOfDD(oDD)) {
9213                return null;
9214            }
9215
9216            var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
9217
9218            try {
9219                pos= Ext.lib.Dom.getXY(el);
9220            } catch (e) { }
9221
9222            if (!pos) {
9223                return null;
9224            }
9225
9226            x1 = pos[0];
9227            x2 = x1 + el.offsetWidth;
9228            y1 = pos[1];
9229            y2 = y1 + el.offsetHeight;
9230
9231            t = y1 - oDD.padding[0];
9232            r = x2 + oDD.padding[1];
9233            b = y2 + oDD.padding[2];
9234            l = x1 - oDD.padding[3];
9235
9236            return new Ext.lib.Region( t, r, b, l );
9237        },
9238
9239        
9240        isOverTarget: function(pt, oTarget, intersect) {
9241            // use cache if available
9242            var loc = this.locationCache[oTarget.id];
9243            if (!loc || !this.useCache) {
9244                loc = this.getLocation(oTarget);
9245                this.locationCache[oTarget.id] = loc;
9246
9247            }
9248
9249            if (!loc) {
9250                return false;
9251            }
9252
9253            oTarget.cursorIsOver = loc.contains( pt );
9254
9255            // DragDrop is using this as a sanity check for the initial mousedown
9256            // in this case we are done.  In POINT mode, if the drag obj has no
9257            // contraints, we are also done. Otherwise we need to evaluate the
9258            // location of the target as related to the actual location of the
9259            // dragged element.
9260            var dc = this.dragCurrent;
9261            if (!dc || !dc.getTargetCoord ||
9262                    (!intersect && !dc.constrainX && !dc.constrainY)) {
9263                return oTarget.cursorIsOver;
9264            }
9265
9266            oTarget.overlap = null;
9267
9268            // Get the current location of the drag element, this is the
9269            // location of the mouse event less the delta that represents
9270            // where the original mousedown happened on the element.  We
9271            // need to consider constraints and ticks as well.
9272            var pos = dc.getTargetCoord(pt.x, pt.y);
9273
9274            var el = dc.getDragEl();
9275            var curRegion = new Ext.lib.Region( pos.y,
9276                                                   pos.x + el.offsetWidth,
9277                                                   pos.y + el.offsetHeight,
9278                                                   pos.x );
9279
9280            var overlap = curRegion.intersect(loc);
9281
9282            if (overlap) {
9283                oTarget.overlap = overlap;
9284                return (intersect) ? true : oTarget.cursorIsOver;
9285            } else {
9286                return false;
9287            }
9288        },
9289
9290        
9291        _onUnload: function(e, me) {
9292            Ext.dd.DragDropMgr.unregAll();
9293        },
9294
9295        
9296        unregAll: function() {
9297
9298            if (this.dragCurrent) {
9299                this.stopDrag();
9300                this.dragCurrent = null;
9301            }
9302
9303            this._execOnAll("unreg", []);
9304
9305            for (var i in this.elementCache) {
9306                delete this.elementCache[i];
9307            }
9308
9309            this.elementCache = {};
9310            this.ids = {};
9311        },
9312
9313        
9314        elementCache: {},
9315
9316        
9317        getElWrapper: function(id) {
9318            var oWrapper = this.elementCache[id];
9319            if (!oWrapper || !oWrapper.el) {
9320                oWrapper = this.elementCache[id] =
9321                    new this.ElementWrapper(Ext.getDom(id));
9322            }
9323            return oWrapper;
9324        },
9325
9326        
9327        getElement: function(id) {
9328            return Ext.getDom(id);
9329        },
9330
9331        
9332        getCss: function(id) {
9333            var el = Ext.getDom(id);
9334            return (el) ? el.style : null;
9335        },
9336
9337        
9338        ElementWrapper: function(el) {
9339                
9340                this.el = el || null;
9341                
9342                this.id = this.el && el.id;
9343                
9344                this.css = this.el && el.style;
9345            },
9346
9347        
9348        getPosX: function(el) {
9349            return Ext.lib.Dom.getX(el);
9350        },
9351
9352        
9353        getPosY: function(el) {
9354            return Ext.lib.Dom.getY(el);
9355        },
9356
9357        
9358        swapNode: function(n1, n2) {
9359            if (n1.swapNode) {
9360                n1.swapNode(n2);
9361            } else {
9362                var p = n2.parentNode;
9363                var s = n2.nextSibling;
9364
9365                if (s == n1) {
9366                    p.insertBefore(n1, n2);
9367                } else if (n2 == n1.nextSibling) {
9368                    p.insertBefore(n2, n1);
9369                } else {
9370                    n1.parentNode.replaceChild(n2, n1);
9371                    p.insertBefore(n1, s);
9372                }
9373            }
9374        },
9375
9376        
9377        getScroll: function () {
9378            var t, l, dde=document.documentElement, db=document.body;
9379            if (dde && (dde.scrollTop || dde.scrollLeft)) {
9380                t = dde.scrollTop;
9381                l = dde.scrollLeft;
9382            } else if (db) {
9383                t = db.scrollTop;
9384                l = db.scrollLeft;
9385            } else {
9386
9387            }
9388            return { top: t, left: l };
9389        },
9390
9391        
9392        getStyle: function(el, styleProp) {
9393            return Ext.fly(el).getStyle(styleProp);
9394        },
9395
9396        
9397        getScrollTop: function () { return this.getScroll().top; },
9398
9399        
9400        getScrollLeft: function () { return this.getScroll().left; },
9401
9402        
9403        moveToEl: function (moveEl, targetEl) {
9404            var aCoord = Ext.lib.Dom.getXY(targetEl);
9405            Ext.lib.Dom.setXY(moveEl, aCoord);
9406        },
9407
9408        
9409        numericSort: function(a, b) { return (a - b); },
9410
9411        
9412        _timeoutCount: 0,
9413
9414        
9415        _addListeners: function() {
9416            var DDM = Ext.dd.DDM;
9417            if ( Ext.lib.Event && document ) {
9418                DDM._onLoad();
9419            } else {
9420                if (DDM._timeoutCount > 2000) {
9421                } else {
9422                    setTimeout(DDM._addListeners, 10);
9423                    if (document && document.body) {
9424                        DDM._timeoutCount += 1;
9425                    }
9426                }
9427            }
9428        },
9429
9430        
9431        handleWasClicked: function(node, id) {
9432            if (this.isHandle(id, node.id)) {
9433                return true;
9434            } else {
9435                // check to see if this is a text node child of the one we want
9436                var p = node.parentNode;
9437
9438                while (p) {
9439                    if (this.isHandle(id, p.id)) {
9440                        return true;
9441                    } else {
9442                        p = p.parentNode;
9443                    }
9444                }
9445            }
9446
9447            return false;
9448        }
9449
9450    };
9451
9452}();
9453
9454// shorter alias, save a few bytes
9455Ext.dd.DDM = Ext.dd.DragDropMgr;
9456Ext.dd.DDM._addListeners();
9457
9458}
9459
9460
9461Ext.dd.DD = function(id, sGroup, config) {
9462    if (id) {
9463        this.init(id, sGroup, config);
9464    }
9465};
9466
9467Ext.extend(Ext.dd.DD, Ext.dd.DragDrop, {
9468
9469    
9470    scroll: true,
9471
9472    
9473    autoOffset: function(iPageX, iPageY) {
9474        var x = iPageX - this.startPageX;
9475        var y = iPageY - this.startPageY;
9476        this.setDelta(x, y);
9477    },
9478
9479    
9480    setDelta: function(iDeltaX, iDeltaY) {
9481        this.deltaX = iDeltaX;
9482        this.deltaY = iDeltaY;
9483    },
9484
9485    
9486    setDragElPos: function(iPageX, iPageY) {
9487        // the first time we do this, we are going to check to make sure
9488        // the element has css positioning
9489
9490        var el = this.getDragEl();
9491        this.alignElWithMouse(el, iPageX, iPageY);
9492    },
9493
9494    
9495    alignElWithMouse: function(el, iPageX, iPageY) {
9496        var oCoord = this.getTargetCoord(iPageX, iPageY);
9497        var fly = el.dom ? el : Ext.fly(el, '_dd');
9498        if (!this.deltaSetXY) {
9499            var aCoord = [oCoord.x, oCoord.y];
9500            fly.setXY(aCoord);
9501            var newLeft = fly.getLeft(true);
9502            var newTop  = fly.getTop(true);
9503            this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ];
9504        } else {
9505            fly.setLeftTop(oCoord.x + this.deltaSetXY[0], oCoord.y + this.deltaSetXY[1]);
9506        }
9507
9508        this.cachePosition(oCoord.x, oCoord.y);
9509        this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
9510        return oCoord;
9511    },
9512
9513    
9514    cachePosition: function(iPageX, iPageY) {
9515        if (iPageX) {
9516            this.lastPageX = iPageX;
9517            this.lastPageY = iPageY;
9518        } else {
9519            var aCoord = Ext.lib.Dom.getXY(this.getEl());
9520            this.lastPageX = aCoord[0];
9521            this.lastPageY = aCoord[1];
9522        }
9523    },
9524
9525    
9526    autoScroll: function(x, y, h, w) {
9527
9528        if (this.scroll) {
9529            // The client height
9530            var clientH = Ext.lib.Dom.getViewHeight();
9531
9532            // The client width
9533            var clientW = Ext.lib.Dom.getViewWidth();
9534
9535            // The amt scrolled down
9536            var st = this.DDM.getScrollTop();
9537
9538            // The amt scrolled right
9539            var sl = this.DDM.getScrollLeft();
9540
9541            // Location of the bottom of the element
9542            var bot = h + y;
9543
9544            // Location of the right of the element
9545            var right = w + x;
9546
9547            // The distance from the cursor to the bottom of the visible area,
9548            // adjusted so that we don't scroll if the cursor is beyond the
9549            // element drag constraints
9550            var toBot = (clientH + st - y - this.deltaY);
9551
9552            // The distance from the cursor to the right of the visible area
9553            var toRight = (clientW + sl - x - this.deltaX);
9554
9555
9556            // How close to the edge the cursor must be before we scroll
9557            // var thresh = (document.all) ? 100 : 40;
9558            var thresh = 40;
9559
9560            // How many pixels to scroll per autoscroll op.  This helps to reduce
9561            // clunky scrolling. IE is more sensitive about this ... it needs this
9562            // value to be higher.
9563            var scrAmt = (document.all) ? 80 : 30;
9564
9565            // Scroll down if we are near the bottom of the visible page and the
9566            // obj extends below the crease
9567            if ( bot > clientH && toBot < thresh ) {
9568                window.scrollTo(sl, st + scrAmt);
9569            }
9570
9571            // Scroll up if the window is scrolled down and the top of the object
9572            // goes above the top border
9573            if ( y < st && st > 0 && y - st < thresh ) {
9574                window.scrollTo(sl, st - scrAmt);
9575            }
9576
9577            // Scroll right if the obj is beyond the right border and the cursor is
9578            // near the border.
9579            if ( right > clientW && toRight < thresh ) {
9580                window.scrollTo(sl + scrAmt, st);
9581            }
9582
9583            // Scroll left if the window has been scrolled to the right and the obj
9584            // extends past the left border
9585            if ( x < sl && sl > 0 && x - sl < thresh ) {
9586                window.scrollTo(sl - scrAmt, st);
9587            }
9588        }
9589    },
9590
9591    
9592    getTargetCoord: function(iPageX, iPageY) {
9593
9594
9595        var x = iPageX - this.deltaX;
9596        var y = iPageY - this.deltaY;
9597
9598        if (this.constrainX) {
9599            if (x < this.minX) { x = this.minX; }
9600            if (x > this.maxX) { x = this.maxX; }
9601        }
9602
9603        if (this.constrainY) {
9604            if (y < this.minY) { y = this.minY; }
9605            if (y > this.maxY) { y = this.maxY; }
9606        }
9607
9608        x = this.getTick(x, this.xTicks);
9609        y = this.getTick(y, this.yTicks);
9610
9611
9612        return {x:x, y:y};
9613    },
9614
9615    
9616    applyConfig: function() {
9617        Ext.dd.DD.superclass.applyConfig.call(this);
9618        this.scroll = (this.config.scroll !== false);
9619    },
9620
9621    
9622    b4MouseDown: function(e) {
9623        // this.resetConstraints();
9624        this.autoOffset(e.getPageX(),
9625                            e.getPageY());
9626    },
9627
9628    
9629    b4Drag: function(e) {
9630        this.setDragElPos(e.getPageX(),
9631                            e.getPageY());
9632    },
9633
9634    toString: function() {
9635        return ("DD " + this.id);
9636    }
9637
9638    //////////////////////////////////////////////////////////////////////////
9639    // Debugging ygDragDrop events that can be overridden
9640    //////////////////////////////////////////////////////////////////////////
9641    
9642
9643});
9644
9645Ext.dd.DDProxy = function(id, sGroup, config) {
9646    if (id) {
9647        this.init(id, sGroup, config);
9648        this.initFrame();
9649    }
9650};
9651
9652
9653Ext.dd.DDProxy.dragElId = "ygddfdiv";
9654
9655Ext.extend(Ext.dd.DDProxy, Ext.dd.DD, {
9656
9657    
9658    resizeFrame: true,
9659
9660    
9661    centerFrame: false,
9662
9663    
9664    createFrame: function() {
9665        var self = this;
9666        var body = document.body;
9667
9668        if (!body || !body.firstChild) {
9669            setTimeout( function() { self.createFrame(); }, 50 );
9670            return;
9671        }
9672
9673        var div = this.getDragEl();
9674
9675        if (!div) {
9676            div    = document.createElement("div");
9677            div.id = this.dragElId;
9678            var s  = div.style;
9679
9680            s.position   = "absolute";
9681            s.visibility = "hidden";
9682            s.cursor     = "move";
9683            s.border     = "2px solid #aaa";
9684            s.zIndex     = 999;
9685
9686            // appendChild can blow up IE if invoked prior to the window load event
9687            // while rendering a table.  It is possible there are other scenarios
9688            // that would cause this to happen as well.
9689            body.insertBefore(div, body.firstChild);
9690        }
9691    },
9692
9693    
9694    initFrame: function() {
9695        this.createFrame();
9696    },
9697
9698    applyConfig: function() {
9699        Ext.dd.DDProxy.superclass.applyConfig.call(this);
9700
9701        this.resizeFrame = (this.config.resizeFrame !== false);
9702        this.centerFrame = (this.config.centerFrame);
9703        this.setDragElId(this.config.dragElId || Ext.dd.DDProxy.dragElId);
9704    },
9705
9706    
9707    showFrame: function(iPageX, iPageY) {
9708        var el = this.getEl();
9709        var dragEl = this.getDragEl();
9710        var s = dragEl.style;
9711
9712        this._resizeProxy();
9713
9714        if (this.centerFrame) {
9715            this.setDelta( Math.round(parseInt(s.width,  10)/2),
9716                           Math.round(parseInt(s.height, 10)/2) );
9717        }
9718
9719        this.setDragElPos(iPageX, iPageY);
9720
9721        Ext.fly(dragEl).show();
9722    },
9723
9724    
9725    _resizeProxy: function() {
9726        if (this.resizeFrame) {
9727            var el = this.getEl();
9728            Ext.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);
9729        }
9730    },
9731
9732    // overrides Ext.dd.DragDrop
9733    b4MouseDown: function(e) {
9734        var x = e.getPageX();
9735        var y = e.getPageY();
9736        this.autoOffset(x, y);
9737        this.setDragElPos(x, y);
9738    },
9739
9740    // overrides Ext.dd.DragDrop
9741    b4StartDrag: function(x, y) {
9742        // show the drag frame
9743        this.showFrame(x, y);
9744    },
9745
9746    // overrides Ext.dd.DragDrop
9747    b4EndDrag: function(e) {
9748        Ext.fly(this.getDragEl()).hide();
9749    },
9750
9751    // overrides Ext.dd.DragDrop
9752    // By default we try to move the element to the last location of the frame.
9753    // This is so that the default behavior mirrors that of Ext.dd.DD.
9754    endDrag: function(e) {
9755
9756        var lel = this.getEl();
9757        var del = this.getDragEl();
9758
9759        // Show the drag frame briefly so we can get its position
9760        del.style.visibility = "";
9761
9762        this.beforeMove();
9763        // Hide the linked element before the move to get around a Safari
9764        // rendering bug.
9765        lel.style.visibility = "hidden";
9766        Ext.dd.DDM.moveToEl(lel, del);
9767        del.style.visibility = "hidden";
9768        lel.style.visibility = "";
9769
9770        this.afterDrag();
9771    },
9772
9773    beforeMove : function(){
9774
9775    },
9776
9777    afterDrag : function(){
9778
9779    },
9780
9781    toString: function() {
9782        return ("DDProxy " + this.id);
9783    }
9784
9785});
9786
9787Ext.dd.DDTarget = function(id, sGroup, config) {
9788    if (id) {
9789        this.initTarget(id, sGroup, config);
9790    }
9791};
9792
9793// Ext.dd.DDTarget.prototype = new Ext.dd.DragDrop();
9794Ext.extend(Ext.dd.DDTarget, Ext.dd.DragDrop, {
9795    toString: function() {
9796        return ("DDTarget " + this.id);
9797    }
9798});
9799
9800Ext.dd.DragTracker = function(config){
9801    Ext.apply(this, config);
9802    this.addEvents(
9803        'mousedown',
9804        'mouseup',
9805        'mousemove',
9806        'dragstart',
9807        'dragend',
9808        'drag'
9809    );
9810
9811    this.dragRegion = new Ext.lib.Region(0,0,0,0);
9812
9813    if(this.el){
9814        this.initEl(this.el);
9815    }
9816}
9817
9818Ext.extend(Ext.dd.DragTracker, Ext.util.Observable,  {
9819    active: false,
9820    tolerance: 5,
9821    autoStart: false,
9822
9823    initEl: function(el){
9824        this.el = Ext.get(el);
9825        el.on('mousedown', this.onMouseDown, this,
9826                this.delegate ? {delegate: this.delegate} : undefined);
9827    },
9828
9829    destroy : function(){
9830        this.el.un('mousedown', this.onMouseDown, this);
9831    },
9832
9833    onMouseDown: function(e, target){
9834        if(this.fireEvent('mousedown', this, e) !== false && this.onBeforeStart(e) !== false){
9835            this.startXY = this.lastXY = e.getXY();
9836            this.dragTarget = this.delegate ? target : this.el.dom;
9837            e.preventDefault();
9838            var doc = Ext.getDoc();
9839            doc.on('mouseup', this.onMouseUp, this);
9840            doc.on('mousemove', this.onMouseMove, this);
9841            doc.on('selectstart', this.stopSelect, this);
9842            if(this.autoStart){
9843                this.timer = this.triggerStart.defer(this.autoStart === true ? 1000 : this.autoStart, this);
9844            }
9845        }
9846    },
9847
9848    onMouseMove: function(e, target){
9849        e.preventDefault();
9850        var xy = e.getXY(), s = this.startXY;
9851        this.lastXY = xy;
9852        if(!this.active){
9853            if(Math.abs(s[0]-xy[0]) > this.tolerance || Math.abs(s[1]-xy[1]) > this.tolerance){
9854                this.triggerStart();
9855            }else{
9856                return;
9857            }
9858        }
9859        this.fireEvent('mousemove', this, e);
9860        this.onDrag(e);
9861        this.fireEvent('drag', this, e);
9862    },
9863
9864    onMouseUp: function(e){
9865        var doc = Ext.getDoc();
9866        doc.un('mousemove', this.onMouseMove, this);
9867        doc.un('mouseup', this.onMouseUp, this);
9868        doc.un('selectstart', this.stopSelect, this);
9869        e.preventDefault();
9870        this.clearStart();
9871        this.active = false;
9872        delete this.elRegion;
9873        this.fireEvent('mouseup', this, e);
9874        this.onEnd(e);
9875        this.fireEvent('dragend', this, e);
9876    },
9877
9878    triggerStart: function(isTimer){
9879        this.clearStart();
9880        this.active = true;
9881        this.onStart(this.startXY);
9882        this.fireEvent('dragstart', this, this.startXY);
9883    },
9884
9885    clearStart : function(){
9886        if(this.timer){
9887            clearTimeout(this.timer);
9888            delete this.timer;
9889        }
9890    },
9891
9892    stopSelect : function(e){
9893        e.stopEvent();
9894        return false;
9895    },
9896
9897    onBeforeStart : function(e){
9898
9899    },
9900
9901    onStart : function(xy){
9902
9903    },
9904
9905    onDrag : function(e){
9906
9907    },
9908
9909    onEnd : function(e){
9910
9911    },
9912
9913    getDragTarget : function(){
9914        return this.dragTarget;
9915    },
9916
9917    getDragCt : function(){
9918        return this.el;
9919    },
9920
9921    getXY : function(constrain){
9922        return constrain ?
9923               this.constrainModes[constrain].call(this, this.lastXY) : this.lastXY;
9924    },
9925
9926    getOffset : function(constrain){
9927        var xy = this.getXY(constrain);
9928        var s = this.startXY;
9929        return [s[0]-xy[0], s[1]-xy[1]];
9930    },
9931
9932    constrainModes: {
9933        'point' : function(xy){
9934
9935            if(!this.elRegion){
9936                this.elRegion = this.getDragCt().getRegion();
9937            }
9938
9939            var dr = this.dragRegion;
9940
9941            dr.left = xy[0];
9942            dr.top = xy[1];
9943            dr.right = xy[0];
9944            dr.bottom = xy[1];
9945
9946            dr.constrainTo(this.elRegion);
9947
9948            return [dr.left, dr.top];
9949        }
9950    }
9951});
9952
9953Ext.dd.ScrollManager = function(){
9954    var ddm = Ext.dd.DragDropMgr;
9955    var els = {};
9956    var dragEl = null;
9957    var proc = {};
9958    
9959    var onStop = function(e){
9960        dragEl = null;
9961        clearProc();
9962    };
9963    
9964    var triggerRefresh = function(){
9965        if(ddm.dragCurrent){
9966             ddm.refreshCache(ddm.dragCurrent.groups);
9967        }
9968    };
9969    
9970    var doScroll = function(){
9971        if(ddm.dragCurrent){
9972            var dds = Ext.dd.ScrollManager;
9973            var inc = proc.el.ddScrollConfig ?
9974                      proc.el.ddScrollConfig.increment : dds.increment;
9975            if(!dds.animate){
9976                if(proc.el.scroll(proc.dir, inc)){
9977                    triggerRefresh();
9978                }
9979            }else{
9980                proc.el.scroll(proc.dir, inc, true, dds.animDuration, triggerRefresh);
9981            }
9982        }
9983    };
9984    
9985    var clearProc = function(){
9986        if(proc.id){
9987            clearInterval(proc.id);
9988        }
9989        proc.id = 0;
9990        proc.el = null;
9991        proc.dir = "";
9992    };
9993    
9994    var startProc = function(el, dir){
9995        clearProc();
9996        proc.el = el;
9997        proc.dir = dir;
9998        var freq = (el.ddScrollConfig && el.ddScrollConfig.frequency) ? 
9999                el.ddScrollConfig.frequency : Ext.dd.ScrollManager.frequency;
10000        proc.id = setInterval(doScroll, freq);
10001    };
10002    
10003    var onFire = function(e, isDrop){
10004        if(isDrop || !ddm.dragCurrent){ return; }
10005        var dds = Ext.dd.ScrollManager;
10006        if(!dragEl || dragEl != ddm.dragCurrent){
10007            dragEl = ddm.dragCurrent;
10008            // refresh regions on drag start
10009            dds.refreshCache();
10010        }
10011        
10012        var xy = Ext.lib.Event.getXY(e);
10013        var pt = new Ext.lib.Point(xy[0], xy[1]);
10014        for(var id in els){
10015            var el = els[id], r = el._region;
10016            var c = el.ddScrollConfig ? el.ddScrollConfig : dds;
10017            if(r && r.contains(pt) && el.isScrollable()){
10018                if(r.bottom - pt.y <= c.vthresh){
10019                    if(proc.el != el){
10020                        startProc(el, "down");
10021                    }
10022                    return;
10023                }else if(r.right - pt.x <= c.hthresh){
10024                    if(proc.el != el){
10025                        startProc(el, "left");
10026                    }
10027                    return;
10028                }else if(pt.y - r.top <= c.vthresh){
10029                    if(proc.el != el){
10030                        startProc(el, "up");
10031                    }
10032                    return;
10033                }else if(pt.x - r.left <= c.hthresh){
10034                    if(proc.el != el){
10035                        startProc(el, "right");
10036                    }
10037                    return;
10038                }
10039            }
10040        }
10041        clearProc();
10042    };
10043    
10044    ddm.fireEvents = ddm.fireEvents.createSequence(onFire, ddm);
10045    ddm.stopDrag = ddm.stopDrag.createSequence(onStop, ddm);
10046    
10047    return {
10048        
10049        register : function(el){
10050            if(Ext.isArray(el)){
10051                for(var i = 0, len = el.length; i < len; i++) {
10052                	this.register(el[i]);
10053                }
10054            }else{
10055                el = Ext.get(el);
10056                els[el.id] = el;
10057            }
10058        },
10059        
10060        
10061        unregister : function(el){
10062            if(Ext.isArray(el)){
10063                for(var i = 0, len = el.length; i < len; i++) {
10064                	this.unregister(el[i]);
10065                }
10066            }else{
10067                el = Ext.get(el);
10068                delete els[el.id];
10069            }
10070        },
10071        
10072        
10073        vthresh : 25,
10074        
10075        hthresh : 25,
10076
10077        
10078        increment : 100,
10079        
10080        
10081        frequency : 500,
10082        
10083        
10084        animate: true,
10085        
10086        
10087        animDuration: .4,
10088        
10089        
10090        refreshCache : function(){
10091            for(var id in els){
10092                if(typeof els[id] == 'object'){ // for people extending the object prototype
10093                    els[id]._region = els[id].getRegion();
10094                }
10095            }
10096        }
10097    };
10098}();
10099
10100Ext.dd.Registry = function(){
10101    var elements = {}; 
10102    var handles = {}; 
10103    var autoIdSeed = 0;
10104
10105    var getId = function(el, autogen){
10106        if(typeof el == "string"){
10107            return el;
10108        }
10109        var id = el.id;
10110        if(!id && autogen !== false){
10111            id = "extdd-" + (++autoIdSeed);
10112            el.id = id;
10113        }
10114        return id;
10115    };
10116    
10117    return {
10118    
10119        register : function(el, data){
10120            data = data || {};
10121            if(typeof el == "string"){
10122                el = document.getElementById(el);
10123            }
10124            data.ddel = el;
10125            elements[getId(el)] = data;
10126            if(data.isHandle !== false){
10127                handles[data.ddel.id] = data;
10128            }
10129            if(data.handles){
10130                var hs = data.handles;
10131                for(var i = 0, len = hs.length; i < len; i++){
10132                	handles[getId(hs[i])] = data;
10133                }
10134            }
10135        },
10136
10137    
10138        unregister : function(el){
10139            var id = getId(el, false);
10140            var data = elements[id];
10141            if(data){
10142                delete elements[id];
10143                if(data.handles){
10144                    var hs = data.handles;
10145                    for(var i = 0, len = hs.length; i < len; i++){
10146                    	delete handles[getId(hs[i], false)];
10147                    }
10148                }
10149            }
10150        },
10151
10152    
10153        getHandle : function(id){
10154            if(typeof id != "string"){ // must be element?
10155                id = id.id;
10156            }
10157            return handles[id];
10158        },
10159
10160    
10161        getHandleFromEvent : function(e){
10162            var t = Ext.lib.Event.getTarget(e);
10163            return t ? handles[t.id] : null;
10164        },
10165
10166    
10167        getTarget : function(id){
10168            if(typeof id != "string"){ // must be element?
10169                id = id.id;
10170            }
10171            return elements[id];
10172        },
10173
10174    
10175        getTargetFromEvent : function(e){
10176            var t = Ext.lib.Event.getTarget(e);
10177            return t ? elements[t.id] || handles[t.id] : null;
10178        }
10179    };
10180}();
10181
10182Ext.dd.StatusProxy = function(config){
10183    Ext.apply(this, config);
10184    this.id = this.id || Ext.id();
10185    this.el = new Ext.Layer({
10186        dh: {
10187            id: this.id, tag: "div", cls: "x-dd-drag-proxy "+this.dropNotAllowed, children: [
10188                {tag: "div", cls: "x-dd-drop-icon"},
10189                {tag: "div", cls: "x-dd-drag-ghost"}
10190            ]
10191        }, 
10192        shadow: !config || config.shadow !== false
10193    });
10194    this.ghost = Ext.get(this.el.dom.childNodes[1]);
10195    this.dropStatus = this.dropNotAllowed;
10196};
10197
10198Ext.dd.StatusProxy.prototype = {
10199    
10200    dropAllowed : "x-dd-drop-ok",
10201    
10202    dropNotAllowed : "x-dd-drop-nodrop",
10203
10204    
10205    setStatus : function(cssClass){
10206        cssClass = cssClass || this.dropNotAllowed;
10207        if(this.dropStatus != cssClass){
10208            this.el.replaceClass(this.dropStatus, cssClass);
10209            this.dropStatus = cssClass;
10210        }
10211    },
10212
10213    
10214    reset : function(clearGhost){
10215        this.el.dom.className = "x-dd-drag-proxy " + this.dropNotAllowed;
10216        this.dropStatus = this.dropNotAllowed;
10217        if(clearGhost){
10218            this.ghost.update("");
10219        }
10220    },
10221
10222    
10223    update : function(html){
10224        if(typeof html == "string"){
10225            this.ghost.update(html);
10226        }else{
10227            this.ghost.update("");
10228            html.style.margin = "0";
10229            this.ghost.dom.appendChild(html);
10230        }
10231        var el = this.ghost.dom.firstChild; 
10232        if(el){
10233            Ext.fly(el).setStyle(Ext.isIE ? 'styleFloat' : 'cssFloat', 'none');
10234        }
10235    },
10236
10237    
10238    getEl : function(){
10239        return this.el;
10240    },
10241
10242    
10243    getGhost : function(){
10244        return this.ghost;
10245    },
10246
10247    
10248    hide : function(clear){
10249        this.el.hide();
10250        if(clear){
10251            this.reset(true);
10252        }
10253    },
10254
10255    
10256    stop : function(){
10257        if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){
10258            this.anim.stop();
10259        }
10260    },
10261
10262    
10263    show : function(){
10264        this.el.show();
10265    },
10266
10267    
10268    sync : function(){
10269        this.el.sync();
10270    },
10271
10272    
10273    repair : function(xy, callback, scope){
10274        this.callback = callback;
10275        this.scope = scope;
10276        if(xy && this.animRepair !== false){
10277            this.el.addClass("x-dd-drag-repair");
10278            this.el.hideUnders(true);
10279            this.anim = this.el.shift({
10280                duration: this.repairDuration || .5,
10281                easing: 'easeOut',
10282                xy: xy,
10283                stopFx: true,
10284                callback: this.afterRepair,
10285                scope: this
10286            });
10287        }else{
10288            this.afterRepair();
10289        }
10290    },
10291
10292    // private
10293    afterRepair : function(){
10294        this.hide(true);
10295        if(typeof this.callback == "function"){
10296            this.callback.call(this.scope || this);
10297        }
10298        this.callback = null;
10299        this.scope = null;
10300    }
10301};
10302
10303Ext.dd.DragSource = function(el, config){
10304    this.el = Ext.get(el);
10305    if(!this.dragData){
10306        this.dragData = {};
10307    }
10308    
10309    Ext.apply(this, config);
10310    
10311    if(!this.proxy){
10312        this.proxy = new Ext.dd.StatusProxy();
10313    }
10314    Ext.dd.DragSource.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group, 
10315          {dragElId : this.proxy.id, resizeFrame: false, isTarget: false, scroll: this.scroll === true});
10316    
10317    this.dragging = false;
10318};
10319
10320Ext.extend(Ext.dd.DragSource, Ext.dd.DDProxy, {
10321    
10322    
10323    dropAllowed : "x-dd-drop-ok",
10324    
10325    dropNotAllowed : "x-dd-drop-nodrop",
10326
10327    
10328    getDragData : function(e){
10329        return this.dragData;
10330    },
10331
10332    // private
10333    onDragEnter : function(e, id){
10334        var target = Ext.dd.DragDropMgr.getDDById(id);
10335        this.cachedTarget = target;
10336        if(this.beforeDragEnter(target, e, id) !== false){
10337            if(target.isNotifyTarget){
10338                var status = target.notifyEnter(this, e, this.dragData);
10339                this.proxy.setStatus(status);
10340            }else{
10341                this.proxy.setStatus(this.dropAllowed);
10342            }
10343            
10344            if(this.afterDragEnter){
10345                
10346                this.afterDragEnter(target, e, id);
10347            }
10348        }
10349    },
10350
10351    
10352    beforeDragEnter : function(target, e, id){
10353        return true;
10354    },
10355
10356    // private
10357    alignElWithMouse: function() {
10358        Ext.dd.DragSource.superclass.alignElWithMouse.apply(this, arguments);
10359        this.proxy.sync();
10360    },
10361
10362    // private
10363    onDragOver : function(e, id){
10364        var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
10365        if(this.beforeDragOver(target, e, id) !== false){
10366            if(target.isNotifyTarget){
10367                var status = target.notifyOver(this, e, this.dragData);
10368                this.proxy.setStatus(status);
10369            }
10370
10371            if(this.afterDragOver){
10372                
10373                this.afterDragOver(target, e, id);
10374            }
10375        }
10376    },
10377
10378    
10379    beforeDragOver : function(target, e, id){
10380        return true;
10381    },
10382
10383    // private
10384    onDragOut : function(e, id){
10385        var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
10386        if(this.beforeDragOut(target, e, id) !== false){
10387            if(target.isNotifyTarget){
10388                target.notifyOut(this, e, this.dragData);
10389            }
10390            this.proxy.reset();
10391            if(this.afterDragOut){
10392                
10393                this.afterDragOut(target, e, id);
10394            }
10395        }
10396        this.cachedTarget = null;
10397    },
10398
10399    
10400    beforeDragOut : function(target, e, id){
10401        return true;
10402    },
10403    
10404    // private
10405    onDragDrop : function(e, id){
10406        var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
10407        if(this.beforeDragDrop(target, e, id) !== false){
10408            if(target.isNotifyTarget){
10409                if(target.notifyDrop(this, e, this.dragData)){ // valid drop?
10410                    this.onValidDrop(target, e, id);
10411                }else{
10412                    this.onInvalidDrop(target, e, id);
10413                }
10414            }else{
10415                this.onValidDrop(target, e, id);
10416            }
10417            
10418            if(this.afterDragDrop){
10419                
10420                this.afterDragDrop(target, e, id);
10421            }
10422        }
10423        delete this.cachedTarget;
10424    },
10425
10426    
10427    beforeDragDrop : function(target, e, id){
10428        return true;
10429    },
10430
10431    // private
10432    onValidDrop : function(target, e, id){
10433        this.hideProxy();
10434        if(this.afterValidDrop){
10435            
10436            this.afterValidDrop(target, e, id);
10437        }
10438    },
10439
10440    // private
10441    getRepairXY : function(e, data){
10442        return this.el.getXY();  
10443    },
10444
10445    // private
10446    onInvalidDrop : function(target, e, id){
10447        this.beforeInvalidDrop(target, e, id);
10448        if(this.cachedTarget){
10449            if(this.cachedTarget.isNotifyTarget){
10450                this.cachedTarget.notifyOut(this, e, this.dragData);
10451            }
10452            this.cacheTarget = null;
10453        }
10454        this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);
10455
10456        if(this.afterInvalidDrop){
10457            
10458            this.afterInvalidDrop(e, id);
10459        }
10460    },
10461
10462    // private
10463    afterRepair : function(){
10464        if(Ext.enableFx){
10465            this.el.highlight(this.hlColor || "c3daf9");
10466        }
10467        this.dragging = false;
10468    },
10469
10470    
10471    beforeInvalidDrop : function(target, e, id){
10472        return true;
10473    },
10474
10475    // private
10476    handleMouseDown : function(e){
10477        if(this.dragging) {
10478            return;
10479        }
10480        var data = this.getDragData(e);
10481        if(data && this.onBeforeDrag(data, e) !== false){
10482            this.dragData = data;
10483            this.proxy.stop();
10484            Ext.dd.DragSource.superclass.handleMouseDown.apply(this, arguments);
10485        } 
10486    },
10487
10488    
10489    onBeforeDrag : function(data, e){
10490        return true;
10491    },
10492
10493    
10494    onStartDrag : Ext.emptyFn,
10495
10496    // private override
10497    startDrag : function(x, y){
10498        this.proxy.reset();
10499        this.dragging = true;
10500        this.proxy.update("");
10501        this.onInitDrag(x, y);
10502        this.proxy.show();
10503    },
10504
10505    // private
10506    onInitDrag : function(x, y){
10507        var clone = this.el.dom.cloneNode(true);
10508        clone.id = Ext.id(); // prevent duplicate ids
10509        this.proxy.update(clone);
10510        this.onStartDrag(x, y);
10511        return true;
10512    },
10513
10514    
10515    getProxy : function(){
10516        return this.proxy;  
10517    },
10518
10519    
10520    hideProxy : function(){
10521        this.proxy.hide();  
10522        this.proxy.reset(true);
10523        this.dragging = false;
10524    },
10525
10526    // private
10527    triggerCacheRefresh : function(){
10528        Ext.dd.DDM.refreshCache(this.groups);
10529    },
10530
10531    // private - override to prevent hiding
10532    b4EndDrag: function(e) {
10533    },
10534
10535    // private - override to prevent moving
10536    endDrag : function(e){
10537        this.onEndDrag(this.dragData, e);
10538    },
10539
10540    // private
10541    onEndDrag : function(data, e){
10542    },
10543    
10544    // private - pin to cursor
10545    autoOffset : function(x, y) {
10546        this.setDelta(-12, -20);
10547    }    
10548});
10549
10550Ext.dd.DropTarget = function(el, config){
10551    this.el = Ext.get(el);
10552    
10553    Ext.apply(this, config);
10554    
10555    if(this.containerScroll){
10556        Ext.dd.ScrollManager.register(this.el);
10557    }
10558    
10559    Ext.dd.DropTarget.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group, 
10560          {isTarget: true});
10561
10562};
10563
10564Ext.extend(Ext.dd.DropTarget, Ext.dd.DDTarget, {
10565    
10566    
10567    
10568    dropAllowed : "x-dd-drop-ok",
10569    
10570    dropNotAllowed : "x-dd-drop-nodrop",
10571
10572    // private
10573    isTarget : true,
10574
10575    // private
10576    isNotifyTarget : true,
10577
10578    
10579    notifyEnter : function(dd, e, data){
10580        if(this.overClass){
10581            this.el.addClass(this.overClass);
10582        }
10583        return this.dropAllowed;
10584    },
10585
10586    
10587    notifyOver : function(dd, e, data){
10588        return this.dropAllowed;
10589    },
10590
10591    
10592    notifyOut : function(dd, e, data){
10593        if(this.overClass){
10594            this.el.removeClass(this.overClass);
10595        }
10596    },
10597
10598    
10599    notifyDrop : function(dd, e, data){
10600        return false;
10601    }
10602});
10603
10604Ext.dd.DragZone = function(el, config){
10605    Ext.dd.DragZone.superclass.constructor.call(this, el, config);
10606    if(this.containerScroll){
10607        Ext.dd.ScrollManager.register(this.el);
10608    }
10609};
10610
10611Ext.extend(Ext.dd.DragZone, Ext.dd.DragSource, {
10612    
10613    
10614
10615    
10616    getDragData : function(e){
10617        return Ext.dd.Registry.getHandleFromEvent(e);
10618    },
10619    
10620    
10621    onInitDrag : function(x, y){
10622        this.proxy.update(this.dragData.ddel.cloneNode(true));
10623        this.onStartDrag(x, y);
10624        return true;
10625    },
10626    
10627    
10628    afterRepair : function(){
10629        if(Ext.enableFx){
10630            Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
10631        }
10632        this.dragging = false;
10633    },
10634
10635    
10636    getRepairXY : function(e){
10637        return Ext.Element.fly(this.dragData.ddel).getXY();  
10638    }
10639});
10640
10641Ext.dd.DropZone = function(el, config){
10642    Ext.dd.DropZone.superclass.constructor.call(this, el, config);
10643};
10644
10645Ext.extend(Ext.dd.DropZone, Ext.dd.DropTarget, {
10646    
10647    getTargetFromEvent : function(e){
10648        return Ext.dd.Registry.getTargetFromEvent(e);
10649    },
10650
10651    
10652    onNodeEnter : function(n, dd, e, data){
10653        
10654    },
10655
10656    
10657    onNodeOver : function(n, dd, e, data){
10658        return this.dropAllowed;
10659    },
10660
10661    
10662    onNodeOut : function(n, dd, e, data){
10663        
10664    },
10665
10666    
10667    onNodeDrop : function(n, dd, e, data){
10668        return false;
10669    },
10670
10671    
10672    onContainerOver : function(dd, e, data){
10673        return this.dropNotAllowed;
10674    },
10675
10676    
10677    onContainerDrop : function(dd, e, data){
10678        return false;
10679    },
10680
10681    
10682    notifyEnter : function(dd, e, data){
10683        return this.dropNotAllowed;
10684    },
10685
10686    
10687    notifyOver : function(dd, e, data){
10688        var n = this.getTargetFromEvent(e);
10689        if(!n){ // not over valid drop target
10690            if(this.lastOverNode){
10691                this.onNodeOut(this.lastOverNode, dd, e, data);
10692                this.lastOverNode = null;
10693            }
10694            return this.onContainerOver(dd, e, data);
10695        }
10696        if(this.lastOverNode != n){
10697            if(this.lastOverNode){
10698                this.onNodeOut(this.lastOverNode, dd, e, data);
10699            }
10700            this.onNodeEnter(n, dd, e, data);
10701            this.lastOverNode = n;
10702        }
10703        return this.onNodeOver(n, dd, e, data);
10704    },
10705
10706    
10707    notifyOut : function(dd, e, data){
10708        if(this.lastOverNode){
10709            this.onNodeOut(this.lastOverNode, dd, e, data);
10710            this.lastOverNode = null;
10711        }
10712    },
10713
10714    
10715    notifyDrop : function(dd, e, data){
10716        if(this.lastOverNode){
10717            this.onNodeOut(this.lastOverNode, dd, e, data);
10718            this.lastOverNode = null;
10719        }
10720        var n = this.getTargetFromEvent(e);
10721        return n ?
10722            this.onNodeDrop(n, dd, e, data) :
10723            this.onContainerDrop(dd, e, data);
10724    },
10725
10726    // private
10727    triggerCacheRefresh : function(){
10728        Ext.dd.DDM.refreshCache(this.groups);
10729    }  
10730});
10731
10732
10733Ext.data.SortTypes = {
10734    
10735    none : function(s){
10736        return s;
10737    },
10738    
10739    
10740    stripTagsRE : /<\/?[^>]+>/gi,
10741    
10742    
10743    asText : function(s){
10744        return String(s).replace(this.stripTagsRE, "");
10745    },
10746    
10747    
10748    asUCText : function(s){
10749        return String(s).toUpperCase().replace(this.stripTagsRE, "");
10750    },
10751    
10752    
10753    asUCString : function(s) {
10754    	return String(s).toUpperCase();
10755    },
10756    
10757    
10758    asDate : function(s) {
10759        if(!s){
10760            return 0;
10761        }
10762        if(Ext.isDate(s)){
10763            return s.getTime();
10764        }
10765    	return Date.parse(String(s));
10766    },
10767    
10768    
10769    asFloat : function(s) {
10770    	var val = parseFloat(String(s).replace(/,/g, ""));
10771        if(isNaN(val)) val = 0;
10772    	return val;
10773    },
10774    
10775    
10776    asInt : function(s) {
10777        var val = parseInt(String(s).replace(/,/g, ""));
10778        if(isNaN(val)) val = 0;
10779    	return val;
10780    }
10781};
10782
10783Ext.data.Record = function(data, id){
10784    this.id = (id || id === 0) ? id : ++Ext.data.Record.AUTO_ID;
10785    this.data = data;
10786};
10787
10788
10789Ext.data.Record.create = function(o){
10790    var f = Ext.extend(Ext.data.Record, {});
10791    var p = f.prototype;
10792    p.fields = new Ext.util.MixedCollection(false, function(field){
10793        return field.name;
10794    });
10795    for(var i = 0, len = o.length; i < len; i++){
10796        p.fields.add(new Ext.data.Field(o[i]));
10797    }
10798    f.getField = function(name){
10799        return p.fields.get(name);
10800    };
10801    return f;
10802};
10803
10804Ext.data.Record.AUTO_ID = 1000;
10805Ext.data.Record.EDIT = 'edit';
10806Ext.data.Record.REJECT = 'reject';
10807Ext.data.Record.COMMIT = 'commit';
10808
10809Ext.data.Record.prototype = {
10810    
10811    
10812    
10813    
10814    dirty : false,
10815    editing : false,
10816    error: null,
10817    
10818    modified: null,
10819
10820    // private
10821    join : function(store){
10822        this.store = store;
10823    },
10824
10825    
10826    set : function(name, value){
10827        if(String(this.data[name]) == String(value)){
10828            return;
10829        }
10830        this.dirty = true;
10831        if(!this.modified){
10832            this.modified = {};
10833        }
10834        if(typeof this.modified[name] == 'undefined'){
10835            this.modified[name] = this.data[name];
10836        }
10837        this.data[name] = value;
10838        if(!this.editing && this.store){
10839            this.store.afterEdit(this);
10840        }
10841    },
10842
10843    
10844    get : function(name){
10845        return this.data[name];
10846    },
10847
10848    
10849    beginEdit : function(){
10850        this.editing = true;
10851        this.modified = {};
10852    },
10853
10854    
10855    cancelEdit : function(){
10856        this.editing = false;
10857        delete this.modified;
10858    },
10859
10860    
10861    endEdit : function(){
10862        this.editing = false;
10863        if(this.dirty && this.store){
10864            this.store.afterEdit(this);
10865        }
10866    },
10867
10868    
10869    reject : function(silent){
10870        var m = this.modified;
10871        for(var n in m){
10872            if(typeof m[n] != "function"){
10873                this.data[n] = m[n];
10874            }
10875        }
10876        this.dirty = false;
10877        delete this.modified;
10878        this.editing = false;
10879        if(this.store && silent !== true){
10880            this.store.afterReject(this);
10881        }
10882    },
10883
10884    
10885    commit : function(silent){
10886        this.dirty = false;
10887        delete this.modified;
10888        this.editing = false;
10889        if(this.store && silent !== true){
10890            this.store.afterCommit(this);
10891        }
10892    },
10893
10894    
10895    getChanges : function(){
10896        var m = this.modified, cs = {};
10897        for(var n in m){
10898            if(m.hasOwnProperty(n)){
10899                cs[n] = this.data[n];
10900            }
10901        }
10902        return cs;
10903    },
10904
10905    // private
10906    hasError : function(){
10907        return this.error != null;
10908    },
10909
10910    // private
10911    clearError : function(){
10912        this.error = null;
10913    },
10914
10915    
10916    copy : function(newId) {
10917        return new this.constructor(Ext.apply({}, this.data), newId || this.id);
10918    },
10919
10920    
10921    isModified : function(fieldName){
10922        return !!(this.modified && this.modified.hasOwnProperty(fieldName));
10923    }
10924};
10925
10926Ext.StoreMgr = Ext.apply(new Ext.util.MixedCollection(), {
10927    
10928
10929    
10930    register : function(){
10931        for(var i = 0, s; s = arguments[i]; i++){
10932            this.add(s);
10933        }
10934    },
10935
10936    
10937    unregister : function(){
10938        for(var i = 0, s; s = arguments[i]; i++){
10939            this.remove(this.lookup(s));
10940        }
10941    },
10942
10943    
10944    lookup : function(id){
10945        return typeof id == "object" ? id : this.get(id);
10946    },
10947
10948    // getKey implementation for MixedCollection
10949    getKey : function(o){
10950         return o.storeId || o.id;
10951    }
10952});
10953
10954Ext.data.Store = function(config){
10955    this.data = new Ext.util.MixedCollection(false);
10956    this.data.getKey = function(o){
10957        return o.id;
10958    };
10959    
10960    this.baseParams = {};
10961    
10962    this.paramNames = {
10963        "start" : "start",
10964        "limit" : "limit",
10965        "sort" : "sort",
10966        "dir" : "dir"
10967    };
10968
10969    if(config && config.data){
10970        this.inlineData = config.data;
10971        delete config.data;
10972    }
10973
10974    Ext.apply(this, config);
10975
10976    if(this.url && !this.proxy){
10977        this.proxy = new Ext.data.HttpProxy({url: this.url});
10978    }
10979
10980    if(this.reader){ // reader passed
10981        if(!this.recordType){
10982            this.recordType = this.reader.recordType;
10983        }
10984        if(this.reader.onMetaChange){
10985            this.reader.onMetaChange = this.onMetaChange.createDelegate(this);
10986        }
10987    }
10988
10989    
10990    if(this.recordType){
10991        
10992        this.fields = this.recordType.prototype.fields;
10993    }
10994    this.modified = [];
10995
10996    this.addEvents(
10997        
10998        'datachanged',
10999        
11000        'metachange',
11001        
11002        'add',
11003        
11004        'remove',
11005        
11006        'update',
11007        
11008        'clear',
11009        
11010        'beforeload',
11011        
11012        'load',
11013        
11014        'loadexception'
11015    );
11016
11017    if(this.proxy){
11018        this.relayEvents(this.proxy,  ["loadexception"]);
11019    }
11020
11021    this.sortToggle = {};
11022    if(this.sortInfo){
11023        this.setDefaultSort(this.sortInfo.field, this.sortInfo.direction);
11024    }
11025
11026    Ext.data.Store.superclass.constructor.call(this);
11027
11028    if(this.storeId || this.id){
11029        Ext.StoreMgr.register(this);
11030    }
11031    if(this.inlineData){
11032        this.loadData(this.inlineData);
11033        delete this.inlineData;
11034    }else if(this.autoLoad){
11035        this.load.defer(10, this, [
11036            typeof this.autoLoad == 'object' ?
11037                this.autoLoad : undefined]);
11038    }
11039};
11040Ext.extend(Ext.data.Store, Ext.util.Observable, {
11041    
11042    
11043    
11044    
11045    
11046    
11047    
11048    
11049    
11050    remoteSort : false,
11051
11052    
11053    pruneModifiedRecords : false,
11054
11055    
11056   lastOptions : null,
11057
11058    destroy : function(){
11059        if(this.storeId || this.id){
11060            Ext.StoreMgr.unregister(this);
11061        }
11062        this.data = null;
11063        this.purgeListeners();
11064    },
11065
11066    
11067    add : function(records){
11068        records = [].concat(records);
11069        if(records.length < 1){
11070            return;
11071        }
11072        for(var i = 0, len = records.length; i < len; i++){
11073            records[i].join(this);
11074        }
11075        var index = this.data.length;
11076        this.data.addAll(records);
11077        if(this.snapshot){
11078            this.snapshot.addAll(records);
11079        }
11080        this.fireEvent("add", this, records, index);
11081    },
11082
11083    
11084    addSorted : function(record){
11085        var index = this.findInsertIndex(record);
11086        this.insert(index, record);
11087    },
11088
11089    
11090    remove : function(record){
11091        var index = this.data.indexOf(record);
11092        this.data.removeAt(index);
11093        if(this.pruneModifiedRecords){
11094            this.modified.remove(record);
11095        }
11096        if(this.snapshot){
11097            this.snapshot.remove(record);
11098        }
11099        this.fireEvent("remove", this, record, index);
11100    },
11101    
11102    
11103    removeAt : function(index){
11104        this.remove(this.getAt(index));    
11105    },
11106
11107    
11108    removeAll : function(){
11109        this.data.clear();
11110        if(this.snapshot){
11111            this.snapshot.clear();
11112        }
11113        if(this.pruneModifiedRecords){
11114            this.modified = [];
11115        }
11116        this.fireEvent("clear", this);
11117    },
11118
11119    
11120    insert : function(index, records){
11121        records = [].concat(records);
11122        for(var i = 0, len = records.length; i < len; i++){
11123            this.data.insert(index, records[i]);
11124            records[i].join(this);
11125        }
11126        this.fireEvent("add", this, records, index);
11127    },
11128
11129    
11130    indexOf : function(record){
11131        return this.data.indexOf(record);
11132    },
11133
11134    
11135    indexOfId : function(id){
11136        return this.data.indexOfKey(id);
11137    },
11138
11139    
11140    getById : function(id){
11141        return this.data.key(id);
11142    },
11143
11144    
11145    getAt : function(index){
11146        return this.data.itemAt(index);
11147    },
11148
11149    
11150    getRange : function(start, end){
11151        return this.data.getRange(start, end);
11152    },
11153
11154    // private
11155    storeOptions : function(o){
11156        o = Ext.apply({}, o);
11157        delete o.callback;
11158        delete o.scope;
11159        this.lastOptions = o;
11160    },
11161
11162    
11163    load : function(options){
11164        options = options || {};
11165        if(this.fireEvent("beforeload", this, options) !== false){
11166            this.storeOptions(options);
11167            var p = Ext.apply(options.params || {}, this.baseParams);
11168            if(this.sortInfo && this.remoteSort){
11169                var pn = this.paramNames;
11170                p[pn["sort"]] = this.sortInfo.field;
11171                p[pn["dir"]] = this.sortInfo.direction;
11172            }
11173            this.proxy.load(p, this.reader, this.loadRecords, this, options);
11174            return true;
11175        } else {
11176          return false;
11177        }
11178    },
11179
11180    
11181    reload : function(options){
11182        this.load(Ext.applyIf(options||{}, this.lastOptions));
11183    },
11184
11185    // private
11186    // Called as a callback by the Reader during a load operation.
11187    loadRecords : function(o, options, success){
11188        if(!o || success === false){
11189            if(success !== false){
11190                this.fireEvent("load", this, [], options);
11191            }
11192            if(options.callback){
11193                options.callback.call(options.scope || this, [], options, false);
11194            }
11195            return;
11196        }
11197        var r = o.records, t = o.totalRecords || r.length;
11198        if(!options || options.add !== true){
11199            if(this.pruneModifiedRecords){
11200                this.modified = [];
11201            }
11202            for(var i = 0, len = r.length; i < len; i++){
11203                r[i].join(this);
11204            }
11205            if(this.snapshot){
11206                this.data = this.snapshot;
11207                delete this.snapshot;
11208            }
11209            this.data.clear();
11210            this.data.addAll(r);
11211            this.totalLength = t;
11212            this.applySort();
11213            this.fireEvent("datachanged", this);
11214        }else{
11215            this.totalLength = Math.max(t, this.data.length+r.length);
11216            this.add(r);
11217        }
11218        this.fireEvent("load", this, r, options);
11219        if(options.callback){
11220            options.callback.call(options.scope || this, r, options, true);
11221        }
11222    },
11223
11224    
11225    loadData : function(o, append){
11226        var r = this.reader.readRecords(o);
11227        this.loadRecords(r, {add: append}, true);
11228    },
11229
11230    
11231    getCount : function(){
11232        return this.data.length || 0;
11233    },
11234
11235    
11236    getTotalCount : function(){
11237        return this.totalLength || 0;
11238    },
11239
11240    
11241    getSortState : function(){
11242        return this.sortInfo;
11243    },
11244
11245    // private
11246    applySort : function(){
11247        if(this.sortInfo && !this.remoteSort){
11248            var s = this.sortInfo, f = s.field;
11249            this.sortData(f, s.direction);
11250        }
11251    },
11252
11253    // private
11254    sortData : function(f, direction){
11255        direction = direction || 'ASC';
11256        var st = this.fields.get(f).sortType;
11257        var fn = function(r1, r2){
11258            var v1 = st(r1.data[f]), v2 = st(r2.data[f]);
11259            return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
11260        };
11261        this.data.sort(direction, fn);
11262        if(this.snapshot && this.snapshot != this.data){
11263            this.snapshot.sort(direction, fn);
11264        }
11265    },
11266
11267    
11268    setDefaultSort : function(field, dir){
11269        dir = dir ? dir.toUpperCase() : "ASC";
11270        this.sortInfo = {field: field, direction: dir};
11271        this.sortToggle[field] = dir;
11272    },
11273
11274    
11275    sort : function(fieldName, dir){
11276        var f = this.fields.get(fieldName);
11277        if(!f){
11278            return false;
11279        }
11280        if(!dir){
11281            if(this.sortInfo && this.sortInfo.field == f.name){ // toggle sort dir
11282                dir = (this.sortToggle[f.name] || "ASC").toggle("ASC", "DESC");
11283            }else{
11284                dir = f.sortDir;
11285            }
11286        }
11287        var st = (this.sortToggle) ? this.sortToggle[f.name] : null;
11288        var si = (this.sortInfo) ? this.sortInfo : null;
11289
11290        this.sortToggle[f.name] = dir;
11291        this.sortInfo = {field: f.name, direction: dir};
11292        if(!this.remoteSort){
11293            this.applySort();
11294            this.fireEvent("datachanged", this);
11295        }else{
11296            if (!this.load(this.lastOptions)) {
11297                if (st) {
11298                    this.sortToggle[f.name] = st;
11299                }
11300                if (si) {
11301                    this.sortInfo = si;
11302                }
11303            }
11304        }
11305    },
11306
11307    
11308    each : function(fn, scope){
11309        this.data.each(fn, scope);
11310    },
11311
11312    
11313    getModifiedRecords : function(){
11314        return this.modified;
11315    },
11316
11317    // private
11318    createFilterFn : function(property, value, anyMatch, caseSensitive){
11319        if(Ext.isEmpty(value, false)){
11320            return false;
11321        }
11322        value = this.data.createValueMatcher(value, anyMatch, caseSensitive);
11323        return function(r){
11324            return value.test(r.data[property]);
11325        };
11326    },
11327
11328    
11329    sum : function(property, start, end){
11330        var rs = this.data.items, v = 0;
11331        start = start || 0;
11332        end = (end || end === 0) ? end : rs.length-1;
11333
11334        for(var i = start; i <= end; i++){
11335            v += (rs[i].data[property] || 0);
11336        }
11337        return v;
11338    },
11339
11340    
11341    filter : function(property, value, anyMatch, caseSensitive){
11342        var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
11343        return fn ? this.filterBy(fn) : this.clearFilter();
11344    },
11345
11346    
11347    filterBy : function(fn, scope){
11348        this.snapshot = this.snapshot || this.data;
11349        this.data = this.queryBy(fn, scope||this);
11350        this.fireEvent("datachanged", this);
11351    },
11352
11353    
11354    query : function(property, value, anyMatch, caseSensitive){
11355        var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
11356        return fn ? this.queryBy(fn) : this.data.clone();
11357    },
11358
11359    
11360    queryBy : function(fn, scope){
11361        var data = this.snapshot || this.data;
11362        return data.filterBy(fn, scope||this);
11363    },
11364
11365    
11366    find : function(property, value, start, anyMatch, caseSensitive){
11367        var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
11368        return fn ? this.data.findIndexBy(fn, null, start) : -1;
11369    },
11370
11371    
11372    findBy : function(fn, scope, start){
11373        return this.data.findIndexBy(fn, scope, start);
11374    },
11375
11376    
11377    collect : function(dataIndex, allowNull, bypassFilter){
11378        var d = (bypassFilter === true && this.snapshot) ?
11379                this.snapshot.items : this.data.items;
11380        var v, sv, r = [], l = {};
11381        for(var i = 0, len = d.length; i < len; i++){
11382            v = d[i].data[dataIndex];
11383            sv = String(v);
11384            if((allowNull || !Ext.isEmpty(v)) && !l[sv]){
11385                l[sv] = true;
11386                r[r.length] = v;
11387            }
11388        }
11389        return r;
11390    },
11391
11392    
11393    clearFilter : function(suppressEvent){
11394        if(this.isFiltered()){
11395            this.data = this.snapshot;
11396            delete this.snapshot;
11397            if(suppressEvent !== true){
11398                this.fireEvent("datachanged", this);
11399            }
11400        }
11401    },
11402
11403    
11404    isFiltered : function(){
11405        return this.snapshot && this.snapshot != this.data;
11406    },
11407
11408    // private
11409    afterEdit : function(record){
11410        if(this.modified.indexOf(record) == -1){
11411            this.modified.push(record);
11412        }
11413        this.fireEvent("update", this, record, Ext.data.Record.EDIT);
11414    },
11415
11416    // private
11417    afterReject : function(record){
11418        this.modified.remove(record);
11419        this.fireEvent("update", this, record, Ext.data.Record.REJECT);
11420    },
11421
11422    // private
11423    afterCommit : function(record){
11424        this.modified.remove(record);
11425        this.fireEvent("update", this, record, Ext.data.Record.COMMIT);
11426    },
11427
11428    
11429    commitChanges : function(){
11430        var m = this.modified.slice(0);
11431        this.modified = [];
11432        for(var i = 0, len = m.length; i < len; i++){
11433            m[i].commit();
11434        }
11435    },
11436
11437    
11438    rejectChanges : function(){
11439        var m = this.modified.slice(0);
11440        this.modified = [];
11441        for(var i = 0, len = m.length; i < len; i++){
11442            m[i].reject();
11443        }
11444    },
11445
11446    // private
11447    onMetaChange : function(meta, rtype, o){
11448        this.recordType = rtype;
11449        this.fields = rtype.prototype.fields;
11450        delete this.snapshot;
11451        this.sortInfo = meta.sortInfo;
11452        this.modified = [];
11453        this.fireEvent('metachange', this, this.reader.meta);
11454    },
11455
11456    // private
11457    findInsertIndex : function(record){
11458        this.suspendEvents();
11459        var data = this.data.clone();
11460        this.data.add(record);
11461        this.applySort();
11462        var index = this.data.indexOf(record);
11463        this.data = data;
11464        this.resumeEvents();
11465        return index;
11466    }
11467});
11468
11469Ext.data.SimpleStore = function(config){
11470    Ext.data.SimpleStore.superclass.constructor.call(this, Ext.apply(config, {
11471        reader: new Ext.data.ArrayReader({
11472                id: config.id
11473            },
11474            Ext.data.Record.create(config.fields)
11475        )
11476    }));
11477};
11478Ext.extend(Ext.data.SimpleStore, Ext.data.Store, {
11479    loadData : function(data, append){
11480        if(this.expandData === true){
11481            var r = [];
11482            for(var i = 0, len = data.length; i < len; i++){
11483                r[r.length] = [data[i]];
11484            }
11485            data = r;
11486        }
11487        Ext.data.SimpleStore.superclass.loadData.call(this, data, append);
11488    }
11489});
11490
11491Ext.data.JsonStore = function(c){
11492    
11493    
11494    Ext.data.JsonStore.superclass.constructor.call(this, Ext.apply(c, {
11495        proxy: c.proxy || (!c.data ? new Ext.data.HttpProxy({url: c.url}) : undefined),
11496        reader: new Ext.data.JsonReader(c, c.fields)
11497    }));
11498};
11499Ext.extend(Ext.data.JsonStore, Ext.data.Store);
11500
11501Ext.data.Field = function(config){
11502    if(typeof config == "string"){
11503        config = {name: config};
11504    }
11505    Ext.apply(this, config);
11506    
11507    if(!this.type){
11508        this.type = "auto";
11509    }
11510    
11511    var st = Ext.data.SortTypes;
11512    // named sortTypes are supported, here we look them up
11513    if(typeof this.sortType == "string"){
11514        this.sortType = st[this.sortType];
11515    }
11516    
11517    // set default sortType for strings and dates
11518    if(!this.sortType){
11519        switch(this.type){
11520            case "string":
11521                this.sortType = st.asUCString;
11522                break;
11523            case "date":
11524                this.sortType = st.asDate;
11525                break;
11526            default:
11527                this.sortType = st.none;
11528        }
11529    }
11530
11531    // define once
11532    var stripRe = /[\$,%]/g;
11533
11534    // prebuilt conversion function for this field, instead of
11535    // switching every time we're reading a value
11536    if(!this.convert){
11537        var cv, dateFormat = this.dateFormat;
11538        switch(this.type){
11539            case "":
11540            case "auto":
11541            case undefined:
11542                cv = function(v){ return v; };
11543                break;
11544            case "string":
11545                cv = function(v){ return (v === undefined || v === null) ? '' : String(v); };
11546                break;
11547            case "int":
11548                cv = function(v){
11549                    return v !== undefined && v !== null && v !== '' ?
11550                           parseInt(String(v).replace(stripRe, ""), 10) : '';
11551                    };
11552                break;
11553            case "float":
11554                cv = function(v){
11555                    return v !== undefined && v !== null && v !== '' ?
11556                           parseFloat(String(v).replace(stripRe, ""), 10) : ''; 
11557                    };
11558                break;
11559            case "bool":
11560            case "boolean":
11561                cv = function(v){ return v === true || v === "true" || v == 1; };
11562                break;
11563            case "date":
11564                cv = function(v){
11565                    if(!v){
11566                        return '';
11567                    }
11568                    if(Ext.isDate(v)){
11569                        return v;
11570                    }
11571                    if(dateFormat){
11572                        if(dateFormat == "timestamp"){
11573                            return new Date(v*1000);
11574                        }
11575                        if(dateFormat == "time"){
11576                            return new Date(parseInt(v, 10));
11577                        }
11578                        return Date.parseDate(v, dateFormat);
11579                    }
11580                    var parsed = Date.parse(v);
11581                    return parsed ? new Date(parsed) : null;
11582                };
11583             break;
11584            
11585        }
11586        this.convert = cv;
11587    }
11588};
11589
11590Ext.data.Field.prototype = {
11591    
11592    
11593    
11594    
11595    dateFormat: null,
11596    
11597    defaultValue: "",
11598    
11599    mapping: null,
11600    
11601    sortType : null,
11602    
11603    sortDir : "ASC"
11604};
11605
11606Ext.data.DataReader = function(meta, recordType){
11607    
11608    this.meta = meta;
11609    this.recordType = Ext.isArray(recordType) ? 
11610        Ext.data.Record.create(recordType) : recordType;
11611};
11612
11613Ext.data.DataReader.prototype = {
11614    
11615};
11616
11617Ext.data.DataProxy = function(){
11618    this.addEvents(
11619        
11620        'beforeload',
11621        
11622        'load'
11623    );
11624    Ext.data.DataProxy.superclass.constructor.call(this);
11625};
11626
11627Ext.extend(Ext.data.DataProxy, Ext.util.Observable);
11628
11629Ext.data.MemoryProxy = function(data){
11630    Ext.data.MemoryProxy.superclass.constructor.call(this);
11631    this.data = data;
11632};
11633
11634Ext.extend(Ext.data.MemoryProxy, Ext.data.DataProxy, {
11635    
11636    
11637    
11638    load : function(params, reader, callback, scope, arg){
11639        params = params || {};
11640        var result;
11641        try {
11642            result = reader.readRecords(this.data);
11643        }catch(e){
11644            this.fireEvent("loadexception", this, arg, null, e);
11645            callback.call(scope, null, arg, false);
11646            return;
11647        }
11648        callback.call(scope, result, arg, true);
11649    },
11650    
11651    // private
11652    update : function(params, records){
11653        
11654    }
11655});
11656
11657Ext.data.HttpProxy = function(conn){
11658    Ext.data.HttpProxy.superclass.constructor.call(this);
11659    
11660    this.conn = conn;
11661    this.useAjax = !conn || !conn.events;
11662
11663    
11664};
11665
11666Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {
11667    
11668    getConnection : function(){
11669        return this.useAjax ? Ext.Ajax : this.conn;
11670    },
11671
11672    
11673    load : function(params, reader, callback, scope, arg){
11674        if(this.fireEvent("beforeload", this, params) !== false){
11675            var  o = {
11676                params : params || {},
11677                request: {
11678                    callback : callback,
11679                    scope : scope,
11680                    arg : arg
11681                },
11682                reader: reader,
11683                callback : this.loadResponse,
11684                scope: this
11685            };
11686            if(this.useAjax){
11687                Ext.applyIf(o, this.conn);
11688                if(this.activeRequest){
11689                    Ext.Ajax.abort(this.activeRequest);
11690                }
11691                this.activeRequest = Ext.Ajax.request(o);
11692            }else{
11693                this.conn.request(o);
11694            }
11695        }else{
11696            callback.call(scope||this, null, arg, false);
11697        }
11698    },
11699
11700    // private
11701    loadResponse : function(o, success, response){
11702        delete this.activeRequest;
11703        if(!success){
11704            this.fireEvent("loadexception", this, o, response);
11705            o.request.callback.call(o.request.scope, null, o.request.arg, false);
11706            return;
11707        }
11708        var result;
11709        try {
11710            result = o.reader.read(response);
11711        }catch(e){
11712            this.fireEvent("loadexception", this, o, response, e);
11713            o.request.callback.call(o.request.scope, null, o.request.arg, false);
11714            return;
11715        }
11716        this.fireEvent("load", this, o, o.request.arg);
11717        o.request.callback.call(o.request.scope, result, o.request.arg, true);
11718    },
11719    
11720    // private
11721    update : function(dataSet){
11722        
11723    },
11724    
11725    // private
11726    updateResponse : function(dataSet){
11727        
11728    }
11729});
11730
11731Ext.data.ScriptTagProxy = function(config){
11732    Ext.data.ScriptTagProxy.superclass.constructor.call(this);
11733    Ext.apply(this, config);
11734    this.head = document.getElementsByTagName("head")[0];
11735    
11736    
11737};
11738
11739Ext.data.ScriptTagProxy.TRANS_ID = 1000;
11740
11741Ext.extend(Ext.data.ScriptTagProxy, Ext.data.DataProxy, {
11742    
11743    
11744    timeout : 30000,
11745    
11746    callbackParam : "callback",
11747    
11748    nocache : true,
11749
11750    
11751    load : function(params, reader, callback, scope, arg){
11752        if(this.fireEvent("beforeload", this, params) !== false){
11753
11754            var p = Ext.urlEncode(Ext.apply(params, this.extraParams));
11755
11756            var url = this.url;
11757            url += (url.indexOf("?") != -1 ? "&" : "?") + p;
11758            if(this.nocache){
11759                url += "&_dc=" + (new Date().getTime());
11760            }
11761            var transId = ++Ext.data.ScriptTagProxy.TRANS_ID;
11762            var trans = {
11763                id : transId,
11764                cb : "stcCallback"+transId,
11765                scriptId : "stcScript"+transId,
11766                params : params,
11767                arg : arg,
11768                url : url,
11769                callback : callback,
11770                scope : scope,
11771                reader : reader
11772            };
11773            var conn = this;
11774
11775            window[trans.cb] = function(o){
11776                conn.handleResponse(o, trans);
11777            };
11778
11779            url += String.format("&{0}={1}", this.callbackParam, trans.cb);
11780
11781            if(this.autoAbort !== false){
11782                this.abort();
11783            }
11784
11785            trans.timeoutId = this.handleFailure.defer(this.timeout, this, [trans]);
11786
11787            var script = document.createElement("script");
11788            script.setAttribute("src", url);
11789            script.setAttribute("type", "text/javascript");
11790            script.setAttribute("id", trans.scriptId);
11791            this.head.appendChild(script);
11792
11793            this.trans = trans;
11794        }else{
11795            callback.call(scope||this, null, arg, false);
11796        }
11797    },
11798
11799    // private
11800    isLoading : function(){
11801        return this.trans ? true : false;
11802    },
11803
11804    
11805    abort : function(){
11806        if(this.isLoading()){
11807            this.destroyTrans(this.trans);
11808        }
11809    },
11810
11811    // private
11812    destroyTrans : function(trans, isLoaded){
11813        this.head.removeChild(document.getElementById(trans.scriptId));
11814        clearTimeout(trans.timeoutId);
11815        if(isLoaded){
11816            window[trans.cb] = undefined;
11817            try{
11818                delete window[trans.cb];
11819            }catch(e){}
11820        }else{
11821            // if hasn't been loaded, wait for load to remove it to prevent script error
11822            window[trans.cb] = function(){
11823                window[trans.cb] = undefined;
11824                try{
11825                    delete window[trans.cb];
11826                }catch(e){}
11827            };
11828        }
11829    },
11830
11831    // private
11832    handleResponse : function(o, trans){
11833        this.trans = false;
11834        this.destroyTrans(trans, true);
11835        var result;
11836        try {
11837            result = trans.reader.readRecords(o);
11838        }catch(e){
11839            this.fireEvent("loadexception", this, o, trans.arg, e);
11840            trans.callback.call(trans.scope||window, null, trans.arg, false);
11841            return;
11842        }
11843        this.fireEvent("load", this, o, trans.arg);
11844        trans.callback.call(trans.scope||window, result, trans.arg, true);
11845    },
11846
11847    // private
11848    handleFailure : function(trans){
11849        this.trans = false;
11850        this.destroyTrans(trans, false);
11851        this.fireEvent("loadexception", this, null, trans.arg);
11852        trans.callback.call(trans.scope||window, null, trans.arg, false);
11853    }
11854});
11855
11856Ext.data.JsonReader = function(meta, recordType){
11857    meta = meta || {};
11858    Ext.data.JsonReader.superclass.constructor.call(this, meta, recordType || meta.fields);
11859};
11860Ext.extend(Ext.data.JsonReader, Ext.data.DataReader, {
11861    
11862    
11863    read : function(response){
11864        var json = response.responseText;
11865        var o = eval("("+json+")");
11866        if(!o) {
11867            throw {message: "JsonReader.read: Json object not found"};
11868        }
11869        return this.readRecords(o);
11870    },
11871
11872    // private function a store will implement
11873    onMetaChange : function(meta, recordType, o){
11874
11875    },
11876
11877    
11878    simpleAccess: function(obj, subsc) {
11879    	return obj[subsc];
11880    },
11881
11882	
11883    getJsonAccessor: function(){
11884        var re = /[\[\.]/;
11885        return function(expr) {
11886            try {
11887                return(re.test(expr))
11888                    ? new Function("obj", "return obj." + expr)
11889                    : function(obj){
11890                        return obj[expr];
11891                    };
11892            } catch(e){}
11893            return Ext.emptyFn;
11894        };
11895    }(),
11896
11897    
11898    readRecords : function(o){
11899        
11900        this.jsonData = o;
11901        if(o.metaData){
11902            delete this.ef;
11903            this.meta = o.metaData;
11904            this.recordType = Ext.data.Record.create(o.metaData.fields);
11905            this.onMetaChange(this.meta, this.recordType, o);
11906        }
11907        var s = this.meta, Record = this.recordType,
11908            f = Record.prototype.fields, fi = f.items, fl = f.length;
11909
11910//      Generate extraction functions for the totalProperty, the root, the id, and for each field
11911        if (!this.ef) {
11912            if(s.totalProperty) {
11913	            this.getTotal = this.getJsonAccessor(s.totalProperty);
11914	        }
11915	        if(s.successProperty) {
11916	            this.getSuccess = this.getJsonAccessor(s.successProperty);
11917	        }
11918	        this.getRoot = s.root ? this.getJsonAccessor(s.root) : function(p){return p;};
11919	        if (s.id) {
11920	        	var g = this.getJsonAccessor(s.id);
11921	        	this.getId = function(rec) {
11922	        		var r = g(rec);
11923		        	return (r === undefined || r === "") ? null : r;
11924	        	};
11925	        } else {
11926	        	this.getId = function(){return null;};
11927	        }
11928            this.ef = [];
11929            for(var i = 0; i < fl; i++){
11930                f = fi[i];
11931                var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;
11932                this.ef[i] = this.getJsonAccessor(map);
11933            }
11934        }
11935
11936    	var root = this.getRoot(o), c = root.length, totalRecords = c, success = true;
11937    	if(s.totalProperty){
11938            var v = parseInt(this.getTotal(o), 10);
11939            if(!isNaN(v)){
11940                totalRecords = v;
11941            }
11942        }
11943        if(s.successProperty){
11944            var v = this.getSuccess(o);
11945            if(v === false || v === 'false'){
11946                success = false;
11947            }
11948        }
11949        var records = [];
11950	    for(var i = 0; i < c; i++){
11951		    var n = root[i];
11952	        var values = {};
11953	        var id = this.getId(n);
11954	        for(var j = 0; j < fl; j++){
11955	            f = fi[j];
11956                var v = this.ef[j](n);
11957                values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue, n);
11958	        }
11959	        var record = new Record(values, id);
11960	        record.json = n;
11961	        records[i] = record;
11962	    }
11963	    return {
11964	        success : success,
11965	        records : records,
11966	        totalRecords : totalRecords
11967	    };
11968    }
11969});
11970
11971Ext.data.XmlReader = function(meta, recordType){
11972    meta = meta || {};
11973    Ext.data.XmlReader.superclass.constructor.call(this, meta, recordType || meta.fields);
11974};
11975Ext.extend(Ext.data.XmlReader, Ext.data.DataReader, {
11976    
11977    read : function(response){
11978        var doc = response.responseXML;
11979        if(!doc) {
11980            throw {message: "XmlReader.read: XML Document not available"};
11981        }
11982        return this.readRecords(doc);
11983    },
11984
11985    
11986    readRecords : function(doc){
11987        
11988        this.xmlData = doc;
11989        var root = doc.documentElement || doc;
11990    	var q = Ext.DomQuery;
11991    	var recordType = this.recordType, fields = recordType.prototype.fields;
11992    	var sid = this.meta.id;
11993    	var totalRecords = 0, success = true;
11994    	if(this.meta.totalRecords){
11995    	    totalRecords = q.selectNumber(this.meta.totalRecords, root, 0);
11996    	}
11997
11998        if(this.meta.success){
11999            var sv = q.selectValue(this.meta.success, root, true);
12000            success = sv !== false && sv !== 'false';
12001    	}
12002    	var records = [];
12003    	var ns = q.select(this.meta.record, root);
12004        for(var i = 0, len = ns.length; i < len; i++) {
12005	        var n = ns[i];
12006	        var values = {};
12007	        var id = sid ? q.selectValue(sid, n) : undefined;
12008	        for(var j = 0, jlen = fields.length; j < jlen; j++){
12009	            var f = fields.items[j];
12010                var v = q.selectValue(f.mapping || f.name, n, f.defaultValue);
12011	            v = f.convert(v, n);
12012	            values[f.name] = v;
12013	        }
12014	        var record = new recordType(values, id);
12015	        record.node = n;
12016	        records[records.length] = record;
12017	    }
12018
12019	    return {
12020	        success : success,
12021	        records : records,
12022	        totalRecords : totalRecords || records.length
12023	    };
12024    }
12025});
12026
12027Ext.data.ArrayReader = Ext.extend(Ext.data.JsonReader, {
12028    
12029    readRecords : function(o){
12030        var sid = this.meta ? this.meta.id : null;
12031    	var recordType = this.recordType, fields = recordType.prototype.fields;
12032    	var records = [];
12033    	var root = o;
12034	    for(var i = 0; i < root.length; i++){
12035		    var n = root[i];
12036	        var values = {};
12037	        var id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null);
12038	        for(var j = 0, jlen = fields.length; j < jlen; j++){
12039                var f = fields.items[j];
12040                var k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j;
12041                var v = n[k] !== undefined ? n[k] : f.defaultValue;
12042                v = f.convert(v, n);
12043                values[f.name] = v;
12044            }
12045	        var record = new recordType(values, id);
12046	        record.json = n;
12047	        records[records.length] = record;
12048	    }
12049	    return {
12050	        records : records,
12051	        totalRecords : records.length
12052	    };
12053    }
12054});
12055
12056Ext.data.Tree = function(root){
12057   this.nodeHash = {};
12058   
12059   this.root = null;
12060   if(root){
12061       this.setRootNode(root);
12062   }
12063   this.addEvents(
12064       
12065       "append",
12066       
12067       "remove",
12068       
12069       "move",
12070       
12071       "insert",
12072       
12073       "beforeappend",
12074       
12075       "beforeremove",
12076       
12077       "beforemove",
12078       
12079       "beforeinsert"
12080   );
12081
12082    Ext.data.Tree.superclass.constructor.call(this);
12083};
12084
12085Ext.extend(Ext.data.Tree, Ext.util.Observable, {
12086    
12087    pathSeparator: "/",
12088
12089    // private
12090    proxyNodeEvent : function(){
12091        return this.fireEvent.apply(this, arguments);
12092    },
12093
12094    
12095    getRootNode : function(){
12096        return this.root;
12097    },
12098
12099    
12100    setRootNode : function(node){
12101        this.root = node;
12102        node.ownerTree = this;
12103        node.isRoot = true;
12104        this.registerNode(node);
12105        return node;
12106    },
12107
12108    
12109    getNodeById : function(id){
12110        return this.nodeHash[id];
12111    },
12112
12113    // private
12114    registerNode : function(node){
12115        this.nodeHash[node.id] = node;
12116    },
12117
12118    // private
12119    unregisterNode : function(node){
12120        delete this.nodeHash[node.id];
12121    },
12122
12123    toString : function(){
12124        return "[Tree"+(this.id?" "+this.id:"")+"]";
12125    }
12126});
12127
12128
12129Ext.data.Node = function(attributes){
12130    
12131    this.attributes = attributes || {};
12132    this.leaf = this.attributes.leaf;
12133    
12134    this.id = this.attributes.id;
12135    if(!this.id){
12136        this.id = Ext.id(null, "ynode-");
12137        this.attributes.id = this.id;
12138    }
12139    
12140    this.childNodes = [];
12141    if(!this.childNodes.indexOf){ // indexOf is a must
12142        this.childNodes.indexOf = function(o){
12143            for(var i = 0, len = this.length; i < len; i++){
12144                if(this[i] == o) return i;
12145            }
12146            return -1;
12147        };
12148    }
12149    
12150    this.parentNode = null;
12151    
12152    this.firstChild = null;
12153    
12154    this.lastChild = null;
12155    
12156    this.previousSibling = null;
12157    
12158    this.nextSibling = null;
12159
12160    this.addEvents({
12161       
12162       "append" : true,
12163       
12164       "remove" : true,
12165       
12166       "move" : true,
12167       
12168       "insert" : true,
12169       
12170       "beforeappend" : true,
12171       
12172       "beforeremove" : true,
12173       
12174       "beforemove" : true,
12175       
12176       "beforeinsert" : true
12177   });
12178    this.listeners = this.attributes.listeners;
12179    Ext.data.Node.superclass.constructor.call(this);
12180};
12181
12182Ext.extend(Ext.data.Node, Ext.util.Observable, {
12183    // private
12184    fireEvent : function(evtName){
12185        // first do standard event for this node
12186        if(Ext.data.Node.superclass.fireEvent.apply(this, arguments) === false){
12187            return false;
12188        }
12189        // then bubble it up to the tree if the event wasn't cancelled
12190        var ot = this.getOwnerTree();
12191        if(ot){
12192            if(ot.proxyNodeEvent.apply(ot, arguments) === false){
12193                return false;
12194            }
12195        }
12196        return true;
12197    },
12198
12199    
12200    isLeaf : function(){
12201        return this.leaf === true;
12202    },
12203
12204    // private
12205    setFirstChild : function(node){
12206        this.firstChild = node;
12207    },
12208
12209    //private
12210    setLastChild : function(node){
12211        this.lastChild = node;
12212    },
12213
12214
12215    
12216    isLast : function(){
12217       return (!this.parentNode ? true : this.parentNode.lastChild == this);
12218    },
12219
12220    
12221    isFirst : function(){
12222       return (!this.parentNode ? true : this.parentNode.firstChild == this);
12223    },
12224
12225    
12226    hasChildNodes : function(){
12227        return !this.isLeaf() && this.childNodes.length > 0;
12228    },
12229    
12230    
12231    isExpandable : function(){
12232        return this.attributes.expandable || this.hasChildNodes();
12233    },
12234
12235    
12236    appendChild : function(node){
12237        var multi = false;
12238        if(Ext.isArray(node)){
12239            multi = node;
12240        }else if(arguments.length > 1){
12241            multi = arguments;
12242        }
12243        // if passed an array or multiple args do them one by one
12244        if(multi){
12245            for(var i = 0, len = multi.length; i < len; i++) {
12246            	this.appendChild(multi[i]);
12247            }
12248        }else{
12249            if(this.fireEvent("beforeappend", this.ownerTree, this, node) === false){
12250                return false;
12251            }
12252            var index = this.childNodes.length;
12253            var oldParent = node.parentNode;
12254            // it's a move, make sure we move it cleanly
12255            if(oldParent){
12256                if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index) === false){
12257                    return false;
12258                }
12259                oldParent.removeChild(node);
12260            }
12261            index = this.childNodes.length;
12262            if(index == 0){
12263                this.setFirstChild(node);
12264            }
12265            this.childNodes.push(node);
12266            node.parentNode = this;
12267            var ps = this.childNodes[index-1];
12268            if(ps){
12269                node.previousSibling = ps;
12270                ps.nextSibling = node;
12271            }else{
12272                node.previousSibling = null;
12273            }
12274            node.nextSibling = null;
12275            this.setLastChild(node);
12276            node.setOwnerTree(this.getOwnerTree());
12277            this.fireEvent("append", this.ownerTree, this, node, index);
12278            if(oldParent){
12279                node.fireEvent("move", this.ownerTree, node, oldParent, this, index);
12280            }
12281            return node;
12282        }
12283    },
12284
12285    
12286    removeChild : function(node){
12287        var index = this.childNodes.indexOf(node);
12288        if(index == -1){
12289            return false;
12290        }
12291        if(this.fireEvent("beforeremove", this.ownerTree, this, node) === false){
12292            return false;
12293        }
12294
12295        // remove it from childNodes collection
12296        this.childNodes.splice(index, 1);
12297
12298        // update siblings
12299        if(node.previousSibling){
12300            node.previousSibling.nextSibling = node.nextSibling;
12301        }
12302        if(node.nextSibling){
12303            node.nextSibling.previousSibling = node.previousSibling;
12304        }
12305
12306        // update child refs
12307        if(this.firstChild == node){
12308            this.setFirstChild(node.nextSibling);
12309        }
12310        if(this.lastChild == node){
12311            this.setLastChild(node.previousSibling);
12312        }
12313
12314        node.setOwnerTree(null);
12315        // clear any references from the node
12316        node.parentNode = null;
12317        node.previousSibling = null;
12318        node.nextSibling = null;
12319        this.fireEvent("remove", this.ownerTree, this, node);
12320        return node;
12321    },
12322
12323    
12324    insertBefore : function(node, refNode){
12325        if(!refNode){ // like standard Dom, refNode can be null for append
12326            return this.appendChild(node);
12327        }
12328        // nothing to do
12329        if(node == refNode){
12330            return false;
12331        }
12332
12333        if(this.fireEvent("beforeinsert", this.ownerTree, this, node, refNode) === false){
12334            return false;
12335        }
12336        var index = this.childNodes.indexOf(refNode);
12337        var oldParent = node.parentNode;
12338        var refIndex = index;
12339
12340        // when moving internally, indexes will change after remove
12341        if(oldParent == this && this.childNodes.indexOf(node) < index){
12342            refIndex--;
12343        }
12344
12345        // it's a move, make sure we move it cleanly
12346        if(oldParent){
12347            if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index, refNode) === false){
12348                return false;
12349            }
12350            oldParent.removeChild(node);
12351        }
12352        if(refIndex == 0){
12353            this.setFirstChild(node);
12354        }
12355        this.childNodes.splice(refIndex, 0, node);
12356        node.parentNode = this;
12357        var ps = this.childNodes[refIndex-1];
12358        if(ps){
12359            node.previousSibling = ps;
12360            ps.nextSibling = node;
12361        }else{
12362            node.previousSibling = null;
12363        }
12364        node.nextSibling = refNode;
12365        refNode.previousSibling = node;
12366        node.setOwnerTree(this.getOwnerTree());
12367        this.fireEvent("insert", this.ownerTree, this, node, refNode);
12368        if(oldParent){
12369            node.fireEvent("move", this.ownerTree, node, oldParent, this, refIndex, refNo
12369de);
12370        }
12371        return node;
12372    },
12373
12374    
12375    remove : function(){
12376        this.parentNode.removeChild(this);
12377        return this;
12378    },
12379
12380    
12381    item : function(index){
12382        return this.childNodes[index];
12383    },
12384
12385    
12386    replaceChild : function(newChild, oldChild){
12387        var s = oldChild ? oldChild.nextSibling : null;
12388        this.removeChild(oldChild);
12389        this.insertBefore(newChild, s);
12390        return oldChild;
12391    },
12392
12393    
12394    indexOf : function(child){
12395        return this.childNodes.indexOf(child);
12396    },
12397
12398    
12399    getOwnerTree : function(){
12400        // if it doesn't have one, look for one
12401        if(!this.ownerTree){
12402            var p = this;
12403            while(p){
12404                if(p.ownerTree){
12405                    this.ownerTree = p.ownerTree;
12406                    break;
12407                }
12408                p = p.parentNode;
12409            }
12410        }
12411        return this.ownerTree;
12412    },
12413
12414    
12415    getDepth : function(){
12416        var depth = 0;
12417        var p = this;
12418        while(p.parentNode){
12419            ++depth;
12420            p = p.parentNode;
12421        }
12422        return depth;
12423    },
12424
12425    // private
12426    setOwnerTree : function(tree){
12427        // if it's move, we need to update everyone
12428        if(tree != this.ownerTree){
12429            if(this.ownerTree){
12430                this.ownerTree.unregisterNode(this);
12431            }
12432            this.ownerTree = tree;
12433            var cs = this.childNodes;
12434            for(var i = 0, len = cs.length; i < len; i++) {
12435            	cs[i].setOwnerTree(tree);
12436            }
12437            if(tree){
12438                tree.registerNode(this);
12439            }
12440        }
12441    },
12442
12443    
12444    getPath : function(attr){
12445        attr = attr || "id";
12446        var p = this.parentNode;
12447        var b = [this.attributes[attr]];
12448        while(p){
12449            b.unshift(p.attributes[attr]);
12450            p = p.parentNode;
12451        }
12452        var sep = this.getOwnerTree().pathSeparator;
12453        return sep + b.join(sep);
12454    },
12455
12456    
12457    bubble : function(fn, scope, args){
12458        var p = this;
12459        while(p){
12460            if(fn.apply(scope || p, args || [p]) === false){
12461                break;
12462            }
12463            p = p.parentNode;
12464        }
12465    },
12466
12467    
12468    cascade : function(fn, scope, args){
12469        if(fn.apply(scope || this, args || [this]) !== false){
12470            var cs = this.childNodes;
12471            for(var i = 0, len = cs.length; i < len; i++) {
12472            	cs[i].cascade(fn, scope, args);
12473            }
12474        }
12475    },
12476
12477    
12478    eachChild : function(fn, scope, args){
12479        var cs = this.childNodes;
12480        for(var i = 0, len = cs.length; i < len; i++) {
12481        	if(fn.apply(scope || this, args || [cs[i]]) === false){
12482        	    break;
12483        	}
12484        }
12485    },
12486
12487    
12488    findChild : function(attribute, value){
12489        var cs = this.childNodes;
12490        for(var i = 0, len = cs.length; i < len; i++) {
12491        	if(cs[i].attributes[attribute] == value){
12492        	    return cs[i];
12493        	}
12494        }
12495        return null;
12496    },
12497
12498    
12499    findChildBy : function(fn, scope){
12500        var cs = this.childNodes;
12501        for(var i = 0, len = cs.length; i < len; i++) {
12502        	if(fn.call(scope||cs[i], cs[i]) === true){
12503        	    return cs[i];
12504        	}
12505        }
12506        return null;
12507    },
12508
12509    
12510    sort : function(fn, scope){
12511        var cs = this.childNodes;
12512        var len = cs.length;
12513        if(len > 0){
12514            var sortFn = scope ? function(){fn.apply(scope, arguments);} : fn;
12515            cs.sort(sortFn);
12516            for(var i = 0; i < len; i++){
12517                var n = cs[i];
12518                n.previousSibling = cs[i-1];
12519                n.nextSibling = cs[i+1];
12520                if(i == 0){
12521                    this.setFirstChild(n);
12522                }
12523                if(i == len-1){
12524                    this.setLastChild(n);
12525                }
12526            }
12527        }
12528    },
12529
12530    
12531    contains : function(node){
12532        return node.isAncestor(this);
12533    },
12534
12535    
12536    isAncestor : function(node){
12537        var p = this.parentNode;
12538        while(p){
12539            if(p == node){
12540                return true;
12541            }
12542            p = p.parentNode;
12543        }
12544        return false;
12545    },
12546
12547    toString : function(){
12548        return "[Node"+(this.id?" "+this.id:"")+"]";
12549    }
12550});
12551
12552Ext.data.GroupingStore = Ext.extend(Ext.data.Store, {
12553    
12554    
12555    remoteGroup : false,
12556    
12557    groupOnSort:false,
12558
12559    
12560    clearGrouping : function(){
12561        this.groupField = false;
12562        if(this.remoteGroup){
12563            if(this.baseParams){
12564                delete this.baseParams.groupBy;
12565            }
12566            this.reload();
12567        }else{
12568            this.applySort();
12569            this.fireEvent('datachanged', this);
12570        }
12571    },
12572
12573    
12574    groupBy : function(field, forceRegroup){
12575        if(this.groupField == field && !forceRegroup){
12576            return; // already grouped by this field
12577        }
12578        this.groupField = field;
12579        if(this.remoteGroup){
12580            if(!this.baseParams){
12581                this.baseParams = {};
12582            }
12583            this.baseParams['groupBy'] = field;
12584        }
12585        if(this.groupOnSort){
12586            this.sort(field);
12587            return;
12588        }
12589        if(this.remoteGroup){
12590            this.reload();
12591        }else{
12592            var si = this.sortInfo || {};
12593            if(si.field != field){
12594                this.applySort();
12595            }else{
12596                this.sortData(field);
12597            }
12598            this.fireEvent('datachanged', this);
12599        }
12600    },
12601
12602    // private
12603    applySort : function(){
12604        Ext.data.GroupingStore.superclass.applySort.call(this);
12605        if(!this.groupOnSort && !this.remoteGroup){
12606            var gs = this.getGroupState();
12607            if(gs && gs != this.sortInfo.field){
12608                this.sortData(this.groupField);
12609            }
12610        }
12611    },
12612
12613    // private
12614    applyGrouping : function(alwaysFireChange){
12615        if(this.groupField !== false){
12616            this.groupBy(this.groupField, true);
12617            return true;
12618        }else{
12619            if(alwaysFireChange === true){
12620                this.fireEvent('datachanged', this);
12621            }
12622            return false;
12623        }
12624    },
12625
12626    // private
12627    getGroupState : function(){
12628        return this.groupOnSort && this.groupField !== false ?
12629               (this.sortInfo ? this.sortInfo.field : undefined) : this.groupField;
12630    }
12631});
12632
12633Ext.ComponentMgr = function(){
12634    var all = new Ext.util.MixedCollection();
12635    var types = {};
12636
12637    return {
12638        
12639        register : function(c){
12640            all.add(c);
12641        },
12642
12643        
12644        unregister : function(c){
12645            all.remove(c);
12646        },
12647
12648        
12649        get : function(id){
12650            return all.get(id);
12651        },
12652
12653        
12654        onAvailable : function(id, fn, scope){
12655            all.on("add", function(index, o){
12656                if(o.id == id){
12657                    fn.call(scope || o, o);
12658                    all.un("add", fn, scope);
12659                }
12660            });
12661        },
12662
12663        
12664        all : all,
12665
12666        
12667        registerType : function(xtype, cls){
12668            types[xtype] = cls;
12669            cls.xtype = xtype;
12670        },
12671
12672        
12673        create : function(config, defaultType){
12674            return new types[config.xtype || defaultType](config);
12675        }
12676    };
12677}();
12678
12679
12680Ext.reg = Ext.ComponentMgr.registerType; // this will be called a lot internally, shorthand to keep the bytes down
12681
12682Ext.Component = function(config){
12683    config = config || {};
12684    if(config.initialConfig){
12685        if(config.isAction){           // actions
12686            this.baseAction = config;
12687        }
12688        config = config.initialConfig; // component cloning / action set up
12689    }else if(config.tagName || config.dom || typeof config == "string"){ // element object
12690        config = {applyTo: config, id: config.id || config};
12691    }
12692
12693    
12694    this.initialConfig = config;
12695
12696    Ext.apply(this, config);
12697    this.addEvents(
12698        
12699        'disable',
12700        
12701        'enable',
12702        
12703        'beforeshow',
12704        
12705        'show',
12706        
12707        'beforehide',
12708        
12709        'hide',
12710        
12711        'beforerender',
12712        
12713        'render',
12714        
12715        'beforedestroy',
12716        
12717        'destroy',
12718        
12719        'beforestaterestore',
12720        
12721        'staterestore',
12722        
12723        'beforestatesave',
12724        
12725        'statesave'
12726    );
12727    this.getId();
12728    Ext.ComponentMgr.register(this);
12729    Ext.Component.superclass.constructor.call(this);
12730
12731    if(this.baseAction){
12732        this.baseAction.addComponent(this);
12733    }
12734
12735    this.initComponent();
12736
12737    if(this.plugins){
12738        if(Ext.isArray(this.plugins)){
12739            for(var i = 0, len = this.plugins.length; i < len; i++){
12740                this.plugins[i] = this.initPlugin(this.plugins[i]);
12741            }
12742        }else{
12743            this.plugins = this.initPlugin(this.plugins);
12744        }
12745    }
12746
12747    if(this.stateful !== false){
12748        this.initState(config);
12749    }
12750
12751    if(this.applyTo){
12752        this.applyToMarkup(this.applyTo);
12753        delete this.applyTo;
12754    }else if(this.renderTo){
12755        this.render(this.renderTo);
12756        delete this.renderTo;
12757    }
12758};
12759
12760// private
12761Ext.Component.AUTO_ID = 1000;
12762
12763Ext.extend(Ext.Component, Ext.util.Observable, {
12764    // Configs below are used for all Components when rendered by FormLayout.
12765    
12766    
12767    
12768    
12769    
12770    
12771
12772    
12773    
12774    
12775    
12776    
12777    
12778    
12779    
12780    
12781    
12782    
12783    
12784
12785    
12786    
12787    
12788
12789    
12790    disabledClass : "x-item-disabled",
12791	
12792    allowDomMove : true,
12793	
12794    autoShow : false,
12795    
12796    hideMode: 'display',
12797    
12798    hideParent: false,
12799
12800    
12801    
12802    hidden : false,
12803    
12804    disabled : false,
12805    
12806    rendered : false,
12807
12808    // private
12809    ctype : "Ext.Component",
12810
12811    // private
12812    actionMode : "el",
12813
12814    // private
12815    getActionEl : function(){
12816        return this[this.actionMode];
12817    },
12818
12819    initPlugin : function(p){
12820        p.init(this);
12821        return p;
12822    },
12823
12824    
12825    initComponent : Ext.emptyFn,
12826
12827    
12828    render : function(container, position){
12829        if(!this.rendered && this.fireEvent("beforerender", this) !== false){
12830            if(!container && this.el){
12831                this.el = Ext.get(this.el);
12832                container = this.el.dom.parentNode;
12833                this.allowDomMove = false;
12834            }
12835            this.container = Ext.get(container);
12836            if(this.ctCls){
12837                this.container.addClass(this.ctCls);
12838            }
12839            this.rendered = true;
12840            if(position !== undefined){
12841                if(typeof position == 'number'){
12842                    position = this.container.dom.childNodes[position];
12843                }else{
12844                    position = Ext.getDom(position);
12845                }
12846            }
12847            this.onRender(this.container, position || null);
12848            if(this.autoShow){
12849                this.el.removeClass(['x-hidden','x-hide-' + this.hideMode]);
12850            }
12851            if(this.cls){
12852                this.el.addClass(this.cls);
12853                delete this.cls;
12854            }
12855            if(this.style){
12856                this.el.applyStyles(this.style);
12857                delete this.style;
12858            }
12859            if(this.overCls){
12860                this.el.addClassOnOver(this.overCls);
12861            }
12862            this.fireEvent("render", this);
12863            this.afterRender(this.container);
12864            if(this.hidden){
12865                this.hide();
12866            }
12867            if(this.disabled){
12868                this.disable();
12869            }
12870
12871            if(this.stateful !== false){
12872                this.initStateEvents();
12873            }
12874        }
12875        return this;
12876    },
12877
12878    // private
12879    initState : function(config){
12880        if(Ext.state.Manager){
12881            var id = this.getStateId();
12882            if(id){
12883                var state = Ext.state.Manager.get(id);
12884                if(state){
12885                    if(this.fireEvent('beforestaterestore', this, state) !== false){
12886                        this.applyState(state);
12887                        this.fireEvent('staterestore', this, state);
12888                    }
12889                }
12890            }
12891        }
12892    },
12893
12894    // private
12895    getStateId : function(){
12896        return this.stateId || ((this.id.indexOf('ext-comp-') == 0 || this.id.indexOf('ext-gen') == 0) ? null : this.id);
12897    },
12898
12899    // private
12900    initStateEvents : function(){
12901        if(this.stateEvents){
12902            for(var i = 0, e; e = this.stateEvents[i]; i++){
12903                this.on(e, this.saveState, this, {delay:100});
12904            }
12905        }
12906    },
12907
12908    // private
12909    applyState : function(state, config){
12910        if(state){
12911            Ext.apply(this, state);
12912        }
12913    },
12914
12915    // private
12916    getState : function(){
12917        return null;
12918    },
12919
12920    // private
12921    saveState : function(){
12922        if(Ext.state.Manager){
12923            var id = this.getStateId();
12924            if(id){
12925                var state = this.getState();
12926                if(this.fireEvent('beforestatesave', this, state) !== false){
12927                    Ext.state.Manager.set(id, state);
12928                    this.fireEvent('statesave', this, state);
12929                }
12930            }
12931        }
12932    },
12933
12934    
12935    applyToMarkup : function(el){
12936        this.allowDomMove = false;
12937        this.el = Ext.get(el);
12938        this.render(this.el.dom.parentNode);
12939    },
12940
12941    
12942    addClass : function(cls){
12943        if(this.el){
12944            this.el.addClass(cls);
12945        }else{
12946            this.cls = this.cls ? this.cls + ' ' + cls : cls;
12947        }
12948    },
12949
12950    
12951    removeClass : function(cls){
12952        if(this.el){
12953            this.el.removeClass(cls);
12954        }else if(this.cls){
12955            this.cls = this.cls.split(' ').remove(cls).join(' ');
12956        }
12957    },
12958
12959    // private
12960    // default function is not really useful
12961    onRender : function(ct, position){
12962        if(this.autoEl){
12963            if(typeof this.autoEl == 'string'){
12964                this.el = document.createElement(this.autoEl);
12965            }else{
12966                var div = document.createElement('div');
12967                Ext.DomHelper.overwrite(div, this.autoEl);
12968                this.el = div.firstChild;
12969            }
12970            if (!this.el.id) {
12971            	this.el.id = this.getId();
12972            }
12973        }
12974        if(this.el){
12975            this.el = Ext.get(this.el);
12976            if(this.allowDomMove !== false){
12977                ct.dom.insertBefore(this.el.dom, position);
12978            }
12979        }
12980    },
12981
12982    // private
12983    getAutoCreate : function(){
12984        var cfg = typeof this.autoCreate == "object" ?
12985                      this.autoCreate : Ext.apply({}, this.defaultAutoCreate);
12986        if(this.id && !cfg.id){
12987            cfg.id = this.id;
12988        }
12989        return cfg;
12990    },
12991
12992    // private
12993    afterRender : Ext.emptyFn,
12994
12995    
12996    destroy : function(){
12997        if(this.fireEvent("beforedestroy", this) !== false){
12998            this.beforeDestroy();
12999            if(this.rendered){
13000                this.el.removeAllListeners();
13001                this.el.remove();
13002                if(this.actionMode == "container"){
13003                    this.container.remove();
13004                }
13005            }
13006            this.onDestroy();
13007            Ext.ComponentMgr.unregister(this);
13008            this.fireEvent("destroy", this);
13009            this.purgeListeners();
13010        }
13011    },
13012
13013	// private
13014    beforeDestroy : Ext.emptyFn,
13015
13016	// private
13017    onDestroy  : Ext.emptyFn,
13018
13019    
13020    getEl : function(){
13021        return this.el;
13022    },
13023
13024    
13025    getId : function(){
13026        return this.id || (this.id = "ext-comp-" + (++Ext.Component.AUTO_ID));
13027    },
13028
13029    
13030    getItemId : function(){
13031        return this.itemId || this.getId();
13032    },
13033
13034    
13035    focus : function(selectText, delay){
13036        if(delay){
13037            this.focus.defer(typeof delay == 'number' ? delay : 10, this, [selectText, false]);
13038            return;
13039        }
13040        if(this.rendered){
13041            this.el.focus();
13042            if(selectText === true){
13043                this.el.dom.select();
13044            }
13045        }
13046        return this;
13047    },
13048
13049    // private
13050    blur : function(){
13051        if(this.rendered){
13052            this.el.blur();
13053        }
13054        return this;
13055    },
13056
13057    
13058    disable : function(){
13059        if(this.rendered){
13060            this.onDisable();
13061        }
13062        this.disabled = true;
13063        this.fireEvent("disable", this);
13064        return this;
13065    },
13066
13067	// private
13068    onDisable : function(){
13069        this.getActionEl().addClass(this.disabledClass);
13070        this.el.dom.disabled = true;
13071    },
13072
13073    
13074    enable : function(){
13075        if(this.rendered){
13076            this.onEnable();
13077        }
13078        this.disabled = false;
13079        this.fireEvent("enable", this);
13080        return this;
13081    },
13082
13083	// private
13084    onEnable : function(){
13085        this.getActionEl().removeClass(this.disabledClass);
13086        this.el.dom.disabled = false;
13087    },
13088
13089    
13090    setDisabled : function(disabled){
13091        this[disabled ? "disable" : "enable"]();
13092    },
13093
13094    
13095    show: function(){
13096        if(this.fireEvent("beforeshow", this) !== false){
13097            this.hidden = false;
13098            if(this.autoRender){
13099                this.render(typeof this.autoRender == 'boolean' ? Ext.getBody() : this.autoRender);
13100            }
13101            if(this.rendered){
13102                this.onShow();
13103            }
13104            this.fireEvent("show", this);
13105        }
13106        return this;
13107    },
13108
13109    // private
13110    onShow : function(){
13111        if(this.hideParent){
13112            this.container.removeClass('x-hide-' + this.hideMode);
13113        }else{
13114            this.getActionEl().removeClass('x-hide-' + this.hideMode);
13115        }
13116
13117    },
13118
13119    
13120    hide: function(){
13121        if(this.fireEvent("beforehide", this) !== false){
13122            this.hidden = true;
13123            if(this.rendered){
13124                this.onHide();
13125            }
13126            this.fireEvent("hide", this);
13127        }
13128        return this;
13129    },
13130
13131    // private
13132    onHide : function(){
13133        if(this.hideParent){
13134            this.container.addClass('x-hide-' + this.hideMode);
13135        }else{
13136            this.getActionEl().addClass('x-hide-' + this.hideMode);
13137        }
13138    },
13139
13140    
13141    setVisible: function(visible){
13142        if(visible) {
13143            this.show();
13144        }else{
13145            this.hide();
13146        }
13147        return this;
13148    },
13149
13150    
13151    isVisible : function(){
13152        return this.rendered && this.getActionEl().isVisible();
13153    },
13154
13155    
13156    cloneConfig : function(overrides){
13157        overrides = overrides || {};
13158        var id = overrides.id || Ext.id();
13159        var cfg = Ext.applyIf(overrides, this.initialConfig);
13160        cfg.id = id; // prevent dup id
13161        return new this.constructor(cfg);
13162    },
13163
13164    
13165    getXType : function(){
13166        return this.constructor.xtype;
13167    },
13168
13169    
13170    isXType : function(xtype, shallow){
13171        //assume a string by default
13172        if (typeof xtype == 'function'){
13173            xtype = xtype.xtype; //handle being passed the class, eg. Ext.Component
13174        }else if (typeof xtype == 'object'){
13175            xtype = xtype.constructor.xtype; //handle being passed an instance
13176        }
13177            
13178        return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1 : this.constructor.xtype == xtype;
13179    },
13180
13181    
13182    getXTypes : function(){
13183        var tc = this.constructor;
13184        if(!tc.xtypes){
13185            var c = [], sc = this;
13186            while(sc && sc.constructor.xtype){
13187                c.unshift(sc.constructor.xtype);
13188                sc = sc.constructor.superclass;
13189            }
13190            tc.xtypeChain = c;
13191            tc.xtypes = c.join('/');
13192        }
13193        return tc.xtypes;
13194    },
13195
13196    
13197    findParentBy: function(fn) {
13198        for (var p = this.ownerCt; (p != null) && !fn(p, this); p = p.ownerCt);
13199        return p || null;
13200    },
13201
13202    
13203    findParentByType: function(xtype) {
13204        return typeof xtype == 'function' ?
13205            this.findParentBy(function(p){
13206                return p.constructor === xtype;
13207            }) :
13208            this.findParentBy(function(p){
13209                return p.constructor.xtype === xtype;
13210            });
13211    },
13212
13213    // internal function for auto removal of assigned event handlers on destruction
13214    mon : function(item, ename, fn, scope, opt){
13215        if(!this.mons){
13216            this.mons = [];
13217            this.on('beforedestroy', function(){
13218                for(var i= 0, len = this.mons.length; i < len; i++){
13219                    var m = this.mons[i];
13220                    m.item.un(m.ename, m.fn, m.scope);
13221                }
13222            }, this);
13223        }
13224        this.mons.push({
13225            item: item, ename: ename, fn: fn, scope: scope
13226        });
13227        item.on(ename, fn, scope, opt);
13228    }
13229});
13230
13231Ext.reg('component', Ext.Component);
13232
13233
13234Ext.Action = function(config){
13235    this.initialConfig = config;
13236    this.items = [];
13237}
13238
13239Ext.Action.prototype = {
13240    
13241    
13242    
13243    
13244    
13245    
13246
13247    // private
13248    isAction : true,
13249
13250    
13251    setText : function(text){
13252        this.initialConfig.text = text;
13253        this.callEach('setText', [text]);
13254    },
13255
13256    
13257    getText : function(){
13258        return this.initialConfig.text;
13259    },
13260
13261    
13262    setIconClass : function(cls){
13263        this.initialConfig.iconCls = cls;
13264        this.callEach('setIconClass', [cls]);
13265    },
13266
13267    
13268    getIconClass : function(){
13269        return this.initialConfig.iconCls;
13270    },
13271
13272    
13273    setDisabled : function(v){
13274        this.initialConfig.disabled = v;
13275        this.callEach('setDisabled', [v]);
13276    },
13277
13278    
13279    enable : function(){
13280        this.setDisabled(false);
13281    },
13282
13283    
13284    disable : function(){
13285        this.setDisabled(true);
13286    },
13287
13288    
13289    isDisabled : function(){
13290        return this.initialConfig.disabled;
13291    },
13292
13293    
13294    setHidden : function(v){
13295        this.initialConfig.hidden = v;
13296        this.callEach('setVisible', [!v]);
13297    },
13298
13299    
13300    show : function(){
13301        this.setHidden(false);
13302    },
13303
13304    
13305    hide : function(){
13306        this.setHidden(true);
13307    },
13308
13309    
13310    isHidden : function(){
13311        return this.initialConfig.hidden;
13312    },
13313
13314    
13315    setHandler : function(fn, scope){
13316        this.initialConfig.handler = fn;
13317        this.initialConfig.scope = scope;
13318        this.callEach('setHandler', [fn, scope]);
13319    },
13320
13321    
13322    each : function(fn, scope){
13323        Ext.each(this.items, fn, scope);
13324    },
13325
13326    // private
13327    callEach : function(fnName, args){
13328        var cs = this.items;
13329        for(var i = 0, len = cs.length; i < len; i++){
13330            cs[i][fnName].apply(cs[i], args);
13331        }
13332    },
13333
13334    // private
13335    addComponent : function(comp){
13336        this.items.push(comp);
13337        comp.on('destroy', this.removeComponent, this);
13338    },
13339
13340    // private
13341    removeComponent : function(comp){
13342        this.items.remove(comp);
13343    },
13344
13345    
13346    execute : function(){
13347        this.initialConfig.handler.apply(this.initialConfig.scope || window, arguments);
13348    }
13349};
13350
13351(function(){
13352Ext.Layer = function(config, existingEl){
13353    config = config || {};
13354    var dh = Ext.DomHelper;
13355    var cp = config.parentEl, pel = cp ? Ext.getDom(cp) : document.body;
13356    if(existingEl){
13357        this.dom = Ext.getDom(existingEl);
13358    }
13359    if(!this.dom){
13360        var o = config.dh || {tag: "div", cls: "x-layer"};
13361        this.dom = dh.append(pel, o);
13362    }
13363    if(config.cls){
13364        this.addClass(config.cls);
13365    }
13366    this.constrain = config.constrain !== false;
13367    this.visibilityMode = Ext.Element.VISIBILITY;
13368    if(config.id){
13369        this.id = this.dom.id = config.id;
13370    }else{
13371        this.id = Ext.id(this.dom);
13372    }
13373    this.zindex = config.zindex || this.getZIndex();
13374    this.position("absolute", this.zindex);
13375    if(config.shadow){
13376        this.shadowOffset = config.shadowOffset || 4;
13377        this.shadow = new Ext.Shadow({
13378            offset : this.shadowOffset,
13379            mode : config.shadow
13380        });
13381    }else{
13382        this.shadowOffset = 0;
13383    }
13384    this.useShim = config.shim !== false && Ext.useShims;
13385    this.useDisplay = config.useDisplay;
13386    this.hide();
13387};
13388
13389var supr = Ext.Element.prototype;
13390
13391// shims are shared among layer to keep from having 100 iframes
13392var shims = [];
13393
13394Ext.extend(Ext.Layer, Ext.Element, {
13395
13396    getZIndex : function(){
13397        return this.zindex || parseInt(this.getStyle("z-index"), 10) || 11000;
13398    },
13399
13400    getShim : function(){
13401        if(!this.useShim){
13402            return null;
13403        }
13404        if(this.shim){
13405            return this.shim;
13406        }
13407        var shim = shims.shift();
13408        if(!shim){
13409            shim = this.createShim();
13410            shim.enableDisplayMode('block');
13411            shim.dom.style.display = 'none';
13412            shim.dom.style.visibility = 'visible';
13413        }
13414        var pn = this.dom.parentNode;
13415        if(shim.dom.parentNode != pn){
13416            pn.insertBefore(shim.dom, this.dom);
13417        }
13418        shim.setStyle('z-index', this.getZIndex()-2);
13419        this.shim = shim;
13420        return shim;
13421    },
13422
13423    hideShim : function(){
13424        if(this.shim){
13425            this.shim.setDisplayed(false);
13426            shims.push(this.shim);
13427            delete this.shim;
13428        }
13429    },
13430
13431    disableShadow : function(){
13432        if(this.shadow){
13433            this.shadowDisabled = true;
13434            this.shadow.hide();
13435            this.lastShadowOffset = this.shadowOffset;
13436            this.shadowOffset = 0;
13437        }
13438    },
13439
13440    enableShadow : function(show){
13441        if(this.shadow){
13442            this.shadowDisabled = false;
13443            this.shadowOffset = this.lastShadowOffset;
13444            delete this.lastShadowOffset;
13445            if(show){
13446                this.sync(true);
13447            }
13448        }
13449    },
13450
13451    // private
13452    // this code can execute repeatedly in milliseconds (i.e. during a drag) so
13453    // code size was sacrificed for effeciency (e.g. no getBox/setBox, no XY calls)
13454    sync : function(doShow){
13455        var sw = this.shadow;
13456        if(!this.updating && this.isVisible() && (sw || this.useShim)){
13457            var sh = this.getShim();
13458
13459            var w = this.getWidth(),
13460                h = this.getHeight();
13461
13462            var l = this.getLeft(true),
13463                t = this.getTop(true);
13464
13465            if(sw && !this.shadowDisabled){
13466                if(doShow && !sw.isVisible()){
13467                    sw.show(this);
13468                }else{
13469                    sw.realign(l, t, w, h);
13470                }
13471                if(sh){
13472                    if(doShow){
13473                       sh.show();
13474                    }
13475                    // fit the shim behind the shadow, so it is shimmed too
13476                    var a = sw.adjusts, s = sh.dom.style;
13477                    s.left = (Math.min(l, l+a.l))+"px";
13478                    s.top = (Math.min(t, t+a.t))+"px";
13479                    s.width = (w+a.w)+"px";
13480                    s.height = (h+a.h)+"px";
13481                }
13482            }else if(sh){
13483                if(doShow){
13484                   sh.show();
13485                }
13486                sh.setSize(w, h);
13487                sh.setLeftTop(l, t);
13488            }
13489
13490        }
13491    },
13492
13493    // private
13494    destroy : function(){
13495        this.hideShim();
13496        if(this.shadow){
13497            this.shadow.hide();
13498        }
13499        this.removeAllListeners();
13500        Ext.removeNode(this.dom);
13501        Ext.Element.uncache(this.id);
13502    },
13503
13504    remove : function(){
13505        this.destroy();
13506    },
13507
13508    // private
13509    beginUpdate : function(){
13510        this.updating = true;
13511    },
13512
13513    // private
13514    endUpdate : function(){
13515        this.updating = false;
13516        this.sync(true);
13517    },
13518
13519    // private
13520    hideUnders : function(negOffset){
13521        if(this.shadow){
13522            this.shadow.hide();
13523        }
13524        this.hideShim();
13525    },
13526
13527    // private
13528    constrainXY : function(){
13529        if(this.constrain){
13530            var vw = Ext.lib.Dom.getViewWidth(),
13531                vh = Ext.lib.Dom.getViewHeight();
13532            var s = Ext.getDoc().getScroll();
13533
13534            var xy = this.getXY();
13535            var x = xy[0], y = xy[1];
13536            var w = this.dom.offsetWidth+this.shadowOffset, h = this.dom.offsetHeight+this.shadowOffset;
13537            // only move it if it needs it
13538            var moved = false;
13539            // first validate right/bottom
13540            if((x + w) > vw+s.left){
13541                x = vw - w - this.shadowOffset;
13542                moved = true;
13543            }
13544            if((y + h) > vh+s.top){
13545                y = vh - h - this.shadowOffset;
13546                moved = true;
13547            }
13548            // then make sure top/left isn't negative
13549            if(x < s.left){
13550                x = s.left;
13551                moved = true;
13552            }
13553            if(y < s.top){
13554                y = s.top;
13555                moved = true;
13556            }
13557            if(moved){
13558                if(this.avoidY){
13559                    var ay = this.avoidY;
13560                    if(y <= ay && (y+h) >= ay){
13561                        y = ay-h-5;
13562                    }
13563                }
13564                xy = [x, y];
13565                this.storeXY(xy);
13566                supr.setXY.call(this, xy);
13567                this.sync();
13568            }
13569        }
13570    },
13571
13572    isVisible : function(){
13573        return this.visible;
13574    },
13575
13576    // private
13577    showAction : function(){
13578        this.visible = true; // track visibility to prevent getStyle calls
13579        if(this.useDisplay === true){
13580            this.setDisplayed("");
13581        }else if(this.lastXY){
13582            supr.setXY.call(this, this.lastXY);
13583        }else if(this.lastLT){
13584            supr.setLeftTop.call(this, this.lastLT[0], this.lastLT[1]);
13585        }
13586    },
13587
13588    // private
13589    hideAction : function(){
13590        this.visible = false;
13591        if(this.useDisplay === true){
13592            this.setDisplayed(false);
13593        }else{
13594            this.setLeftTop(-10000,-10000);
13595        }
13596    },
13597
13598    // overridden Element method
13599    setVisible : function(v, a, d, c, e){
13600        if(v){
13601            this.showAction();
13602        }
13603        if(a && v){
13604            var cb = function(){
13605                this.sync(true);
13606                if(c){
13607                    c();
13608                }
13609            }.createDelegate(this);
13610            supr.setVisible.call(this, true, true, d, cb, e);
13611        }else{
13612            if(!v){
13613                this.hideUnders(true);
13614            }
13615            var cb = c;
13616            if(a){
13617                cb = function(){
13618                    this.hideAction();
13619                    if(c){
13620                        c();
13621                    }
13622                }.createDelegate(this);
13623            }
13624            supr.setVisible.call(this, v, a, d, cb, e);
13625            if(v){
13626                this.sync(true);
13627            }else if(!a){
13628                this.hideAction();
13629            }
13630        }
13631    },
13632
13633    storeXY : function(xy){
13634        delete this.lastLT;
13635        this.lastXY = xy;
13636    },
13637
13638    storeLeftTop : function(left, top){
13639        delete this.lastXY;
13640        this.lastLT = [left, top];
13641    },
13642
13643    // private
13644    beforeFx : function(){
13645        this.beforeAction();
13646        return Ext.Layer.superclass.beforeFx.apply(this, arguments);
13647    },
13648
13649    // private
13650    afterFx : function(){
13651        Ext.Layer.superclass.afterFx.apply(this, arguments);
13652        this.sync(this.isVisible());
13653    },
13654
13655    // private
13656    beforeAction : function(){
13657        if(!this.updating && this.shadow){
13658            this.shadow.hide();
13659        }
13660    },
13661
13662    // overridden Element method
13663    setLeft : function(left){
13664        this.storeLeftTop(left, this.getTop(true));
13665        supr.setLeft.apply(this, arguments);
13666        this.sync();
13667    },
13668
13669    setTop : function(top){
13670        this.storeLeftTop(this.getLeft(true), top);
13671        supr.setTop.apply(this, arguments);
13672        this.sync();
13673    },
13674
13675    setLeftTop : function(left, top){
13676        this.storeLeftTop(left, top);
13677        supr.setLeftTop.apply(this, arguments);
13678        this.sync();
13679    },
13680
13681    setXY : function(xy, a, d, c, e){
13682        this.fixDisplay();
13683        this.beforeAction();
13684        this.storeXY(xy);
13685        var cb = this.createCB(c);
13686        supr.setXY.call(this, xy, a, d, cb, e);
13687        if(!a){
13688            cb();
13689        }
13690    },
13691
13692    // private
13693    createCB : function(c){
13694        var el = this;
13695        return function(){
13696            el.constrainXY();
13697            el.sync(true);
13698            if(c){
13699                c();
13700            }
13701        };
13702    },
13703
13704    // overridden Element method
13705    setX : function(x, a, d, c, e){
13706        this.setXY([x, this.getY()], a, d, c, e);
13707    },
13708
13709    // overridden Element method
13710    setY : function(y, a, d, c, e){
13711        this.setXY([this.getX(), y], a, d, c, e);
13712    },
13713
13714    // overridden Element method
13715    setSize : function(w, h, a, d, c, e){
13716        this.beforeAction();
13717        var cb = this.createCB(c);
13718        supr.setSize.call(this, w, h, a, d, cb, e);
13719        if(!a){
13720            cb();
13721        }
13722    },
13723
13724    // overridden Element method
13725    setWidth : function(w, a, d, c, e){
13726        this.beforeAction();
13727        var cb = this.createCB(c);
13728        supr.setWidth.call(this, w, a, d, cb, e);
13729        if(!a){
13730            cb();
13731        }
13732    },
13733
13734    // overridden Element method
13735    setHeight : function(h, a, d, c, e){
13736        this.beforeAction();
13737        var cb = this.createCB(c);
13738        supr.setHeight.call(this, h, a, d, cb, e);
13739        if(!a){
13740            cb();
13741        }
13742    },
13743
13744    // overridden Element method
13745    setBounds : function(x, y, w, h, a, d, c, e){
13746        this.beforeAction();
13747        var cb = this.createCB(c);
13748        if(!a){
13749            this.storeXY([x, y]);
13750            supr.setXY.call(this, [x, y]);
13751            supr.setSize.call(this, w, h, a, d, cb, e);
13752            cb();
13753        }else{
13754            supr.setBounds.call(this, x, y, w, h, a, d, cb, e);
13755        }
13756        return this;
13757    },
13758
13759    
13760    setZIndex : function(zindex){
13761        this.zindex = zindex;
13762        this.setStyle("z-index", zindex + 2);
13763        if(this.shadow){
13764            this.shadow.setZIndex(zindex + 1);
13765        }
13766        if(this.shim){
13767            this.shim.setStyle("z-index", zindex);
13768        }
13769    }
13770});
13771})();
13772
13773Ext.Shadow = function(config){
13774    Ext.apply(this, config);
13775    if(typeof this.mode != "string"){
13776        this.mode = this.defaultMode;
13777    }
13778    var o = this.offset, a = {h: 0};
13779    var rad = Math.floor(this.offset/2);
13780    switch(this.mode.toLowerCase()){ // all this hideous nonsense calculates the various offsets for shadows
13781        case "drop":
13782            a.w = 0;
13783            a.l = a.t = o;
13784            a.t -= 1;
13785            if(Ext.isIE){
13786                a.l -= this.offset + rad;
13787                a.t -= this.offset + rad;
13788                a.w -= rad;
13789                a.h -= rad;
13790                a.t += 1;
13791            }
13792        break;
13793        case "sides":
13794            a.w = (o*2);
13795            a.l = -o;
13796            a.t = o-1;
13797            if(Ext.isIE){
13798                a.l -= (this.offset - rad);
13799                a.t -= this.offset + rad;
13800                a.l += 1;
13801                a.w -= (this.offset - rad)*2;
13802                a.w -= rad + 1;
13803                a.h -= 1;
13804            }
13805        break;
13806        case "frame":
13807            a.w = a.h = (o*2);
13808            a.l = a.t = -o;
13809            a.t += 1;
13810            a.h -= 2;
13811            if(Ext.isIE){
13812                a.l -= (this.offset - rad);
13813                a.t -= (this.offset - rad);
13814                a.l += 1;
13815                a.w -= (this.offset + rad + 1);
13816                a.h -= (this.offset + rad);
13817                a.h += 1;
13818            }
13819        break;
13820    };
13821
13822    this.adjusts = a;
13823};
13824
13825Ext.Shadow.prototype = {
13826    
13827    
13828    offset: 4,
13829
13830    // private
13831    defaultMode: "drop",
13832
13833    
13834    show : function(target){
13835        target = Ext.get(target);
13836        if(!this.el){
13837            this.el = Ext.Shadow.Pool.pull();
13838            if(this.el.dom.nextSibling != target.dom){
13839                this.el.insertBefore(target);
13840            }
13841        }
13842        this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10)-1);
13843        if(Ext.isIE){
13844            this.el.dom.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius="+(this.offset)+")";
13845        }
13846        this.realign(
13847            target.getLeft(true),
13848            target.getTop(true),
13849            target.getWidth(),
13850            target.getHeight()
13851        );
13852        this.el.dom.style.display = "block";
13853    },
13854
13855    
13856    isVisible : function(){
13857        return this.el ? true : false;  
13858    },
13859
13860    
13861    realign : function(l, t, w, h){
13862        if(!this.el){
13863            return;
13864        }
13865        var a = this.adjusts, d = this.el.dom, s = d.style;
13866        var iea = 0;
13867        s.left = (l+a.l)+"px";
13868        s.top = (t+a.t)+"px";
13869        var sw = (w+a.w), sh = (h+a.h), sws = sw +"px", shs = sh + "px";
13870        if(s.width != sws || s.height != shs){
13871            s.width = sws;
13872            s.height = shs;
13873            if(!Ext.isIE){
13874                var cn = d.childNodes;
13875                var sww = Math.max(0, (sw-12))+"px";
13876                cn[0].childNodes[1].style.width = sww;
13877                cn[1].childNodes[1].style.width = sww;
13878                cn[2].childNodes[1].style.width = sww;
13879                cn[1].style.height = Math.max(0, (sh-12))+"px";
13880            }
13881        }
13882    },
13883
13884    
13885    hide : function(){
13886        if(this.el){
13887            this.el.dom.style.display = "none";
13888            Ext.Shadow.Pool.push(this.el);
13889            delete this.el;
13890        }
13891    },
13892
13893    
13894    setZIndex : function(z){
13895        this.zIndex = z;
13896        if(this.el){
13897            this.el.setStyle("z-index", z);
13898        }
13899    }
13900};
13901
13902// Private utility class that manages the internal Shadow cache
13903Ext.Shadow.Pool = function(){
13904    var p = [];
13905    var markup = Ext.isIE ?
13906                 '<div class="x-ie-shadow"></div>' :
13907                 '<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>';
13908    return {
13909        pull : function(){
13910            var sh = p.shift();
13911            if(!sh){
13912                sh = Ext.get(Ext.DomHelper.insertHtml("beforeBegin", document.body.firstChild, markup));
13913                sh.autoBoxAdjust = false;
13914            }
13915            return sh;
13916        },
13917
13918        push : function(sh){
13919            p.push(sh);
13920        }
13921    };
13922}();
13923
13924Ext.BoxComponent = Ext.extend(Ext.Component, {
13925    
13926    
13927    
13928    
13929    
13930    
13931    
13932    
13933
13934    
13935
13936	// private
13937    initComponent : function(){
13938        Ext.BoxComponent.superclass.initComponent.call(this);
13939        this.addEvents(
13940            
13941            'resize',
13942            
13943            'move'
13944        );
13945    },
13946
13947    // private, set in afterRender to signify that the component has been rendered
13948    boxReady : false,
13949    // private, used to defer height settings to subclasses
13950    deferHeight: false,
13951
13952    
13953    setSize : function(w, h){
13954        // support for standard size objects
13955        if(typeof w == 'object'){
13956            h = w.height;
13957            w = w.width;
13958        }
13959        // not rendered
13960        if(!this.boxReady){
13961            this.width = w;
13962            this.height = h;
13963            return this;
13964        }
13965
13966        // prevent recalcs when not needed
13967        if(this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
13968            return this;
13969        }
13970        this.lastSize = {width: w, height: h};
13971        var adj = this.adjustSize(w, h);
13972        var aw = adj.width, ah = adj.height;
13973        if(aw !== undefined || ah !== undefined){ // this code is nasty but performs better with floaters
13974            var rz = this.getResizeEl();
13975            if(!this.deferHeight && aw !== undefined && ah !== undefined){
13976                rz.setSize(aw, ah);
13977            }else if(!this.deferHeight && ah !== undefined){
13978                rz.setHeight(ah);
13979            }else if(aw !== undefined){
13980                rz.setWidth(aw);
13981            }
13982            this.onResize(aw, ah, w, h);
13983            this.fireEvent('resize', this, aw, ah, w, h);
13984        }
13985        return this;
13986    },
13987
13988    
13989    setWidth : function(width){
13990        return this.setSize(width);
13991    },
13992
13993    
13994    setHeight : function(height){
13995        return this.setSize(undefined, height);
13996    },
13997
13998    
13999    getSize : function(){
14000        return this.el.getSize();
14001    },
14002
14003    
14004    getPosition : function(local){
14005        if(local === true){
14006            return [this.el.getLeft(true), this.el.getTop(true)];
14007        }
14008        return this.xy || this.el.getXY();
14009    },
14010
14011    
14012    getBox : function(local){
14013        var s = this.el.getSize();
14014        if(local === true){
14015            s.x = this.el.getLeft(true);
14016            s.y = this.el.getTop(true);
14017        }else{
14018            var xy = this.xy || this.el.getXY();
14019            s.x = xy[0];
14020            s.y = xy[1];
14021        }
14022        return s;
14023    },
14024
14025    
14026    updateBox : function(box){
14027        this.setSize(box.width, box.height);
14028        this.setPagePosition(box.x, box.y);
14029        return this;
14030    },
14031
14032    // protected
14033    getResizeEl : function(){
14034        return this.resizeEl || this.el;
14035    },
14036
14037    // protected
14038    getPositionEl : function(){
14039        return this.positionEl || this.el;
14040    },
14041
14042    
14043    setPosition : function(x, y){
14044        if(x && typeof x[1] == 'number'){
14045            y = x[1];
14046            x = x[0];
14047        }
14048        this.x = x;
14049        this.y = y;
14050        if(!this.boxReady){
14051            return this;
14052        }
14053        var adj = this.adjustPosition(x, y);
14054        var ax = adj.x, ay = adj.y;
14055
14056        var el = this.getPositionEl();
14057        if(ax !== undefined || ay !== undefined){
14058            if(ax !== undefined && ay !== undefined){
14059                el.setLeftTop(ax, ay);
14060            }else if(ax !== undefined){
14061                el.setLeft(ax);
14062            }else if(ay !== undefined){
14063                el.setTop(ay);
14064            }
14065            this.onPosition(ax, ay);
14066            this.fireEvent('move', this, ax, ay);
14067        }
14068        return this;
14069    },
14070
14071    
14072    setPagePosition : function(x, y){
14073        if(x && typeof x[1] == 'number'){
14074            y = x[1];
14075            x = x[0];
14076        }
14077        this.pageX = x;
14078        this.pageY = y;
14079        if(!this.boxReady){
14080            return;
14081        }
14082        if(x === undefined || y === undefined){ // cannot translate undefined points
14083            return;
14084        }
14085        var p = this.el.translatePoints(x, y);
14086        this.setPosition(p.left, p.top);
14087        return this;
14088    },
14089
14090    // private
14091    onRender : function(ct, position){
14092        Ext.BoxComponent.superclass.onRender.call(this, ct, position);
14093        if(this.resizeEl){
14094            this.resizeEl = Ext.get(this.resizeEl);
14095        }
14096        if(this.positionEl){
14097            this.positionEl = Ext.get(this.positionEl);
14098        }
14099    },
14100
14101    // private
14102    afterRender : function(){
14103        Ext.BoxComponent.superclass.afterRender.call(this);
14104        this.boxReady = true;
14105        this.setSize(this.width, this.height);
14106        if(this.x || this.y){
14107            this.setPosition(this.x, this.y);
14108        }else if(this.pageX || this.pageY){
14109            this.setPagePosition(this.pageX, this.pageY);
14110        }
14111    },
14112
14113    
14114    syncSize : function(){
14115        delete this.lastSize;
14116        this.setSize(this.autoWidth ? undefined : this.el.getWidth(), this.autoHeight ? undefined : this.el.getHeight());
14117        return this;
14118    },
14119
14120    
14121    onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
14122
14123    },
14124
14125    
14126    onPosition : function(x, y){
14127
14128    },
14129
14130    // private
14131    adjustSize : function(w, h){
14132        if(this.autoWidth){
14133            w = 'auto';
14134        }
14135        if(this.autoHeight){
14136            h = 'auto';
14137        }
14138        return {width : w, height: h};
14139    },
14140
14141    // private
14142    adjustPosition : function(x, y){
14143        return {x : x, y: y};
14144    }
14145});
14146Ext.reg('box', Ext.BoxComponent);
14147
14148Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy){
14149    
14150    
14151    this.el = Ext.get(dragElement, true);
14152    this.el.dom.unselectable = "on";
14153    
14154    this.resizingEl = Ext.get(resizingElement, true);
14155
14156    
14157    this.orientation = orientation || Ext.SplitBar.HORIZONTAL;
14158    
14159    
14160    this.minSize = 0;
14161    
14162    
14163    this.maxSize = 2000;
14164    
14165    
14166    this.animate = false;
14167    
14168    
14169    this.useShim = false;
14170    
14171    
14172    this.shim = null;
14173    
14174    if(!existingProxy){
14175        
14176        this.proxy = Ext.SplitBar.createProxy(this.orientation);
14177    }else{
14178        this.proxy = Ext.get(existingProxy).dom;
14179    }
14180    
14181    this.dd = new Ext.dd.DDProxy(this.el.dom.id, "XSplitBars", {dragElId : this.proxy.id});
14182    
14183    
14184    this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);
14185    
14186    
14187    this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);
14188    
14189    
14190    this.dragSpecs = {};
14191    
14192    
14193    this.adapter = new Ext.SplitBar.BasicLayoutAdapter();
14194    this.adapter.init(this);
14195    
14196    if(this.orientation == Ext.SplitBar.HORIZONTAL){
14197        
14198        this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? Ext.SplitBar.LEFT : Ext.SplitBar.RIGHT);
14199        this.el.addClass("x-splitbar-h");
14200    }else{
14201        
14202        this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? Ext.SplitBar.TOP : Ext.SplitBar.BOTTOM);
14203        this.el.addClass("x-splitbar-v");
14204    }
14205    
14206    this.addEvents(
14207        
14208        "resize",
14209        
14210        "moved",
14211        
14212        "beforeresize",
14213
14214        "beforeapply"
14215    );
14216
14217    Ext.SplitBar.superclass.constructor.call(this);
14218};
14219
14220Ext.extend(Ext.SplitBar, Ext.util.Observable, {
14221    onStartProxyDrag : function(x, y){
14222        this.fireEvent("beforeresize", this);
14223        this.overlay =  Ext.DomHelper.append(document.body,  {cls: "x-drag-overlay", html: "&#160;"}, true);
14224        this.overlay.unselectable();
14225        this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
14226        this.overlay.show();
14227        Ext.get(this.proxy).setDisplayed("block");
14228        var size = this.adapter.getElementSize(this);
14229        this.activeMinSize = this.getMinimumSize();
14230        this.activeMaxSize = this.getMaximumSize();
14231        var c1 = size - this.activeMinSize;
14232        var c2 = Math.max(this.activeMaxSize - size, 0);
14233        if(this.orientation == Ext.SplitBar.HORIZONTAL){
14234            this.dd.resetConstraints();
14235            this.dd.setXConstraint(
14236                this.placement == Ext.SplitBar.LEFT ? c1 : c2, 
14237                this.placement == Ext.SplitBar.LEFT ? c2 : c1
14238            );
14239            this.dd.setYConstraint(0, 0);
14240        }else{
14241            this.dd.resetConstraints();
14242            this.dd.setXConstraint(0, 0);
14243            this.dd.setYConstraint(
14244                this.placement == Ext.SplitBar.TOP ? c1 : c2, 
14245                this.placement == Ext.SplitBar.TOP ? c2 : c1
14246            );
14247         }
14248        this.dragSpecs.startSize = size;
14249        this.dragSpecs.startPoint = [x, y];
14250        Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);
14251    },
14252    
14253    
14254    onEndProxyDrag : function(e){
14255        Ext.get(this.proxy).setDisplayed(false);
14256        var endPoint = Ext.lib.Event.getXY(e);
14257        if(this.overlay){
14258            Ext.destroy(this.overlay);
14259            delete this.overlay;
14260        }
14261        var newSize;
14262        if(this.orientation == Ext.SplitBar.HORIZONTAL){
14263            newSize = this.dragSpecs.startSize + 
14264                (this.placement == Ext.SplitBar.LEFT ?
14265                    endPoint[0] - this.dragSpecs.startPoint[0] :
14266                    this.dragSpecs.startPoint[0] - endPoint[0]
14267                );
14268        }else{
14269            newSize = this.dragSpecs.startSize + 
14270                (this.placement == Ext.SplitBar.TOP ?
14271                    endPoint[1] - this.dragSpecs.startPoint[1] :
14272                    this.dragSpecs.startPoint[1] - endPoint[1]
14273                );
14274        }
14275        newSize = Math.min(Math.max(newSize, this.activeMinSize), this.activeMaxSize);
14276        if(newSize != this.dragSpecs.startSize){
14277            if(this.fireEvent('beforeapply', this, newSize) !== false){
14278                this.adapter.setElementSize(this, newSize);
14279                this.fireEvent("moved", this, newSize);
14280                this.fireEvent("resize", this, newSize);
14281            }
14282        }
14283    },
14284    
14285    
14286    getAdapter : function(){
14287        return this.adapter;
14288    },
14289    
14290    
14291    setAdapter : function(adapter){
14292        this.adapter = adapter;
14293        this.adapter.init(this);
14294    },
14295    
14296    
14297    getMinimumSize : function(){
14298        return this.minSize;
14299    },
14300    
14301    
14302    setMinimumSize : function(minSize){
14303        this.minSize = minSize;
14304    },
14305    
14306    
14307    getMaximumSize : function(){
14308        return this.maxSize;
14309    },
14310    
14311    
14312    setMaximumSize : function(maxSize){
14313        this.maxSize = maxSize;
14314    },
14315    
14316    
14317    setCurrentSize : function(size){
14318        var oldAnimate = this.animate;
14319        this.animate = false;
14320        this.adapter.setElementSize(this, size);
14321        this.animate = oldAnimate;
14322    },
14323    
14324    
14325    destroy : function(removeEl){
14326        if(this.shim){
14327            this.shim.remove();
14328        }
14329        this.dd.unreg();
14330        Ext.destroy(Ext.get(this.proxy));
14331        if(removeEl){
14332            this.el.remove();
14333        }
14334    }
14335});
14336
14337
14338Ext.SplitBar.createProxy = function(dir){
14339    var proxy = new Ext.Element(document.createElement("div"));
14340    proxy.unselectable();
14341    var cls = 'x-splitbar-proxy';
14342    proxy.addClass(cls + ' ' + (dir == Ext.SplitBar.HORIZONTAL ? cls +'-h' : cls + '-v'));
14343    document.body.appendChild(proxy.dom);
14344    return proxy.dom;
14345};
14346
14347
14348Ext.SplitBar.BasicLayoutAdapter = function(){
14349};
14350
14351Ext.SplitBar.BasicLayoutAdapter.prototype = {
14352    // do nothing for now
14353    init : function(s){
14354    
14355    },
14356    
14357     getElementSize : function(s){
14358        if(s.orientation == Ext.SplitBar.HORIZONTAL){
14359            return s.resizingEl.getWidth();
14360        }else{
14361            return s.resizingEl.getHeight();
14362        }
14363    },
14364    
14365    
14366    setElementSize : function(s, newSize, onComplete){
14367        if(s.orientation == Ext.SplitBar.HORIZONTAL){
14368            if(!s.animate){
14369                s.resizingEl.setWidth(newSize);
14370                if(onComplete){
14371                    onComplete(s, newSize);
14372                }
14373            }else{
14374                s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');
14375            }
14376        }else{
14377            
14378            if(!s.animate){
14379                s.resizingEl.setHeight(newSize);
14380                if(onComplete){
14381                    onComplete(s, newSize);
14382                }
14383            }else{
14384                s.resizingEl.setHeight(newSize, true, .1, onComplete, 'easeOut');
14385            }
14386        }
14387    }
14388};
14389
14390
14391Ext.SplitBar.AbsoluteLayoutAdapter = function(container){
14392    this.basic = new Ext.SplitBar.BasicLayoutAdapter();
14393    this.container = Ext.get(container);
14394};
14395
14396Ext.SplitBar.AbsoluteLayoutAdapter.prototype = {
14397    init : function(s){
14398        this.basic.init(s);
14399    },
14400    
14401    getElementSize : function(s){
14402        return this.basic.getElementSize(s);
14403    },
14404    
14405    setElementSize : function(s, newSize, onComplete){
14406        this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));
14407    },
14408    
14409    moveSplitter : function(s){
14410        var yes = Ext.SplitBar;
14411        switch(s.placement){
14412            case yes.LEFT:
14413                s.el.setX(s.resizingEl.getRight());
14414                break;
14415            case yes.RIGHT:
14416                s.el.setStyle("right", (this.container.getWidth() - s.resizingEl.getLeft()) + "px");
14417                break;
14418            case yes.TOP:
14419                s.el.setY(s.resizingEl.getBottom());
14420                break;
14421            case yes.BOTTOM:
14422                s.el.setY(s.resizingEl.getTop() - s.el.getHeight());
14423                break;
14424        }
14425    }
14426};
14427
14428
14429Ext.SplitBar.VERTICAL = 1;
14430
14431
14432Ext.SplitBar.HORIZONTAL = 2;
14433
14434
14435Ext.SplitBar.LEFT = 1;
14436
14437
14438Ext.SplitBar.RIGHT = 2;
14439
14440
14441Ext.SplitBar.TOP = 3;
14442
14443
14444Ext.SplitBar.BOTTOM = 4;
14445
14446
14447Ext.Container = Ext.extend(Ext.BoxComponent, {
14448    
14449    
14450    
14451    
14452    
14453    
14454    
14455
14456    
14457    autoDestroy: true,
14458    
14459    
14460    defaultType: 'panel',
14461
14462    // private
14463    initComponent : function(){
14464        Ext.Container.superclass.initComponent.call(this);
14465
14466        this.addEvents(
14467            
14468            'afterlayout',
14469            
14470            'beforeadd',
14471            
14472            'beforeremove',
14473            
14474            'add',
14475            
14476            'remove'
14477        );
14478
14479        
14480        var items = this.items;
14481        if(items){
14482            delete this.items;
14483            if(Ext.isArray(items) && items.length > 0){
14484                this.add.apply(this, items);
14485            }else{
14486                this.add(items);
14487            }
14488        }
14489    },
14490
14491    // private
14492    initItems : function(){
14493        if(!this.items){
14494            this.items = new Ext.util.MixedCollection(false, this.getComponentId);
14495            this.getLayout(); // initialize the layout
14496        }
14497    },
14498
14499    // private
14500    setLayout : function(layout){
14501        if(this.layout && this.layout != layout){
14502            this.layout.setContainer(null);
14503        }
14504        this.initItems();
14505        this.layout = layout;
14506        layout.setContainer(this);
14507    },
14508
14509    // private
14510    render : function(){
14511        Ext.Container.superclass.render.apply(this, arguments);
14512        if(this.layout){
14513            if(typeof this.layout == 'string'){
14514                this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig);
14515            }
14516            this.setLayout(this.layout);
14517
14518            if(this.activeItem !== undefined){
14519                var item = this.activeItem;
14520                delete this.activeItem;
14521                this.layout.setActiveItem(item);
14522                return;
14523            }
14524        }
14525        if(!this.ownerCt){
14526            this.doLayout();
14527        }
14528        if(this.monitorResize === true){
14529            Ext.EventManager.onWindowResize(this.doLayout, this, [false]);
14530        }
14531    },
14532
14533    
14534    getLayoutTarget : function(){
14535        return this.el;
14536    },
14537
14538    // private - used as the key lookup function for the items collection
14539    getComponentId : function(comp){
14540        return comp.itemId || comp.id;
14541    },
14542
14543    
14544    add : function(comp){
14545        if(!this.items){
14546            this.initItems();
14547        }
14548        var a = arguments, len = a.length;
14549        if(len > 1){
14550            for(var i = 0; i < len; i++) {
14551                this.add(a[i]);
14552            }
14553            return;
14554        }
14555        var c = this.lookupComponent(this.applyDefaults(comp));
14556        var pos = this.items.length;
14557        if(this.fireEvent('beforeadd', this, c, pos) !== false && this.onBeforeAdd(c) !== false){
14558            this.items.add(c);
14559            c.ownerCt = this;
14560            this.fireEvent('add', this, c, pos);
14561        }
14562        return c;
14563    },
14564
14565    
14566    insert : function(index, comp){
14567        if(!this.items){
14568            this.initItems();
14569        }
14570        var a = arguments, len = a.length;
14571        if(len > 2){
14572            for(var i = len-1; i >= 1; --i) {
14573                this.insert(index, a[i]);
14574            }
14575            return;
14576        }
14577        var c = this.lookupComponent(this.applyDefaults(comp));
14578
14579        if(c.ownerCt == this && this.items.indexOf(c) < index){
14580            --index;
14581        }
14582
14583        if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
14584            this.items.insert(index, c);
14585            c.ownerCt = this;
14586            this.fireEvent('add', this, c, index);
14587        }
14588        return c;
14589    },
14590
14591    // private
14592    applyDefaults : function(c){
14593        if(this.defaults){
14594            if(typeof c == 'string'){
14595                c = Ext.ComponentMgr.get(c);
14596                Ext.apply(c, this.defaults);
14597            }else if(!c.events){
14598                Ext.applyIf(c, this.defaults);
14599            }else{
14600                Ext.apply(c, this.defaults);
14601            }
14602        }
14603        return c;
14604    },
14605
14606    // private
14607    onBeforeAdd : function(item){
14608        if(item.ownerCt){
14609            item.ownerCt.remove(item, false);
14610        }
14611        if(this.hideBorders === true){
14612            item.border = (item.border === true);
14613        }
14614    },
14615
14616    
14617    remove : function(comp, autoDestroy){
14618        var c = this.getComponent(comp);
14619        if(c && this.fireEvent('beforeremove', this, c) !== false){
14620            this.items.remove(c);
14621            delete c.ownerCt;
14622            if(autoDestroy === true || (autoDestroy !== false && this.autoDestroy)){
14623                c.destroy();
14624            }
14625            if(this.layout && this.layout.activeItem == c){
14626                delete this.layout.activeItem;
14627            }
14628            this.fireEvent('remove', this, c);
14629        }
14630        return c;
14631    },
14632    
14633    
14634    removeAll: function(autoDestroy){
14635        var item, items = [];
14636        while((item = this.items.last())){
14637            items.unshift(this.remove(item, autoDestroy));
14638        }
14639        return items;
14640    },
14641
14642    
14643    getComponent : function(comp){
14644        if(typeof comp == 'object'){
14645            return comp;
14646        }
14647        return this.items.get(comp);
14648    },
14649
14650    // private
14651    lookupComponent : function(comp){
14652        if(typeof comp == 'string'){
14653            return Ext.ComponentMgr.get(comp);
14654        }else if(!comp.events){
14655            return this.createComponent(comp);
14656        }
14657        return comp;
14658    },
14659
14660    // private
14661    createComponent : function(config){
14662        return Ext.ComponentMgr.create(config, this.defaultType);
14663    },
14664
14665    
14666    doLayout : function(shallow){
14667        if(this.rendered && this.layout){
14668            this.layout.layout();
14669        }
14670        if(shallow !== false && this.items){
14671            var cs = this.items.items;
14672            for(var i = 0, len = cs.length; i < len; i++) {
14673                var c  = cs[i];
14674                if(c.doLayout){
14675                    c.doLayout();
14676                }
14677            }
14678        }
14679    },
14680
14681    
14682    getLayout : function(){
14683        if(!this.layout){
14684            var layout = new Ext.layout.ContainerLayout(this.layoutConfig);
14685            this.setLayout(layout);
14686        }
14687        return this.layout;
14688    },
14689
14690    // private
14691    beforeDestroy : function(){
14692        if(this.items){
14693            Ext.destroy.apply(Ext, this.items.items);
14694        }
14695        if(this.monitorResize){
14696            Ext.EventManager.removeResizeListener(this.doLayout, this);
14697        }
14698        if (this.layout && this.layout.destroy) {
14699            this.layout.destroy();
14700        }
14701        Ext.Container.superclass.beforeDestroy.call(this);
14702    },
14703
14704    
14705    bubble : function(fn, scope, args){
14706        var p = this;
14707        while(p){
14708            if(fn.apply(scope || p, args || [p]) === false){
14709                break;
14710            }
14711            p = p.ownerCt;
14712        }
14713    },
14714
14715    
14716    cascade : function(fn, scope, args){
14717        if(fn.apply(scope || this, args || [this]) !== false){
14718            if(this.items){
14719                var cs = this.items.items;
14720                for(var i = 0, len = cs.length; i < len; i++){
14721                    if(cs[i].cascade){
14722                        cs[i].cascade(fn, scope, args);
14723                    }else{
14724                        fn.apply(scope || cs[i], args || [cs[i]]);
14725                    }
14726                }
14727            }
14728        }
14729    },
14730
14731    
14732    findById : function(id){
14733        var m, ct = this;
14734        this.cascade(function(c){
14735            if(ct != c && c.id === id){
14736                m = c;
14737                return false;
14738            }
14739        });
14740        return m || null;
14741    },
14742
14743    
14744    findByType : function(xtype, shallow){
14745        return this.findBy(function(c){
14746            return c.isXType(xtype, shallow);
14747        });
14748    },
14749
14750    
14751    find : function(prop, value){
14752        return this.findBy(function(c){
14753            return c[prop] === value;
14754        });
14755    },
14756
14757    
14758    findBy : function(fn, scope){
14759        var m = [], ct = this;
14760        this.cascade(function(c){
14761            if(ct != c && fn.call(scope || c, c, ct) === true){
14762                m.push(c);
14763            }
14764        });
14765        return m;
14766    }
14767});
14768
14769Ext.Container.LAYOUTS = {};
14770Ext.reg('container', Ext.Container);
14771
14772Ext.layout.ContainerLayout = function(config){
14773    Ext.apply(this, config);
14774};
14775
14776Ext.layout.ContainerLayout.prototype = {
14777    
14778    
14779
14780    
14781
14782    // private
14783    monitorResize:false,
14784    // private
14785    activeItem : null,
14786
14787    // private
14788    layout : function(){
14789        var target = this.container.getLayoutTarget();
14790        this.onLayout(this.container, target);
14791        this.container.fireEvent('afterlayout', this.container, this);
14792    },
14793
14794    // private
14795    onLayout : function(ct, target){
14796        this.renderAll(ct, target);
14797    },
14798
14799    // private
14800    isValidParent : function(c, target){
14801		var el = c.getPositionEl ? c.getPositionEl() : c.getEl();
14802		return el.dom.parentNode == target.dom;
14803    },
14804
14805    // private
14806    renderAll : function(ct, target){
14807        var items = ct.items.items;
14808        for(var i = 0, len = items.length; i < len; i++) {
14809            var c = items[i];
14810            if(c && (!c.rendered || !this.isValidParent(c, target))){
14811                this.renderItem(c, i, target);
14812            }
14813        }
14814    },
14815
14816    // private
14817    renderItem : function(c, position, target){
14818        if(c && !c.rendered){
14819            c.render(target, position);
14820            if(this.extraCls){
14821            	var t = c.getPositionEl ? c.getPositionEl() : c;
14822            	t.addClass(this.extraCls);
14823            }
14824            if (this.renderHidden && c != this.activeItem) {
14825                c.hide();
14826            }
14827        }else if(c && !this.isValidParent(c, target)){
14828            if(this.extraCls){
14829                var t = c.getPositionEl ? c.getPositionEl() : c;
14830            	t.addClass(this.extraCls);
14831            }
14832            if(typeof position == 'number'){
14833                position = target.dom.childNodes[position];
14834            }
14835            target.dom.insertBefore(c.getEl().dom, position || null);
14836            if (this.renderHidden && c != this.activeItem) {
14837                c.hide();
14838            }
14839        }
14840    },
14841
14842    // private
14843    onResize: function(){
14844        if(this.container.collapsed){
14845            return;
14846        }
14847        var b = this.container.bufferResize;
14848        if(b){
14849            if(!this.resizeTask){
14850                this.resizeTask = new Ext.util.DelayedTask(this.layout, this);
14851                this.resizeBuffer = typeof b == 'number' ? b : 100;
14852            }
14853            this.resizeTask.delay(this.resizeBuffer);
14854        }else{
14855            this.layout();
14856        }
14857    },
14858
14859    // private
14860    setContainer : function(ct){
14861        if(this.monitorResize && ct != this.container){
14862            if(this.container){
14863                this.container.un('resize', this.onResize, this);
14864            }
14865            if(ct){
14866                ct.on('resize', this.onResize, this);
14867            }
14868        }
14869        this.container = ct;
14870    },
14871
14872    // private
14873    parseMargins : function(v){
14874        var ms = v.split(' ');
14875        var len = ms.length;
14876        if(len == 1){
14877            ms[1] = ms[0];
14878            ms[2] = ms[0];
14879            ms[3] = ms[0];
14880        }
14881        if(len == 2){
14882            ms[2] = ms[0];
14883            ms[3] = ms[1];
14884        }
14885        return {
14886            top:parseInt(ms[0], 10) || 0,
14887            right:parseInt(ms[1], 10) || 0,
14888            bottom:parseInt(ms[2], 10) || 0,
14889            left:parseInt(ms[3], 10) || 0
14890        };
14891    },
14892
14893    
14894    destroy : Ext.emptyFn
14895};
14896Ext.Container.LAYOUTS['auto'] = Ext.layout.ContainerLayout;
14897
14898Ext.layout.FitLayout = Ext.extend(Ext.layout.ContainerLayout, {
14899    // private
14900    monitorResize:true,
14901
14902    // private
14903    onLayout : function(ct, target){
14904        Ext.layout.FitLayout.superclass.onLayout.call(this, ct, target);
14905        if(!this.container.collapsed){
14906            this.setItemSize(this.activeItem || ct.items.itemAt(0), target.getStyleSize());
14907        }
14908    },
14909
14910    // private
14911    setItemSize : function(item, size){
14912        if(item && size.height > 0){ // display none?
14913            item.setSize(size);
14914        }
14915    }
14916});
14917Ext.Container.LAYOUTS['fit'] = Ext.layout.FitLayout;
14918
14919Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {
14920    
14921    deferredRender : false,
14922
14923    // private
14924    renderHidden : true,
14925
14926    
14927    setActiveItem : function(item){
14928        item = this.container.getComponent(item);
14929        if(this.activeItem != item){
14930            if(this.activeItem){
14931                this.activeItem.hide();
14932            }
14933            this.activeItem = item;
14934            item.show();
14935            this.layout();
14936        }
14937    },
14938
14939    // private
14940    renderAll : function(ct, target){
14941        if(this.deferredRender){
14942            this.renderItem(this.activeItem, undefined, target);
14943        }else{
14944            Ext.layout.CardLayout.superclass.renderAll.call(this, ct, target);
14945        }
14946    }
14947});
14948Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;
14949
14950Ext.layout.AnchorLayout = Ext.extend(Ext.layout.ContainerLayout, {
14951    // private
14952    monitorResize:true,
14953
14954    // private
14955    getAnchorViewSize : function(ct, target){
14956        return target.dom == document.body ?
14957                   target.getViewSize() : target.getStyleSize();
14958    },
14959
14960    // private
14961    onLayout : function(ct, target){
14962        Ext.layout.AnchorLayout.superclass.onLayout.call(this, ct, target);
14963
14964        var size = this.getAnchorViewSize(ct, target);
14965
14966        var w = size.width, h = size.height;
14967
14968        if(w < 20 || h < 20){
14969            return;
14970        }
14971
14972        // find the container anchoring size
14973        var aw, ah;
14974        if(ct.anchorSize){
14975            if(typeof ct.anchorSize == 'number'){
14976                aw = ct.anchorSize;
14977            }else{
14978                aw = ct.anchorSize.width;
14979                ah = ct.anchorSize.height;
14980            }
14981        }else{
14982            aw = ct.initialConfig.width;
14983            ah = ct.initialConfig.height;
14984        }
14985
14986        var cs = ct.items.items, len = cs.length, i, c, a, cw, ch;
14987        for(i = 0; i < len; i++){
14988            c = cs[i];
14989            if(c.anchor){
14990                a = c.anchorSpec;
14991                if(!a){ // cache all anchor values
14992                    var vs = c.anchor.split(' ');
14993                    c.anchorSpec = a = {
14994                        right: this.parseAnchor(vs[0], c.initialConfig.width, aw),
14995                        bottom: this.parseAnchor(vs[1], c.initialConfig.height, ah)
14996                    };
14997                }
14998                cw = a.right ? this.adjustWidthAnchor(a.right(w), c) : undefined;
14999                ch = a.bottom ? this.adjustHeightAnchor(a.bottom(h), c) : undefined;
15000
15001                if(cw || ch){
15002                    c.setSize(cw || undefined, ch || undefined);
15003                }
15004            }
15005        }
15006    },
15007
15008    // private
15009    parseAnchor : function(a, start, cstart){
15010        if(a && a != 'none'){
15011            var last;
15012            if(/^(r|right|b|bottom)$/i.test(a)){   // standard anchor
15013                var diff = cstart - start;
15014                return function(v){
15015                    if(v !== last){
15016                        last = v;
15017                        return v - diff;
15018                    }
15019                }
15020            }else if(a.indexOf('%') != -1){
15021                var ratio = parseFloat(a.replace('%', ''))*.01;   // percentage
15022                return function(v){
15023                    if(v !== last){
15024                        last = v;
15025                        return Math.floor(v*ratio);
15026                    }
15027                }
15028            }else{
15029                a = parseInt(a, 10);
15030                if(!isNaN(a)){                            // simple offset adjustment
15031                    return function(v){
15032                        if(v !== last){
15033                            last = v;
15034                            return v + a;
15035                        }
15036                    }
15037                }
15038            }
15039        }
15040        return false;
15041    },
15042
15043    // private
15044    adjustWidthAnchor : function(value, comp){
15045        return value;
15046    },
15047
15048    // private
15049    adjustHeightAnchor : function(value, comp){
15050        return value;
15051    }
15052    
15053    
15054});
15055Ext.Container.LAYOUTS['anchor'] = Ext.layout.AnchorLayout;
15056
15057Ext.layout.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {
15058    // private
15059    monitorResize:true,
15060    
15061    
15062    extraCls: 'x-column',
15063
15064    scrollOffset : 0,
15065
15066    // private
15067    isValidParent : function(c, target){
15068        return (c.getPositionEl ? c.getPositionEl() : c.getEl()).dom.parentNode == this.innerCt.dom;
15069    },
15070
15071    // private
15072    onLayout : function(ct, target){
15073        var cs = ct.items.items, len = cs.length, c, i;
15074
15075        if(!this.innerCt){
15076            target.addClass('x-column-layout-ct');
15077
15078            // the innerCt prevents wrapping and shuffling while
15079            // the container is resizing
15080            this.innerCt = target.createChild({cls:'x-column-inner'});
15081            this.innerCt.createChild({cls:'x-clear'});
15082        }
15083        this.renderAll(ct, this.innerCt);
15084
15085        var size = Ext.isIE && target.dom != Ext.getBody().dom ? target.getStyleSize() : target.getViewSize();
15086
15087        if(size.width < 1 && size.height < 1){ // display none?
15088            return;
15089        }
15090
15091        var w = size.width - target.getPadding('lr') - this.scrollOffset,
15092            h = size.height - target.getPadding('tb'),
15093            pw = w;
15094
15095        this.innerCt.setWidth(w);
15096        
15097        // some columns can be percentages while others are fixed
15098        // so we need to make 2 passes
15099
15100        for(i = 0; i < len; i++){
15101            c = cs[i];
15102            if(!c.columnWidth){
15103                pw -= (c.getSize().width + c.getEl().getMargins('lr'));
15104            }
15105        }
15106
15107        pw = pw < 0 ? 0 : pw;
15108
15109        for(i = 0; i < len; i++){
15110            c = cs[i];
15111            if(c.columnWidth){
15112                c.setSize(Math.floor(c.columnWidth*pw) - c.getEl().getMargins('lr'));
15113            }
15114        }
15115    }
15116    
15117    
15118});
15119
15120Ext.Container.LAYOUTS['column'] = Ext.layout.ColumnLayout;
15121
15122Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {
15123    // private
15124    monitorResize:true,
15125    // private
15126    rendered : false,
15127
15128    // private
15129    onLayout : function(ct, target){
15130        var collapsed;
15131        if(!this.rendered){
15132            target.position();
15133            target.addClass('x-border-layout-ct');
15134            var items = ct.items.items;
15135            collapsed = [];
15136            for(var i = 0, len = items.length; i < len; i++) {
15137                var c = items[i];
15138                var pos = c.region;
15139                if(c.collapsed){
15140                    collapsed.push(c);
15141                }
15142                c.collapsed = false;
15143                if(!c.rendered){
15144                    c.cls = c.cls ? c.cls +' x-border-panel' : 'x-border-panel';
15145                    c.render(target, i);
15146                }
15147                this[pos] = pos != 'center' && c.split ?
15148                    new Ext.layout.BorderLayout.SplitRegion(this, c.initialConfig, pos) :
15149                    new Ext.layout.BorderLayout.Region(this, c.initialConfig, pos);
15150                this[pos].render(target, c);
15151            }
15152            this.rendered = true;
15153        }
15154
15155        var size = target.getViewSize();
15156        if(size.width < 20 || size.height < 20){ // display none?
15157            if(collapsed){
15158                this.restoreCollapsed = collapsed;
15159            }
15160            return;
15161        }else if(this.restoreCollapsed){
15162            collapsed = this.restoreCollapsed;
15163            delete this.restoreCollapsed;
15164        }
15165
15166        var w = size.width, h = size.height;
15167        var centerW = w, centerH = h, centerY = 0, centerX = 0;
15168
15169        var n = this.north, s = this.south, west = this.west, e = this.east, c = this.center;
15170        if(!c && Ext.layout.BorderLayout.WARN !== false){
15171            throw 'No center region defined in BorderLayout ' + ct.id;
15172        }
15173
15174        if(n && n.isVisible()){
15175            var b = n.getSize();
15176            var m = n.getMargins();
15177            b.width = w - (m.left+m.right);
15178            b.x = m.left;
15179            b.y = m.top;
15180            centerY = b.height + b.y + m.bottom;
15181            centerH -= centerY;
15182            n.applyLayout(b);
15183        }
15184        if(s && s.isVisible()){
15185            var b = s.getSize();
15186            var m = s.getMargins();
15187            b.width = w - (m.left+m.right);
15188            b.x = m.left;
15189            var totalHeight = (b.height + m.top + m.bottom);
15190            b.y = h - totalHeight + m.top;
15191            centerH -= totalHeight;
15192            s.applyLayout(b);
15193        }
15194        if(west && west.isVisible()){
15195            var b = west.getSize();
15196            var m = west.getMargins();
15197            b.height = centerH - (m.top+m.bottom);
15198            b.x = m.left;
15199            b.y = centerY + m.top;
15200            var totalWidth = (b.width + m.left + m.right);
15201            centerX += totalWidth;
15202            centerW -= totalWidth;
15203            west.applyLayout(b);
15204        }
15205        if(e && e.isVisible()){
15206            var b = e.getSize();
15207            var m = e.getMargins();
15208            b.height = centerH - (m.top+m.bottom);
15209            var totalWidth = (b.width + m.left + m.right);
15210            b.x = w - totalWidth + m.left;
15211            b.y = centerY + m.top;
15212            centerW -= totalWidth;
15213            e.applyLayout(b);
15214        }
15215
15216        if(c){
15217            var m = c.getMargins();
15218            var centerBox = {
15219                x: centerX + m.left,
15220                y: centerY + m.top,
15221                width: centerW - (m.left+m.right),
15222                height: centerH - (m.top+m.bottom)
15223            };
15224            c.applyLayout(centerBox);
15225        }
15226        if(collapsed){
15227            for(var i = 0, len = collapsed.length; i < len; i++){
15228                collapsed[i].collapse(false);
15229            }
15230        }
15231
15232        if(Ext.isIE && Ext.isStrict){ // workaround IE strict repainting issue
15233            target.repaint();
15234        }
15235    },
15236
15237    // inherit docs
15238    destroy: function() {
15239        var r = ['north', 'south', 'east', 'west'];
15240        for (var i = 0; i < r.length; i++) {
15241            var region = this[r[i]];
15242            if(region){
15243                if(region.destroy){
15244	                region.destroy();
15245	            }else if (region.split){
15246	                region.split.destroy(true);
15247	            }
15248            }
15249        }
15250        Ext.layout.BorderLayout.superclass.destroy.call(this);
15251    }
15252    
15253    
15254});
15255
15256
15257Ext.layout.BorderLayout.Region = function(layout, config, pos){
15258    Ext.apply(this, config);
15259    this.layout = layout;
15260    this.position = pos;
15261    this.state = {};
15262    if(typeof this.margins == 'string'){
15263        this.margins = this.layout.parseMargins(this.margins);
15264    }
15265    this.margins = Ext.applyIf(this.margins || {}, this.defaultMargins);
15266    if(this.collapsible){
15267        if(typeof this.cmargins == 'string'){
15268            this.cmargins = this.layout.parseMargins(this.cmargins);
15269        }
15270        if(this.collapseMode == 'mini' && !this.cmargins){
15271            this.cmargins = {left:0,top:0,right:0,bottom:0};
15272        }else{
15273            this.cmargins = Ext.applyIf(this.cmargins || {},
15274                pos == 'north' || pos == 'south' ? this.defaultNSCMargins : this.defaultEWCMargins);
15275        }
15276    }
15277};
15278
15279Ext.layout.BorderLayout.Region.prototype = {
15280    
15281    
15282	
15283    
15284    
15285    
15286    
15287    collapsible : false,
15288    
15289    split:false,
15290    
15291    floatable: true,
15292    
15293    minWidth:50,
15294    
15295    minHeight:50,
15296
15297    // private
15298    defaultMargins : {left:0,top:0,right:0,bottom:0},
15299    // private
15300    defaultNSCMargins : {left:5,top:5,right:5,bottom:5},
15301    // private
15302    defaultEWCMargins : {left:5,top:0,right:5,bottom:0},
15303
15304    
15305    isCollapsed : false,
15306
15307    
15308    
15309    
15310
15311    // private
15312    render : function(ct, p){
15313        this.panel = p;
15314        p.el.enableDisplayMode();
15315        this.targetEl = ct;
15316        this.el = p.el;
15317
15318        var gs = p.getState, ps = this.position;
15319        p.getState = function(){
15320            return Ext.apply(gs.call(p) || {}, this.state);
15321        }.createDelegate(this);
15322
15323        if(ps != 'center'){
15324            p.allowQueuedExpand = false;
15325            p.on({
15326                beforecollapse: this.beforeCollapse,
15327                collapse: this.onCollapse,
15328                beforeexpand: this.beforeExpand,
15329                expand: this.onExpand,
15330                hide: this.onHide,
15331                show: this.onShow,
15332                scope: this
15333            });
15334            if(this.collapsible){
15335                p.collapseEl = 'el';
15336                p.slideAnchor = this.getSlideAnchor();
15337            }
15338            if(p.tools && p.tools.toggle){
15339                p.tools.toggle.addClass('x-tool-collapse-'+ps);
15340                p.tools.toggle.addClassOnOver('x-tool-collapse-'+ps+'-over');
15341            }
15342        }
15343    },
15344
15345    // private
15346    getCollapsedEl : function(){
15347        if(!this.collapsedEl){
15348            if(!this.toolTemplate){
15349                var tt = new Ext.Template(
15350                     '<div class="x-tool x-tool-{id}">&#160;</div>'
15351                );
15352                tt.disableFormats = true;
15353                tt.compile();
15354                Ext.layout.BorderLayout.Region.prototype.toolTemplate = tt;
15355            }
15356            this.collapsedEl = this.targetEl.createChild({
15357                cls: "x-layout-collapsed x-layout-collapsed-"+this.position,
15358                id: this.panel.id + '-xcollapsed'
15359            });
15360            this.collapsedEl.enableDisplayMode('block');
15361
15362            if(this.collapseMode == 'mini'){
15363                this.collapsedEl.addClass('x-layout-cmini-'+this.position);
15364                this.miniCollapsedEl = this.collapsedEl.createChild({
15365                    cls: "x-layout-mini x-layout-mini-"+this.position, html: "&#160;"
15366                });
15367                this.miniCollapsedEl.addClassOnOver('x-layout-mini-over');
15368                this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
15369                this.collapsedEl.on('click', this.onExpandClick, this, {stopEvent:true});
15370            }else {
15371                var t = this.toolTemplate.append(
15372                        this.collapsedEl.dom,
15373                        {id:'expand-'+this.position}, true);
15374                t.addClassOnOver('x-tool-expand-'+this.position+'-over');
15375                t.on('click', this.onExpandClick, this, {stopEvent:true});
15376                
15377                if(this.floatable !== false){
15378                   this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
15379                   this.collapsedEl.on("click", this.collapseClick, this);
15380                }
15381            }
15382        }
15383        return this.collapsedEl;
15384    },
15385
15386    // private
15387    onExpandClick : function(e){
15388        if(this.isSlid){
15389            this.afterSlideIn();
15390            this.panel.expand(false);
15391        }else{
15392            this.panel.expand();
15393        }
15394    },
15395
15396    // private
15397    onCollapseClick : function(e){
15398        this.panel.collapse();
15399    },
15400
15401    // private
15402    beforeCollapse : function(p, animate){
15403        this.lastAnim = animate;
15404        if(this.splitEl){
15405            this.splitEl.hide();
15406        }
15407        this.getCollapsedEl().show();
15408        this.panel.el.setStyle('z-index', 100);
15409        this.isCollapsed = true;
15410        this.layout.layout();
15411    },
15412
15413    // private
15414    onCollapse : function(animate){
15415        this.panel.el.setStyle('z-index', 1);
15416        if(this.lastAnim === false || this.panel.animCollapse === false){
15417            this.getCollapsedEl().dom.style.visibility = 'visible';
15418        }else{
15419            this.getCollapsedEl().slideIn(this.panel.slideAnchor, {duration:.2});
15420        }
15421        this.state.collapsed = true;
15422        this.panel.saveState();
15423    },
15424
15425    // private
15426    beforeExpand : function(animate){
15427        var c = this.getCollapsedEl();
15428        this.el.show();
15429        if(this.position == 'east' || this.position == 'west'){
15430            this.panel.setSize(undefined, c.getHeight());
15431        }else{
15432            this.panel.setSize(c.getWidth(), undefined);
15433        }
15434        c.hide();
15435        c.dom.style.visibility = 'hidden';
15436        this.panel.el.setStyle('z-index', 100);
15437    },
15438
15439    // private
15440    onExpand : function(){
15441        this.isCollapsed = false;
15442        if(this.splitEl){
15443            this.splitEl.show();
15444        }
15445        this.layout.layout();
15446        this.panel.el.setStyle('z-index', 1);
15447        this.state.collapsed = false;
15448        this.panel.saveState();
15449    },
15450
15451    // private
15452    collapseClick : function(e){
15453        if(this.isSlid){
15454           e.stopPropagation();
15455           this.slideIn();
15456        }else{
15457           e.stopPropagation();
15458           this.slideOut();
15459        }
15460    },
15461
15462    // private
15463    onHide : function(){
15464        if(this.isCollapsed){
15465            this.getCollapsedEl().hide();
15466        }else if(this.splitEl){
15467            this.splitEl.hide();
15468        }
15469    },
15470
15471    // private
15472    onShow : function(){
15473        if(this.isCollapsed){
15474            this.getCollapsedEl().show();
15475        }else if(this.splitEl){
15476            this.splitEl.show();
15477        }
15478    },
15479
15480    
15481    isVisible : function(){
15482        return !this.panel.hidden;
15483    },
15484
15485    
15486    getMargins : function(){
15487        return this.isCollapsed && this.cmargins ? this.cmargins : this.margins;
15488    },
15489
15490    
15491    getSize : function(){
15492        return this.isCollapsed ? this.getCollapsedEl().getSize() : this.panel.getSize();
15493    },
15494
15495    
15496    setPanel : function(panel){
15497        this.panel = panel;
15498    },
15499
15500    
15501    getMinWidth: function(){
15502        return this.minWidth;
15503    },
15504
15505    
15506    getMinHeight: function(){
15507        return this.minHeight;
15508    },
15509
15510    // private
15511    applyLayoutCollapsed : function(box){
15512        var ce = this.getCollapsedEl();
15513        ce.setLeftTop(box.x, box.y);
15514        ce.setSize(box.width, box.height);
15515    },
15516
15517    // private
15518    applyLayout : function(box){
15519        if(this.isCollapsed){
15520            this.applyLayoutCollapsed(box);
15521        }else{
15522            this.panel.setPosition(box.x, box.y);
15523            this.panel.setSize(box.width, box.height);
15524        }
15525    },
15526
15527    // private
15528    beforeSlide: function(){
15529        this.panel.beforeEffect();
15530    },
15531
15532    // private
15533    afterSlide : function(){
15534        this.panel.afterEffect();
15535    },
15536
15537    // private
15538    initAutoHide : function(){
15539        if(this.autoHide !== false){
15540            if(!this.autoHideHd){
15541                var st = new Ext.util.DelayedTask(this.slideIn, this);
15542                this.autoHideHd = {
15543                    "mouseout": function(e){
15544                        if(!e.within(this.el, true)){
15545                            st.delay(500);
15546                        }
15547                    },
15548                    "mouseover" : function(e){
15549                        st.cancel();
15550                    },
15551                    scope : this
15552                };
15553            }
15554            this.el.on(this.autoHideHd);
15555        }
15556    },
15557
15558    // private
15559    clearAutoHide : function(){
15560        if(this.autoHide !== false){
15561            this.el.un("mouseout", this.autoHideHd.mouseout);
15562            this.el.un("mouseover", this.autoHideHd.mouseover);
15563        }
15564    },
15565
15566    // private
15567    clearMonitor : function(){
15568        Ext.getDoc().un("click", this.slideInIf, this);
15569    },
15570
15571    // these names are backwards but not changed for compat
15572    // private
15573    slideOut : function(){
15574        if(this.isSlid || this.el.hasActiveFx()){
15575            return;
15576        }
15577        this.isSlid = true;
15578        var ts = this.panel.tools;
15579        if(ts && ts.toggle){
15580            ts.toggle.hide();
15581        }
15582        this.el.show();
15583        if(this.position == 'east' || this.position == 'west'){
15584            this.panel.setSize(undefined, this.collapsedEl.getHeight());
15585        }else{
15586            this.panel.setSize(this.collapsedEl.getWidth(), undefined);
15587        }
15588        this.restoreLT = [this.el.dom.style.left, this.el.dom.style.top];
15589        this.el.alignTo(this.collapsedEl, this.getCollapseAnchor());
15590        this.el.setStyle("z-index", 102);
15591        this.panel.el.replaceClass('x-panel-collapsed', 'x-panel-floating');
15592        if(this.animFloat !== false){
15593            this.beforeSlide();
15594            this.el.slideIn(this.getSlideAnchor(), {
15595                callback: function(){
15596                    this.afterSlide();
15597                    this.initAutoHide();
15598                    Ext.getDoc().on("click", this.slideInIf, this);
15599                },
15600                scope: this,
15601                block: true
15602            });
15603        }else{
15604            this.initAutoHide();
15605             Ext.getDoc().on("click", this.slideInIf, this);
15606        }
15607    },
15608
15609    // private
15610    afterSlideIn : function(){
15611        this.clearAutoHide();
15612        this.isSlid = false;
15613        this.clearMonitor();
15614        this.el.setStyle("z-index", "");
15615        this.panel.el.replaceClass('x-panel-floating', 'x-panel-collapsed');
15616        this.el.dom.style.left = this.restoreLT[0];
15617        this.el.dom.style.top = this.restoreLT[1];
15618
15619        var ts = this.panel.tools;
15620        if(ts && ts.toggle){
15621            ts.toggle.show();
15622        }
15623    },
15624
15625    // private
15626    slideIn : function(cb){
15627        if(!this.isSlid || this.el.hasActiveFx()){
15628            Ext.callback(cb);
15629            return;
15630        }
15631        this.isSlid = false;
15632        if(this.animFloat !== false){
15633            this.beforeSlide();
15634            this.el.slideOut(this.getSlideAnchor(), {
15635                callback: function(){
15636                    this.el.hide();
15637                    this.afterSlide();
15638                    this.afterSlideIn();
15639                    Ext.callback(cb);
15640                },
15641                scope: this,
15642                block: true
15643            });
15644        }else{
15645            this.el.hide();
15646            this.afterSlideIn();
15647        }
15648    },
15649
15650    // private
15651    slideInIf : function(e){
15652        if(!e.within(this.el)){
15653            this.slideIn();
15654        }
15655    },
15656
15657    // private
15658    anchors : {
15659        "west" : "left",
15660        "east" : "right",
15661        "north" : "top",
15662        "south" : "bottom"
15663    },
15664
15665    // private
15666    sanchors : {
15667        "west" : "l",
15668        "east" : "r",
15669        "north" : "t",
15670        "south" : "b"
15671    },
15672
15673    // private
15674    canchors : {
15675        "west" : "tl-tr",
15676        "east" : "tr-tl",
15677        "north" : "tl-bl",
15678        "south" : "bl-tl"
15679    },
15680
15681    // private
15682    getAnchor : function(){
15683        return this.anchors[this.position];
15684    },
15685
15686    // private
15687    getCollapseAnchor : function(){
15688        return this.canchors[this.position];
15689    },
15690
15691    // private
15692    getSlideAnchor : function(){
15693        return this.sanchors[this.position];
15694    },
15695
15696    // private
15697    getAlignAdj : function(){
15698        var cm = this.cmargins;
15699        switch(this.position){
15700            case "west":
15701                return [0, 0];
15702            break;
15703            case "east":
15704                return [0, 0];
15705            break;
15706            case "north":
15707                return [0, 0];
15708            break;
15709            case "south":
15710                return [0, 0];
15711            break;
15712        }
15713    },
15714
15715    // private
15716    getExpandAdj : function(){
15717        var c = this.collapsedEl, cm = this.cmargins;
15718        switch(this.position){
15719            case "west":
15720                return [-(cm.right+c.getWidth()+cm.left), 0];
15721            break;
15722            case "east":
15723                return [cm.right+c.getWidth()+cm.left, 0];
15724            break;
15725            case "north":
15726                return [0, -(cm.top+cm.bottom+c.getHeight())];
15727            break;
15728            case "south":
15729                return [0, cm.top+cm.bottom+c.getHeight()];
15730            break;
15731        }
15732    }
15733};
15734
15735
15736Ext.layout.BorderLayout.SplitRegion = function(layout, config, pos){
15737    Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this, layout, config, pos);
15738    // prevent switch
15739    this.applyLayout = this.applyFns[pos];
15740};
15741
15742Ext.extend(Ext.layout.BorderLayout.SplitRegion, Ext.layout.BorderLayout.Region, {
15743    
15744    splitTip : "Drag to resize.",
15745    
15746    collapsibleSplitTip : "Drag to resize. Double click to hide.",
15747    
15748    useSplitTips : false,
15749
15750    // private
15751    splitSettings : {
15752        north : {
15753            orientation: Ext.SplitBar.VERTICAL,
15754            placement: Ext.SplitBar.TOP,
15755            maxFn : 'getVMaxSize',
15756            minProp: 'minHeight',
15757            maxProp: 'maxHeight'
15758        },
15759        south : {
15760            orientation: Ext.SplitBar.VERTICAL,
15761            placement: Ext.SplitBar.BOTTOM,
15762            maxFn : 'getVMaxSize',
15763            minProp: 'minHeight',
15764            maxProp: 'maxHeight'
15765        },
15766        east : {
15767            orientation: Ext.SplitBar.HORIZONTAL,
15768            placement: Ext.SplitBar.RIGHT,
15769            maxFn : 'getHMaxSize',
15770            minProp: 'minWidth',
15771            maxProp: 'maxWidth'
15772        },
15773        west : {
15774            orientation: Ext.SplitBar.HORIZONTAL,
15775            placement: Ext.SplitBar.LEFT,
15776            maxFn : 'getHMaxSize',
15777            minProp: 'minWidth',
15778            maxProp: 'maxWidth'
15779        }
15780    },
15781
15782    // private
15783    applyFns : {
15784        west : function(box){
15785            if(this.isCollapsed){
15786                return this.applyLayoutCollapsed(box);
15787            }
15788            var sd = this.splitEl.dom, s = sd.style;
15789            this.panel.setPosition(box.x, box.y);
15790            var sw = sd.offsetWidth;
15791            s.left = (box.x+box.width-sw)+'px';
15792            s.top = (box.y)+'px';
15793            s.height = Math.max(0, box.height)+'px';
15794            this.panel.setSize(box.width-sw, box.height);
15795        },
15796        east : function(box){
15797            if(this.isCollapsed){
15798                return this.applyLayoutCollapsed(box);
15799            }
15800            var sd = this.splitEl.dom, s = sd.style;
15801            var sw = sd.offsetWidth;
15802            this.panel.setPosition(box.x+sw, box.y);
15803            s.left = (box.x)+'px';
15804            s.top = (box.y)+'px';
15805            s.height = Math.max(0, box.height)+'px';
15806            this.panel.setSize(box.width-sw, box.height);
15807        },
15808        north : function(box){
15809            if(this.isCollapsed){
15810                return this.applyLayoutCollapsed(box);
15811            }
15812            var sd = this.splitEl.dom, s = sd.style;
15813            var sh = sd.offsetHeight;
15814            this.panel.setPosition(box.x, box.y);
15815            s.left = (box.x)+'px';
15816            s.top = (box.y+box.height-sh)+'px';
15817            s.width = Math.max(0, box.width)+'px';
15818            this.panel.setSize(box.width, box.height-sh);
15819        },
15820        south : function(box){
15821            if(this.isCollapsed){
15822                return this.applyLayoutCollapsed(box);
15823            }
15824            var sd = this.splitEl.dom, s = sd.style;
15825            var sh = sd.offsetHeight;
15826            this.panel.setPosition(box.x, box.y+sh);
15827            s.left = (box.x)+'px';
15828            s.top = (box.y)+'px';
15829            s.width = Math.max(0, box.width)+'px';
15830            this.panel.setSize(box.width, box.height-sh);
15831        }
15832    },
15833
15834    // private
15835    render : function(ct, p){
15836        Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this, ct, p);
15837
15838        var ps = this.position;
15839
15840        this.splitEl = ct.createChild({
15841            cls: "x-layout-split x-layout-split-"+ps, html: "&#160;",
15842            id: this.panel.id + '-xsplit'
15843        });
15844
15845        if(this.collapseMode == 'mini'){
15846            this.miniSplitEl = this.splitEl.createChild({
15847                cls: "x-layout-mini x-layout-mini-"+ps, html: "&#160;"
15848            });
15849            this.miniSplitEl.addClassOnOver('x-layout-mini-over');
15850            this.miniSplitEl.on('click', this.onCollapseClick, this, {stopEvent:true});
15851        }
15852
15853        var s = this.splitSettings[ps];
15854
15855        this.split = new Ext.SplitBar(this.splitEl.dom, p.el, s.orientation);
15856        this.split.placement = s.placement;
15857        this.split.getMaximumSize = this[s.maxFn].createDelegate(this);
15858        this.split.minSize = this.minSize || this[s.minProp];
15859        this.split.on("beforeapply", this.onSplitMove, this);
15860        this.split.useShim = this.useShim === true;
15861        this.maxSize = this.maxSize || this[s.maxProp];
15862
15863        if(p.hidden){
15864            this.splitEl.hide();
15865        }
15866
15867        if(this.useSplitTips){
15868            this.splitEl.dom.title = this.collapsible ? this.collapsibleSplitTip : this.splitTip;
15869        }
15870        if(this.collapsible){
15871            this.splitEl.on("dblclick", this.onCollapseClick,  this);
15872        }
15873    },
15874
15875    //docs inherit from superclass
15876    getSize : function(){
15877        if(this.isCollapsed){
15878            return this.collapsedEl.getSize();
15879        }
15880        var s = this.panel.getSize();
15881        if(this.position == 'north' || this.position == 'south'){
15882            s.height += this.splitEl.dom.offsetHeight;
15883        }else{
15884            s.width += this.splitEl.dom.offsetWidth;
15885        }
15886        return s;
15887    },
15888
15889    // private
15890    getHMaxSize : function(){
15891         var cmax = this.maxSize || 10000;
15892         var center = this.layout.center;
15893         return Math.min(cmax, (this.el.getWidth()+center.el.getWidth())-center.getMinWidth());
15894    },
15895
15896    // private
15897    getVMaxSize : function(){
15898        var cmax = this.maxSize || 10000;
15899        var center = this.layout.center;
15900        return Math.min(cmax, (this.el.getHeight()+center.el.getHeight())-center.getMinHeight());
15901    },
15902
15903    // private
15904    onSplitMove : function(split, newSize){
15905        var s = this.panel.getSize();
15906        this.lastSplitSize = newSize;
15907        if(this.position == 'north' || this.position == 'south'){
15908            this.panel.setSize(s.width, newSize);
15909            this.state.height = newSize;
15910        }else{
15911            this.panel.setSize(newSize, s.height);
15912            this.state.width = newSize;
15913        }
15914        this.layout.layout();
15915        this.panel.saveState();
15916        return false;
15917    },
15918
15919    
15920    getSplitBar : function(){
15921        return this.split;
15922    },
15923    
15924    // inherit docs
15925    destroy : function() {
15926        Ext.destroy(
15927            this.miniSplitEl, 
15928            this.split, 
15929            this.splitEl
15930        );
15931    }
15932});
15933
15934Ext.Container.LAYOUTS['border'] = Ext.layout.BorderLayout;
15935
15936Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {
15937    
15938    labelSeparator : ':',
15939
15940    // private
15941    getAnchorViewSize : function(ct, target){
15942        return (ct.body||ct.el).getStyleSize();
15943    },
15944
15945    // private
15946    setContainer : function(ct){
15947        Ext.layout.FormLayout.superclass.setContainer.call(this, ct);
15948
15949        if(ct.labelAlign){
15950            ct.addClass('x-form-label-'+ct.labelAlign);
15951        }
15952
15953        if(ct.hideLabels){
15954            this.labelStyle = "display:none";
15955            this.elementStyle = "padding-left:0;";
15956            this.labelAdjust = 0;
15957        }else{
15958            this.labelSeparator = ct.labelSeparator || this.labelSeparator;
15959            ct.labelWidth = ct.labelWidth || 100;
15960            if(typeof ct.labelWidth == 'number'){
15961                var pad = (typeof ct.labelPad == 'number' ? ct.labelPad : 5);
15962                this.labelAdjust = ct.labelWidth+pad;
15963                this.labelStyle = "width:"+ct.labelWidth+"px;";
15964                this.elementStyle = "padding-left:"+(ct.labelWidth+pad)+'px';
15965            }
15966            if(ct.labelAlign == 'top'){
15967                this.labelStyle = "width:auto;";
15968                this.labelAdjust = 0;
15969                this.elementStyle = "padding-left:0;";
15970            }
15971        }
15972
15973        if(!this.fieldTpl){
15974            // the default field template used by all form layouts
15975            var t = new Ext.Template(
15976                '<div class="x-form-item {5}" tabIndex="-1">',
15977                    '<label for="{0}" style="{2}" class="x-form-item-label">{1}{4}</label>',
15978                    '<div class="x-form-element" id="x-form-el-{0}" style="{3}">',
15979                    '</div><div class="{6}"></div>',
15980                '</div>'
15981            );
15982            t.disableFormats = true;
15983            t.compile();
15984            Ext.layout.FormLayout.prototype.fieldTpl = t;
15985        }
15986    },
15987    
15988    //private
15989    getLabelStyle: function(s){
15990        var ls = '', items = [this.labelStyle, s];
15991        for (var i = 0, len = items.length; i < len; ++i){
15992            if (items[i]){
15993                ls += items[i];
15994                if (ls.substr(-1, 1) != ';'){
15995                    ls += ';'
15996                }
15997            }
15998        }
15999        return ls;
16000    },
16001
16002    // private
16003    renderItem : function(c, position, target){
16004        if(c && !c.rendered && c.isFormField && c.inputType != 'hidden'){
16005            var args = [
16006                   c.id, c.fieldLabel,
16007                   this.getLabelStyle(c.labelStyle),
16008                   this.elementStyle||'',
16009                   typeof c.labelSeparator == 'undefined' ? this.labelSeparator : c.labelSeparator,
16010                   (c.itemCls||this.container.itemCls||'') + (c.hideLabel ? ' x-hide-label' : ''),
16011                   c.clearCls || 'x-form-clear-left' 
16012            ];
16013            if(typeof position == 'number'){
16014                position = target.dom.childNodes[position] || null;
16015            }
16016            if(position){
16017                this.fieldTpl.insertBefore(position, args);
16018            }else{
16019                this.fieldTpl.append(target, args);
16020            }
16021            c.render('x-form-el-'+c.id);
16022        }else {
16023            Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments);
16024        }
16025    },
16026
16027    // private
16028    adjustWidthAnchor : function(value, comp){
16029        return value - (comp.isFormField  ? (comp.hideLabel ? 0 : this.labelAdjust) : 0);
16030    },
16031
16032    // private
16033    isValidParent : function(c, target){
16034        return true;
16035    }
16036
16037    
16038});
16039
16040Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout;
16041
16042Ext.layout.Accordion = Ext.extend(Ext.layout.FitLayout, {
16043    
16044    fill : true,
16045    
16046    autoWidth : true,
16047    
16048    titleCollapse : true,
16049    
16050    hideCollapseTool : false,
16051    
16052    collapseFirst : false,
16053    
16054    animate : false,
16055    
16056    sequence : false,
16057    
16058    activeOnTop : false,
16059
16060    renderItem : function(c){
16061        if(this.animate === false){
16062            c.animCollapse = false;
16063        }
16064        c.collapsible = true;
16065        if(this.autoWidth){
16066            c.autoWidth = true;
16067        }
16068        if(this.titleCollapse){
16069            c.titleCollapse = true;
16070        }
16071        if(this.hideCollapseTool){
16072            c.hideCollapseTool = true;
16073        }
16074        if(this.collapseFirst !== undefined){
16075            c.collapseFirst = this.collapseFirst;
16076        }
16077        if(!this.activeItem && !c.collapsed){
16078            this.activeItem = c;
16079        }else if(this.activeItem){
16080            c.collapsed = true;
16081        }
16082        Ext.layout.Accordion.superclass.renderItem.apply(this, arguments);
16083        c.header.addClass('x-accordion-hd');
16084        c.on('beforeexpand', this.beforeExpand, this);
16085    },
16086
16087    // private
16088    beforeExpand : function(p, anim){
16089        var ai = this.activeItem;
16090        if(ai){
16091            if(this.sequence){
16092                delete this.activeItem;
16093                if (!ai.collapsed){
16094                    ai.collapse({callback:function(){
16095                        p.expand(anim || true);
16096                    }, scope: this});
16097                    return false;
16098                }
16099            }else{
16100                ai.collapse(this.animate);
16101            }
16102        }
16103        this.activeItem = p;
16104        if(this.activeOnTop){
16105            p.el.dom.parentNode.insertBefore(p.el.dom, p.el.dom.parentNode.firstChild);
16106        }
16107        this.layout();
16108    },
16109
16110    // private
16111    setItemSize : function(item, size){
16112        if(this.fill && item){
16113            var items = this.container.items.items;
16114            var hh = 0;
16115            for(var i = 0, len = items.length; i < len; i++){
16116                var p = items[i];
16117                if(p != item){
16118                    hh += (p.getSize().height - p.bwrap.getHeight());
16119                }
16120            }
16121            size.height -= hh;
16122            item.setSize(size);
16123        }
16124    }
16125});
16126Ext.Container.LAYOUTS['accordion'] = Ext.layout.Accordion;
16127
16128Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {
16129    
16130
16131    // private
16132    monitorResize:false,
16133
16134    // private
16135    setContainer : function(ct){
16136        Ext.layout.TableLayout.superclass.setContainer.call(this, ct);
16137
16138        this.currentRow = 0;
16139        this.currentColumn = 0;
16140        this.cells = [];
16141    },
16142
16143    // private
16144    onLayout : function(ct, target){
16145        var cs = ct.items.items, len = cs.length, c, i;
16146
16147        if(!this.table){
16148            target.addClass('x-table-layout-ct');
16149
16150            this.table = target.createChild(
16151                {tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, null, true);
16152
16153            this.renderAll(ct, target);
16154        }
16155    },
16156
16157    // private
16158    getRow : function(index){
16159        var row = this.table.tBodies[0].childNodes[index];
16160        if(!row){
16161            row = document.createElement('tr');
16162            this.table.tBodies[0].appendChild(row);
16163        }
16164        return row;
16165    },
16166
16167    // private
16168	getNextCell : function(c){
16169		var cell = this.getNextNonSpan(this.currentColumn, this.currentRow);
16170		var curCol = this.currentColumn = cell[0], curRow = this.currentRow = cell[1];
16171		for(var rowIndex = curRow; rowIndex < curRow + (c.rowspan || 1); rowIndex++){
16172			if(!this.cells[rowIndex]){
16173				this.cells[rowIndex] = [];
16174			}
16175			for(var colIndex = curCol; colIndex < curCol + (c.colspan || 1); colIndex++){
16176				this.cells[rowIndex][colIndex] = true;
16177			}
16178		}
16179		var td = document.createElement('td');
16180		if(c.cellId){
16181			td.id = c.cellId;
16182		}
16183		var cls = 'x-table-layout-cell';
16184		if(c.cellCls){
16185			cls += ' ' + c.cellCls;
16186		}
16187		td.className = cls;
16188		if(c.colspan){
16189			td.colSpan = c.colspan;
16190		}
16191		if(c.rowspan){
16192			td.rowSpan = c.rowspan;
16193		}
16194		this.getRow(curRow).appendChild(td);
16195		return td;
16196	},
16197    
16198    // private
16199	getNextNonSpan: function(colIndex, rowIndex){
16200		var cols = this.columns;
16201		while((cols && colIndex >= cols) || (this.cells[rowIndex] && this.cells[rowIndex][colIndex])) {
16202			if(cols && colIndex >= cols){
16203				rowIndex++;
16204				colIndex = 0;
16205			}else{
16206				colIndex++;
16207			}
16208		}
16209		return [colIndex, rowIndex];
16210	},
16211
16212    // private
16213    renderItem : function(c, position, target){
16214        if(c && !c.rendered){
16215            c.render(this.getNextCell(c));
16216            if(this.extraCls){
16217                var t = c.getPositionEl ? c.getPositionEl() : c;
16218                t.addClass(this.extraCls);
16219            }
16220        }
16221    },
16222
16223    // private
16224    isValidParent : function(c, target){
16225        return true;
16226    }
16227
16228    
16229});
16230
16231Ext.Container.LAYOUTS['table'] = Ext.layout.TableLayout;
16232
16233Ext.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {
16234    
16235    extraCls: 'x-abs-layout-item',
16236    isForm: false,
16237    // private
16238    setContainer : function(ct){
16239        Ext.layout.AbsoluteLayout.superclass.setContainer.call(this, ct);
16240        if(ct.isXType('form')){
16241            this.isForm = true;
16242        }
16243    },
16244
16245    onLayout : function(ct, target){
16246        if(this.isForm){ ct.body.position(); } else { target.position(); }
16247        Ext.layout.AbsoluteLayout.superclass.onLayout.call(this, ct, target);
16248    },
16249
16250    // private
16251    getAnchorViewSize : function(ct, target){
16252        return this.isForm ? ct.body.getStyleSize() : Ext.layout.AbsoluteLayout.superclass.getAnchorViewSize.call(this, ct, target);
16253    },
16254
16255    // private
16256    isValidParent : function(c, target){
16257        return this.isForm ? true : Ext.layout.AbsoluteLayout.superclass.isValidParent.call(this, c, target);
16258    },
16259
16260    // private
16261    adjustWidthAnchor : function(value, comp){
16262        return value ? value - comp.getPosition(true)[0] : value;
16263    },
16264
16265    // private
16266    adjustHeightAnchor : function(value, comp){
16267        return  value ? value - comp.getPosition(true)[1] : value;
16268    }
16269    
16270});
16271Ext.Container.LAYOUTS['absolute'] = Ext.layout.AbsoluteLayout;
16272
16273Ext.Viewport = Ext.extend(Ext.Container, {
16274	
16275    
16276    
16277    
16278    
16279    
16280    
16281    
16282    
16283    
16284    
16285    
16286    initComponent : function() {
16287        Ext.Viewport.superclass.initComponent.call(this);
16288        document.getElementsByTagName('html')[0].className += ' x-viewport';
16289        this.el = Ext.getBody();
16290        this.el.setHeight = Ext.emptyFn;
16291        this.el.setWidth = Ext.emptyFn;
16292        this.el.setSize = Ext.emptyFn;
16293        this.el.dom.scroll = 'no';
16294        this.allowDomMove = false;
16295        this.autoWidth = true;
16296        this.autoHeight = true;
16297        Ext.EventManager.onWindowResize(this.fireResize, this);
16298        this.renderTo = this.el;
16299    },
16300
16301    fireResize : function(w, h){
16302        this.fireEvent('resize', this, w, h, w, h);
16303    }
16304});
16305Ext.reg('viewport', Ext.Viewport);
16306
16307Ext.Panel = Ext.extend(Ext.Container, {
16308    
16309    
16310    
16311    
16312    
16313    
16314    
16315    
16316    
16317    
16318    
16319    
16320    
16321    
16322    
16323    
16324    
16325    
16326    
16327    
16328    
16329    
16330    
16331    
16332    
16333    
16334    
16335    
16336    
16337     
16338    
16339    
16340    
16341    
16342
16343    
16344    baseCls : 'x-panel',
16345    
16346    collapsedCls : 'x-panel-collapsed',
16347    
16348    maskDisabled: true,
16349    
16350    animCollapse: Ext.enableFx,
16351    
16352    headerAsText: true,
16353    
16354    buttonAlign: 'right',
16355    
16356    collapsed : false,
16357    
16358    collapseFirst: true,
16359    
16360    minButtonWidth:75,
16361    
16362    elements : 'body',
16363
16364    // protected - these could be used to customize the behavior of the window,
16365    // but changing them would not be useful without further mofifications and
16366    // could lead to unexpected or undesirable results.
16367    toolTarget : 'header',
16368    collapseEl : 'bwrap',
16369    slideAnchor : 't',
16370    disabledClass: '',
16371
16372    // private, notify box this class will handle heights
16373    deferHeight: true,
16374    // private
16375    expandDefaults: {
16376        duration:.25
16377    },
16378    // private
16379    collapseDefaults: {
16380        duration:.25
16381    },
16382
16383    // private
16384    initComponent : function(){
16385        Ext.Panel.superclass.initComponent.call(this);
16386
16387        this.addEvents(
16388            
16389            'bodyresize',
16390            
16391            'titlechange',
16392            
16393            'iconchange',
16394            
16395            'collapse',
16396            
16397            'expand',
16398            
16399            'beforecollapse',
16400            
16401            'beforeexpand',
16402            
16403            'beforeclose',
16404            
16405            'close',
16406            
16407            'activate',
16408            
16409            'deactivate'
16410        );
16411
16412        // shortcuts
16413        if(this.tbar){
16414            this.elements += ',tbar';
16415            if(typeof this.tbar == 'object'){
16416                this.topToolbar = this.tbar;
16417            }
16418            delete this.tbar;
16419        }
16420        if(this.bbar){
16421            this.elements += ',bbar';
16422            if(typeof this.bbar == 'object'){
16423                this.bottomToolbar = this.bbar;
16424            }
16425            delete this.bbar;
16426        }
16427
16428        if(this.header === true){
16429            this.elements += ',header';
16430            delete this.header;
16431        }else if(this.title && this.header !== false){
16432            this.elements += ',header';
16433        }
16434
16435        if(this.footer === true){
16436            this.elements += ',footer';
16437            delete this.footer;
16438        }
16439
16440        if(this.buttons){
16441            var btns = this.buttons;
16442            
16443            this.buttons = [];
16444            for(var i = 0, len = btns.length; i < len; i++) {
16445                if(btns[i].render){ // button instance
16446                    btns[i].ownerCt = this;
16447                    this.buttons.push(btns[i]);
16448                }else{
16449                    this.addButton(btns[i]);
16450                }
16451            }
16452        }
16453        if(this.autoLoad){
16454            this.on('render', this.doAutoLoad, this, {delay:10});
16455        }
16456    },
16457
16458    // private
16459    createElement : function(name, pnode){
16460        if(this[name]){
16461            pnode.appendChild(this[name].dom);
16462            return;
16463        }
16464
16465        if(name === 'bwrap' || this.elements.indexOf(name) != -1){
16466            if(this[name+'Cfg']){
16467                this[name] = Ext.fly(pnode).createChild(this[name+'Cfg']);
16468            }else{
16469                var el = document.createElement('div');
16470                el.className = this[name+'Cls'];
16471                this[name] = Ext.get(pnode.appendChild(el));
16472            }
16473            if(this[name+'CssClass']){
16474                this[name].addClass(this[name+'CssClass']);
16475            }
16476            if(this[name+'Style']){
16477                this[name].applyStyles(this[name+'Style']);
16478            }
16479        }
16480    },
16481
16482    // private
16483    onRender : function(ct, position){
16484        Ext.Panel.superclass.onRender.call(this, ct, position);
16485
16486        this.createClasses();
16487
16488        if(this.el){ // existing markup
16489            this.el.addClass(this.baseCls);
16490            this.header = this.el.down('.'+this.headerCls);
16491            this.bwrap = this.el.down('.'+this.bwrapCls);
16492            var cp = this.bwrap ? this.bwrap : this.el;
16493            this.tbar = cp.down('.'+this.tbarCls);
16494            this.body = cp.down('.'+this.bodyCls);
16495            this.bbar = cp.down('.'+this.bbarCls);
16496            this.footer = cp.down('.'+this.footerCls);
16497            this.fromMarkup = true;
16498        }else{
16499            this.el = ct.createChild({
16500                id: this.id,
16501                cls: this.baseCls
16502            }, position);
16503        }
16504        var el = this.el, d = el.dom;
16505
16506        if(this.cls){
16507            this.el.addClass(this.cls);
16508        }
16509
16510        if(this.buttons){
16511            this.elements += ',footer';
16512        }
16513
16514        // This block allows for maximum flexibility and performance when using existing markup
16515
16516        // framing requires special markup
16517        if(this.frame){
16518            el.insertHtml('afterBegin', String.format(Ext.Element.boxMarkup, this.baseCls));
16519
16520            this.createElement('header', d.firstChild.firstChild.firstChild);
16521            this.createElement('bwrap', d);
16522
16523            // append the mid and bottom frame to the bwrap
16524            var bw = this.bwrap.dom;
16525            var ml = d.childNodes[1], bl = d.childNodes[2];
16526            bw.appendChild(ml);
16527            bw.appendChild(bl);
16528
16529            var mc = bw.firstChild.firstChild.firstChild;
16530            this.createElement('tbar', mc);
16531            this.createElement('body', mc);
16532            this.createElement('bbar', mc);
16533            this.createElement('footer', bw.lastChild.firstChild.firstChild);
16534
16535            if(!this.footer){
16536                this.bwrap.dom.lastChild.className += ' x-panel-nofooter';
16537            }
16538        }else{
16539            this.createElement('header', d);
16540            this.createElement('bwrap', d);
16541
16542            // append the mid and bottom frame to the bwrap
16543            var bw = this.bwrap.dom;
16544            this.createElement('tbar', bw);
16545            this.createElement('body', bw);
16546            this.createElement('bbar', bw);
16547            this.createElement('footer', bw);
16548
16549            if(!this.header){
16550                this.body.addClass(this.bodyCls + '-noheader');
16551                if(this.tbar){
16552                    this.tbar.addClass(this.tbarCls + '-noheader');
16553                }
16554            }
16555        }
16556
16557        if(this.border === false){
16558            this.el.addClass(this.baseCls + '-noborder');
16559            this.body.addClass(this.bodyCls + '-noborder');
16560            if(this.header){
16561                this.header.addClass(this.headerCls + '-noborder');
16562            }
16563            if(this.footer){
16564                this.footer.addClass(this.footerCls + '-noborder');
16565            }
16566            if(this.tbar){
16567                this.tbar.addClass(this.tbarCls + '-noborder');
16568            }
16569            if(this.bbar){
16570                this.bbar.addClass(this.bbarCls + '-noborder');
16571            }
16572        }
16573
16574        if(this.bodyBorder === false){
16575           this.body.addClass(this.bodyCls + '-noborder');
16576        }
16577
16578        this.bwrap.enableDisplayMode('block');
16579
16580        if(this.header){
16581            this.header.unselectable();
16582
16583            // for tools, we need to wrap any existing header markup
16584            if(this.headerAsText){
16585                this.header.dom.innerHTML =
16586                    '<span class="' + this.headerTextCls + '">'+this.header.dom.innerHTML+'</span>';
16587
16588                if(this.iconCls){
16589                    this.setIconClass(this.iconCls);
16590                }
16591            }
16592        }
16593
16594        if(this.floating){
16595            this.makeFloating(this.floating);
16596        }
16597
16598        if(this.collapsible){
16599            this.tools = this.tools ? this.tools.slice(0) : [];
16600            if(!this.hideCollapseTool){
16601                this.tools[this.collapseFirst?'unshift':'push']({
16602                    id: 'toggle',
16603                    handler : this.toggleCollapse,
16604                    scope: this
16605                });
16606            }
16607            if(this.titleCollapse && this.header){
16608                this.header.on('click', this.toggleCollapse, this);
16609                this.header.setStyle('cursor', 'pointer');
16610            }
16611        }
16612        if(this.tools){
16613            var ts = this.tools;
16614            this.tools = {};
16615            this.addTool.apply(this, ts);
16616        }else{
16617            this.tools = {};
16618        }
16619
16620        if(this.buttons && this.buttons.length > 0){
16621            // tables are required to maintain order and for correct IE layout
16622            var tb = this.footer.createChild({cls:'x-panel-btns-ct', cn: {
16623                cls:"x-panel-btns x-panel-btns-"+this.buttonAlign,
16624                html:'<table cellspacing="0"><tbody><tr></tr></tbody></table><div class="x-clear"></div>'
16625            }}, null, true);
16626            var tr = tb.getElementsByTagName('tr')[0];
16627            for(var i = 0, len = this.buttons.length; i < len; i++) {
16628                var b = this.buttons[i];
16629                var td = document.createElement('td');
16630                td.className = 'x-panel-btn-td';
16631                b.render(tr.appendChild(td));
16632            }
16633        }
16634
16635        if(this.tbar && this.topToolbar){
16636            if(Ext.isArray(this.topToolbar)){
16637                this.topToolbar = new Ext.Toolbar(this.topToolbar);
16638            }
16639            this.topToolbar.render(this.tbar);
16640            this.topToolbar.ownerCt = this;
16641        }
16642        if(this.bbar && this.bottomToolbar){
16643            if(Ext.isArray(this.bottomToolbar)){
16644                this.bottomToolbar = new Ext.Toolbar(this.bottomToolbar);
16645            }
16646            this.bottomToolbar.render(this.bbar);
16647            this.bottomToolbar.ownerCt = this;
16648        }
16649    },
16650
16651    
16652    setIconClass : function(cls){
16653        var old = this.iconCls;
16654        this.iconCls = cls;
16655        if(this.rendered && this.header){
16656            if(this.frame){
16657                this.header.addClass('x-panel-icon');
16658                this.header.replaceClass(old, this.iconCls);
16659            }else{
16660                var hd = this.header.dom;
16661                var img = hd.firstChild && String(hd.firstChild.tagName).toLowerCase() == 'img' ? hd.firstChild : null;
16662                if(img){
16663                    Ext.fly(img).replaceClass(old, this.iconCls);
16664                }else{
16665                    Ext.DomHelper.insertBefore(hd.firstChild, {
16666                        tag:'img', src: Ext.BLANK_IMAGE_URL, cls:'x-panel-inline-icon '+this.iconCls
16667                    });
16668                 }
16669            }
16670        }
16671        this.fireEvent('iconchange', this, cls, old);
16672    },
16673
16674    // private
16675    makeFloating : function(cfg){
16676        this.floating = true;
16677        this.el = new Ext.Layer(
16678            typeof cfg == 'object' ? cfg : {
16679                shadow: this.shadow !== undefined ? this.shadow : 'sides',
16680                shadowOffset: this.shadowOffset,
16681                constrain:false,
16682                shim: this.shim === false ? false : undefined
16683            }, this.el
16684        );
16685    },
16686
16687    
16688    getTopToolbar : function(){
16689        return this.topToolbar;
16690    },
16691
16692    
16693    getBottomToolbar : function(){
16694        return this.bottomToolbar;
16695    },
16696
16697    
16698    addButton : function(config, handler, scope){
16699        var bc = {
16700            handler: handler,
16701            scope: scope,
16702            minWidth: this.minButtonWidth,
16703            hideParent:true
16704        };
16705        if(typeof config == "string"){
16706            bc.text = config;
16707        }else{
16708            Ext.apply(bc, config);
16709        }
16710        var btn = new Ext.Button(bc);
16711        btn.ownerCt = this;
16712        if(!this.buttons){
16713            this.buttons = [];
16714        }
16715        this.buttons.push(btn);
16716        return btn;
16717    },
16718
16719    // private
16720    addTool : function(){
16721        if(!this[this.toolTarget]) { // no where to render tools!
16722            return;
16723        }
16724        if(!this.toolTemplate){
16725            // initialize the global tool template on first use
16726            var tt = new Ext.Template(
16727                 '<div class="x-tool x-tool-{id}">&#160;</div>'
16728            );
16729            tt.disableFormats = true;
16730            tt.compile();
16731            Ext.Panel.prototype.toolTemplate = tt;
16732        }
16733        for(var i = 0, a = arguments, len = a.length; i < len; i++) {
16734            var tc = a[i];
16735            if(!this.tools[tc.id]){
16736	            var overCls = 'x-tool-'+tc.id+'-over';
16737	            var t = this.toolTemplate.insertFirst((tc.align !== 'left') ? this[this.toolTarget] : this[this.toolTarget].child('span'), tc, true);
16738	            this.tools[tc.id] = t;
16739	            t.enableDisplayMode('block');
16740	            t.on('click', this.createToolHandler(t, tc, overCls, this));
16741	            if(tc.on){
16742	                t.on(tc.on);
16743	            }
16744	            if(tc.hidden){
16745	                t.hide();
16746	            }
16747	            if(tc.qtip){
16748	                if(typeof tc.qtip == 'object'){
16749	                    Ext.QuickTips.register(Ext.apply({
16750	                          target: t.id
16751	                    }, tc.qtip));
16752	                } else {
16753	                    t.dom.qtip = tc.qtip;
16754	                }
16755	            }
16756	            t.addClassOnOver(overCls);
16757            }
16758        }
16759    },
16760
16761    // private
16762    onShow : function(){
16763        if(this.floating){
16764            return this.el.show();
16765        }
16766        Ext.Panel.superclass.onShow.call(this);
16767    },
16768
16769    // private
16770    onHide : function(){
16771        if(this.floating){
16772            return this.el.hide();
16773        }
16774        Ext.Panel.superclass.onHide.call(this);
16775    },
16776
16777    // private
16778    createToolHandler : function(t, tc, overCls, panel){
16779        return function(e){
16780            t.removeClass(overCls);
16781            e.stopEvent();
16782            if(tc.handler){
16783                tc.handler.call(tc.scope || t, e, t, panel);
16784            }
16785        };
16786    },
16787
16788    // private
16789    afterRender : function(){
16790        if(this.fromMarkup && this.height === undefined && !this.autoHeight){
16791            this.height = this.el.getHeight();
16792        }
16793        if(this.floating && !this.hidden && !this.initHidden){
16794            this.el.show();
16795        }
16796        if(this.title){
16797            this.setTitle(this.title);
16798        }
16799        this.setAutoScroll();
16800        if(this.html){
16801            this.body.update(typeof this.html == 'object' ?
16802                             Ext.DomHelper.markup(this.html) :
16803                             this.html);
16804            delete this.html;
16805        }
16806        if(this.contentEl){
16807            var ce = Ext.getDom(this.contentEl);
16808            Ext.fly(ce).removeClass(['x-hidden', 'x-hide-display']);
16809            this.body.dom.appendChild(ce);
16810        }
16811        if(this.collapsed){
16812            this.collapsed = false;
16813            this.collapse(false);
16814        }
16815        Ext.Panel.superclass.afterRender.call(this); // do sizing calcs last
16816        this.initEvents();
16817    },
16818
16819    // private
16820    setAutoScroll : function(){
16821        if(this.rendered && this.autoScroll){
16822            var el = this.body || this.el;
16823            if(el){
16824                el.setOverflow('auto');
16825            }
16826        }
16827    },
16828
16829    // private
16830    getKeyMap : function(){
16831        if(!this.keyMap){
16832            this.keyMap = new Ext.KeyMap(this.el, this.keys);
16833        }
16834        return this.keyMap;
16835    },
16836
16837    // private
16838    initEvents : function(){
16839        if(this.keys){
16840            this.getKeyMap();
16841        }
16842        if(this.draggable){
16843            this.initDraggable();
16844        }
16845    },
16846
16847    // private
16848    initDraggable : function(){
16849        
16850        this.dd = new Ext.Panel.DD(this, typeof this.draggable == 'boolean' ? null : this.draggable);
16851    },
16852
16853    // private
16854    beforeEffect : function(){
16855        if(this.floating){
16856            this.el.beforeAction();
16857        }
16858        this.el.addClass('x-panel-animated');
16859    },
16860
16861    // private
16862    afterEffect : function(){
16863        this.syncShadow();
16864        this.el.removeClass('x-panel-animated');
16865    },
16866
16867    // private - wraps up an animation param with internal callbacks
16868    createEffect : function(a, cb, scope){
16869        var o = {
16870            scope:scope,
16871            block:true
16872        };
16873        if(a === true){
16874            o.callback = cb;
16875            return o;
16876        }else if(!a.callback){
16877            o.callback = cb;
16878        }else { // wrap it up
16879            o.callback = function(){
16880                cb.call(scope);
16881                Ext.callback(a.callback, a.scope);
16882            };
16883        }
16884        return Ext.applyIf(o, a);
16885    },
16886
16887    
16888    collapse : function(animate){
16889        if(this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforecollapse', this, animate) === false){
16890            return;
16891        }
16892        var doAnim = animate === true || (animate !== false && this.animCollapse);
16893        this.beforeEffect();
16894        this.onCollapse(doAnim, animate);
16895        return this;
16896    },
16897
16898    // private
16899    onCollapse : function(doAnim, animArg){
16900        if(doAnim){
16901            this[this.collapseEl].slideOut(this.slideAnchor,
16902                    Ext.apply(this.createEffect(animArg||true, this.afterCollapse, this),
16903                        this.collapseDefaults));
16904        }else{
16905            this[this.collapseEl].hide();
16906            this.afterCollapse();
16907        }
16908    },
16909
16910    // private
16911    afterCollapse : function(){
16912        this.collapsed = true;
16913        this.el.addClass(this.collapsedCls);
16914        this.afterEffect();
16915        this.fireEvent('collapse', this);
16916    },
16917
16918    
16919    expand : function(animate){
16920        if(!this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforeexpand', this, animate) === false){
16921            return;
16922        }
16923        var doAnim = animate === true || (animate !== false && this.animCollapse);
16924        this.el.removeClass(this.collapsedCls);
16925        this.beforeEffect();
16926        this.onExpand(doAnim, animate);
16927        return this;
16928    },
16929
16930    // private
16931    onExpand : function(doAnim, animArg){
16932        if(doAnim){
16933            this[this.collapseEl].slideIn(this.slideAnchor,
16934                    Ext.apply(this.createEffect(animArg||true, this.afterExpand, this),
16935                        this.expandDefaults));
16936        }else{
16937            this[this.collapseEl].show();
16938            this.afterExpand();
16939        }
16940    },
16941
16942    // private
16943    afterExpand : function(){
16944        this.collapsed = false;
16945        this.afterEffect();
16946        this.fireEvent('expand', this);
16947    },
16948
16949    
16950    toggleCollapse : function(animate){
16951        this[this.collapsed ? 'expand' : 'collapse'](animate);
16952        return this;
16953    },
16954
16955    // private
16956    onDisable : function(){
16957        if(this.rendered && this.maskDisabled){
16958            this.el.mask();
16959        }
16960        Ext.Panel.superclass.onDisable.call(this);
16961    },
16962
16963    // private
16964    onEnable : function(){
16965        if(this.rendered && this.maskDisabled){
16966            this.el.unmask();
16967        }
16968        Ext.Panel.superclass.onEnable.call(this);
16969    },
16970
16971    // private
16972    onResize : function(w, h){
16973        if(w !== undefined || h !== undefined){
16974            if(!this.collapsed){
16975                if(typeof w == 'number'){
16976                    this.body.setWidth(
16977                            this.adjustBodyWidth(w - this.getFrameWidth()));
16978                }else if(w == 'auto'){
16979                    this.body.setWidth(w);
16980                }
16981
16982                if(typeof h == 'number'){
16983                    this.body.setHeight(
16984                            this.adjustBodyHeight(h - this.getFrameHeight()));
16985                }else if(h == 'auto'){
16986                    this.body.setHeight(h);
16987                }
16988                
16989                if(this.disabled && this.el._mask){
16990                    this.el._mask.setSize(this.el.dom.clientWidth, this.el.getHeight());
16991                }
16992            }else{
16993                this.queuedBodySize = {width: w, height: h};
16994                if(!this.queuedExpand && this.allowQueuedExpand !== false){
16995                    this.queuedExpand = true;
16996                    this.on('expand', function(){
16997                        delete this.queuedExpand;
16998                        this.onResize(this.queuedBodySize.width, this.queuedBodySize.height);
16999                        this.doLayout();
17000                    }, this, {single:true});
17001                }
17002            }
17003            this.fireEvent('bodyresize', this, w, h);
17004        }
17005        this.syncShadow();
17006    },
17007
17008    // private
17009    adjustBodyHeight : function(h){
17010        return h;
17011    },
17012
17013    // private
17014    adjustBodyWidth : function(w){
17015        return w;
17016    },
17017
17018    // private
17019    onPosition : function(){
17020        this.syncShadow();
17021    },
17022
17023    
17024    getFrameWidth : function(){
17025        var w = this.el.getFrameWidth('lr');
17026
17027        if(this.frame){
17028            var l = this.bwrap.dom.firstChild;
17029            w += (Ext.fly(l).getFrameWidth('l') + Ext.fly(l.firstChild).getFrameWidth('r'));
17030            var mc = this.bwrap.dom.firstChild.firstChild.firstChild;
17031            w += Ext.fly(mc).getFrameWidth('lr');
17032        }
17033        return w;
17034    },
17035
17036    
17037    getFrameHeight : function(){
17038        var h  = this.el.getFrameWidth('tb');
17039        h += (this.tbar ? this.tbar.getHeight() : 0) +
17040             (this.bbar ? this.bbar.getHeight() : 0);
17041
17042        if(this.frame){
17043            var hd = this.el.dom.firstChild;
17044            var ft = this.bwrap.dom.lastChild;
17045            h += (hd.offsetHeight + ft.offsetHeight);
17046            var mc = this.bwrap.dom.firstChild.firstChild.firstChild;
17047            h += Ext.fly(mc).getFrameWidth('tb');
17048        }else{
17049            h += (this.header ? this.header.getHeight() : 0) +
17050                (this.footer ? this.footer.getHeight() : 0);
17051        }
17052        return h;
17053    },
17054
17055    
17056    getInnerWidth : function(){
17057        return this.getSize().width - this.getFrameWidth();
17058    },
17059
17060    
17061    getInnerHeight : function(){
17062        return this.getSize().height - this.getFrameHeight();
17063    },
17064
17065    // private
17066    syncShadow : function(){
17067        if(this.floating){
17068            this.el.sync(true);
17069        }
17070    },
17071
17072    // private
17073    getLayoutTarget : function(){
17074        return this.body;
17075    },
17076
17077    
17078    setTitle : function(title, iconCls){
17079        this.title = title;
17080        if(this.header && this.headerAsText){
17081            this.header.child('span').update(title);
17082        }
17083        if(iconCls){
17084            this.setIconClass(iconCls);
17085        }
17086        this.fireEvent('titlechange', this, title);
17087        return this;
17088    },
17089
17090    
17091    getUpdater : function(){
17092        return this.body.getUpdater();
17093    },
17094
17095     
17096    load : function(){
17097        var um = this.body.getUpdater();
17098        um.update.apply(um, arguments);
17099        return this;
17100    },
17101
17102    // private
17103    beforeDestroy : function(){
17104        if(this.header){
17105            this.header.removeAllListeners();
17106            if(this.headerAsText){
17107                Ext.Element.uncache(this.header.child('span'));
17108            }
17109        }
17110        Ext.Element.uncache(
17111            this.header,
17112            this.tbar,
17113            this.bbar,
17114            this.footer,
17115            this.body,
17116            this.bwrap
17117        );
17118        if(this.tools){
17119            for(var k in this.tools){
17120                Ext.destroy(this.tools[k]);
17121            }
17122        }
17123        if(this.buttons){
17124            for(var b in this.buttons){
17125                Ext.destroy(this.buttons[b]);
17126            }
17127        }
17128        Ext.destroy(
17129            this.topToolbar,
17130            this.bottomToolbar
17131        );
17132        Ext.Panel.superclass.beforeDestroy.call(this);
17133    },
17134
17135    // private
17136    createClasses : function(){
17137        this.headerCls = this.baseCls + '-header';
17138        this.headerTextCls = this.baseCls + '-header-text';
17139        this.bwrapCls = this.baseCls + '-bwrap';
17140        this.tbarCls = this.baseCls + '-tbar';
17141        this.bodyCls = this.baseCls + '-body';
17142        this.bbarCls = this.baseCls + '-bbar';
17143        this.footerCls = this.baseCls + '-footer';
17144    },
17145
17146    // private
17147    createGhost : function(cls, useShim, appendTo){
17148        var el = document.createElement('div');
17149        el.className = 'x-panel-ghost ' + (cls ? cls : '');
17150        if(this.header){
17151            el.appendChild(this.el.dom.firstChild.cloneNode(true));
17152        }
17153        Ext.fly(el.appendChild(document.createElement('ul'))).setHeight(this.bwrap.getHeight());
17154        el.style.width = this.el.dom.offsetWidth + 'px';;
17155        if(!appendTo){
17156            this.container.dom.appendChild(el);
17157        }else{
17158            Ext.getDom(appendTo).appendChild(el);
17159        }
17160        if(useShim !== false && this.el.useShim !== false){
17161            var layer = new Ext.Layer({shadow:false, useDisplay:true, constrain:false}, el);
17162            layer.show();
17163            return layer;
17164        }else{
17165            return new Ext.Element(el);
17166        }
17167    },
17168
17169    // private
17170    doAutoLoad : function(){
17171        this.body.load(
17172            typeof this.autoLoad == 'object' ?
17173                this.autoLoad : {url: this.autoLoad});
17174    },
17175    
17176    
17177    getTool: function(id) {
17178        return this.tools[id];
17179    }
17180
17181
17182});
17183Ext.reg('panel', Ext.Panel);
17184
17185
17186Ext.Window = Ext.extend(Ext.Panel, {
17187    
17188    
17189    
17190    
17191    
17192    
17193    
17194    
17195    
17196    
17197    
17198    
17199    baseCls : 'x-window',
17200    
17201    resizable:true,
17202    
17203    draggable:true,
17204    
17205    closable : true,
17206    
17207    constrain:false,
17208    
17209    constrainHeader:false,
17210    
17211    plain:false,
17212    
17213    minimizable : false,
17214    
17215    maximizable : false,
17216    
17217    minHeight: 100,
17218    
17219    minWidth: 200,
17220    
17221    expandOnShow: true,
17222    
17223    closeAction: 'close',
17224    
17225    elements: 'header,body',
17226
17227    // inherited docs, same default
17228    collapsible:false,
17229
17230    // private
17231    initHidden : true,
17232    
17233    monitorResize : true,
17234    
17235    frame:true,
17236    
17237    floating:true,
17238
17239    // private
17240    initComponent : function(){
17241        Ext.Window.superclass.initComponent.call(this);
17242        this.addEvents(
17243            
17244            
17245            
17246            'resize',
17247            
17248            'maximize',
17249            
17250            'minimize',
17251            
17252            'restore'
17253        );
17254    },
17255
17256    // private
17257    getState : function(){
17258        return Ext.apply(Ext.Window.superclass.getState.call(this) || {}, this.getBox());
17259    },
17260
17261    // private
17262    onRender : function(ct, position){
17263        Ext.Window.superclass.onRender.call(this, ct, position);
17264
17265        if(this.plain){
17266            this.el.addClass('x-window-plain');
17267        }
17268
17269        // this element allows the Window to be focused for keyboard events
17270        this.focusEl = this.el.createChild({
17271                    tag: "a", href:"#", cls:"x-dlg-focus",
17272                    tabIndex:"-1", html: "&#160;"});
17273        this.focusEl.swallowEvent('click', true);
17274
17275        this.proxy = this.el.createProxy("x-window-proxy");
17276        this.proxy.enableDisplayMode('block');
17277
17278        if(this.modal){
17279            this.mask = this.container.createChild({cls:"ext-el-mask"}, this.el.dom);
17280            this.mask.enableDisplayMode("block");
17281            this.mask.hide();
17282            this.mask.on('click', this.focus, this);
17283        }
17284    },
17285
17286    // private
17287    initEvents : function(){
17288        Ext.Window.superclass.initEvents.call(this);
17289        if(this.animateTarget){
17290            this.setAnimateTarget(this.animateTarget);
17291        }
17292
17293        if(this.resizable){
17294            this.resizer = new Ext.Resizable(this.el, {
17295                minWidth: this.minWidth,
17296                minHeight:this.minHeight,
17297                handles: this.resizeHandles || "all",
17298                pinned: true,
17299                resizeElement : this.resizerAction
17300            });
17301            this.resizer.window = this;
17302            this.resizer.on("beforeresize", this.beforeResize, this);
17303        }
17304
17305        if(this.draggable){
17306            this.header.addClass("x-window-draggable");
17307        }
17308        this.initTools();
17309
17310        this.el.on("mousedown", this.toFront, this);
17311        this.manager = this.manager || Ext.WindowMgr;
17312        this.manager.register(this);
17313        this.hidden = true;
17314        if(this.maximized){
17315            this.maximized = false;
17316            this.maximize();
17317        }
17318        if(this.closable){
17319            var km = this.getKeyMap();
17320            km.on(27, this.onEsc, this);
17321            km.disable();
17322        }
17323    },
17324
17325    initDraggable : function(){
17326        
17327        this.dd = new Ext.Window.DD(this);
17328    },
17329
17330   // private
17331    onEsc : function(){
17332        this[this.closeAction]();
17333    },
17334
17335    // private
17336    beforeDestroy : function(){
17337        this.hide();
17338        if(this.doAnchor){
17339            Ext.EventManager.removeResizeListener(this.doAnchor, this);
17340            Ext.EventManager.un(window, 'scroll', this.doAnchor, this);
17341        }
17342        Ext.destroy(
17343            this.focusEl,
17344            this.resizer,
17345            this.dd,
17346            this.proxy,
17347            this.mask
17348        );
17349        Ext.Window.superclass.beforeDestroy.call(this);
17350    },
17351
17352    // private
17353    onDestroy : function(){
17354        if(this.manager){
17355            this.manager.unregister(this);
17356        }
17357        Ext.Window.superclass.onDestroy.call(this);
17358    },
17359
17360    // private
17361    initTools : function(){
17362        if(this.minimizable){
17363            this.addTool({
17364                id: 'minimize',
17365                handler: this.minimize.createDelegate(this, [])
17366            });
17367        }
17368        if(this.maximizable){
17369            this.addTool({
17370                id: 'maximize',
17371                handler: this.maximize.createDelegate(this, [])
17372            });
17373            this.addTool({
17374                id: 'restore',
17375                handler: this.restore.createDelegate(this, []),
17376                hidden:true
17377            });
17378            this.header.on('dblclick', this.toggleMaximize, this);
17379        }
17380        if(this.closable){
17381            this.addTool({
17382                id: 'close',
17383                handler: this[this.closeAction].createDelegate(this, [])
17384            });
17385        }
17386    },
17387
17388    // private
17389    resizerAction : function(){
17390        var box = this.proxy.getBox();
17391        this.proxy.hide();
17392        this.window.handleResize(box);
17393        return box;
17394    },
17395
17396    // private
17397    beforeResize : function(){
17398        this.resizer.minHeight = Math.max(this.minHeight, this.getFrameHeight() + 40); // 40 is a magic minimum content size?
17399        this.resizer.minWidth = Math.max(this.minWidth, this.getFrameWidth() + 40);
17400        this.resizeBox = this.el.getBox();
17401    },
17402
17403    // private
17404    updateHandles : function(){
17405        if(Ext.isIE && this.resizer){
17406            this.resizer.syncHandleHeight();
17407            this.el.repaint();
17408        }
17409    },
17410
17411    // private
17412    handleResize : function(box){
17413        var rz = this.resizeBox;
17414        if(rz.x != box.x || rz.y != box.y){
17415            this.updateBox(box);
17416        }else{
17417            this.setSize(box);
17418        }
17419        this.focus();
17420        this.updateHandles();
17421        this.saveState();
17422        if(this.layout){
17423            this.doLayout();
17424        }
17425        this.fireEvent("resize", this, box.width, box.height);
17426    },
17427
17428    
17429    focus : function(){
17430        var f = this.focusEl, db = this.defaultButton, t = typeof db;
17431        if(t != 'undefined'){
17432            if(t == 'number'){
17433                f = this.buttons[db];
17434            }else if(t == 'string'){
17435                f = Ext.getCmp(db);
17436            }else{
17437                f = db;
17438            }
17439        }
17440        f.focus.defer(10, f);
17441    },
17442
17443    
17444    setAnimateTarget : function(el){
17445        el = Ext.get(el);
17446        this.animateTarget = el;
17447    },
17448
17449    // private
17450    beforeShow : function(){
17451        delete this.el.lastXY;
17452        delete this.el.lastLT;
17453        if(this.x === undefined || this.y === undefined){
17454            var xy = this.el.getAlignToXY(this.container, 'c-c');
17455            var pos = this.el.translatePoints(xy[0], xy[1]);
17456            this.x = this.x === undefined? pos.left : this.x;
17457            this.y = this.y === undefined? pos.top : this.y;
17458        }
17459        this.el.setLeftTop(this.x, this.y);
17460
17461        if(this.expandOnShow){
17462            this.expand(false);
17463        }
17464
17465        if(this.modal){
17466            Ext.getBody().addClass("x-body-masked");
17467            this.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
17468            this.mask.show();
17469        }
17470    },
17471
17472    
17473    show : function(animateTarget, cb, scope){
17474        if(!this.rendered){
17475            this.render(Ext.getBody());
17476        }
17477        if(this.hidden === false){
17478            this.toFront();
17479            return;
17480        }
17481        if(this.fireEvent("beforeshow", this) === false){
17482            return;
17483        }
17484        if(cb){
17485            this.on('show', cb, scope, {single:true});
17486        }
17487        this.hidden = false;
17488        if(animateTarget !== undefined){
17489            this.setAnimateTarget(animateTarget);
17490        }
17491        this.beforeShow();
17492        if(this.animateTarget){
17493            this.animShow();
17494        }else{
17495            this.afterShow();
17496        }
17497    },
17498
17499    // private
17500    afterShow : function(){
17501        this.proxy.hide();
17502        this.el.setStyle('display', 'block');
17503        this.el.show();
17504        if(this.maximized){
17505            this.fitContainer();
17506        }
17507        if(Ext.isMac && Ext.isGecko){ // work around stupid FF 2.0/Mac scroll bar bug
17508        	this.cascade(this.setAutoScroll);
17509        }
17510
17511        if(this.monitorResize || this.modal || this.constrain || this.constrainHeader){
17512            Ext.EventManager.onWindowResize(this.onWindowResize, this);
17513        }
17514        this.doConstrain();
17515        if(this.layout){
17516            this.doLayout();
17517        }
17518        if(this.keyMap){
17519            this.keyMap.enable();
17520        }
17521        this.toFront();
17522        this.updateHandles();
17523        this.fireEvent("show", this);
17524    },
17525
17526    // private
17527    animShow : function(){
17528        this.proxy.show();
17529        this.proxy.setBox(this.animateTarget.getBox());
17530        this.proxy.setOpacity(0);
17531        var b = this.getBox(false);
17532        b.callback = this.afterShow;
17533        b.scope = this;
17534        b.duration = .25;
17535        b.easing = 'easeNone';
17536        b.opacity = .5;
17537        b.block = true;
17538        this.el.setStyle('display', 'none');
17539        this.proxy.shift(b);
17540    },
17541
17542    
17543    hide : function(animateTarget, cb, scope){
17544        if(this.activeGhost){ // drag active?
17545            this.hide.defer(100, this, [animateTarget, cb, scope]);
17546            return;
17547        }
17548        if(this.hidden || this.fireEvent("beforehide", this) === false){
17549            return;
17550        }
17551        if(cb){
17552            this.on('hide', cb, scope, {single:true});
17553        }
17554        this.hidden = true;
17555        if(animateTarget !== undefined){
17556            this.setAnimateTarget(animateTarget);
17557        }
17558        if(this.animateTarget){
17559            this.animHide();
17560        }else{
17561            this.el.hide();
17562            this.afterHide();
17563        }
17564    },
17565
17566    // private
17567    afterHide : function(){
17568        this.proxy.hide();
17569        if(this.monitorResize || this.modal || this.constrain || this.constrainHeader){
17570            Ext.EventManager.removeResizeListener(this.onWindowResize, this);
17571        }
17572        if(this.modal){
17573            this.mask.hide();
17574            Ext.getBody().removeClass("x-body-masked");
17575        }
17576        if(this.keyMap){
17577            this.keyMap.disable();
17578        }
17579        this.fireEvent("hide", this);
17580    },
17581
17582    // private
17583    animHide : function(){
17584        this.proxy.setOpacity(.5);
17585        this.proxy.show();
17586        var tb = this.getBox(false);
17587        this.proxy.setBox(tb);
17588        this.el.hide();
17589        var b = this.animateTarget.getBox();
17590        b.callback = this.afterHide;
17591        b.scope = this;
17592        b.duration = .25;
17593        b.easing = 'easeNone';
17594        b.block = true;
17595        b.opacity = 0;
17596        this.proxy.shift(b);
17597    },
17598
17599    // private
17600    onWindowResize : function(){
17601        if(this.maximized){
17602            this.fitContainer();
17603        }
17604        if(this.modal){
17605            this.mask.setSize('100%', '100%');
17606            var force = this.mask.dom.offsetHeight;
17607            this.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
17608        }
17609        this.doConstrain();
17610    },
17611
17612    // private
17613    doConstrain : function(){
17614        if(this.constrain || this.constrainHeader){
17615            var offsets;
17616            if(this.constrain){
17617                offsets = {
17618                    right:this.el.shadowOffset,
17619                    left:this.el.shadowOffset,
17620                    bottom:this.el.shadowOffset
17621                };
17622            }else {
17623                var s = this.getSize();
17624                offsets = {
17625                    right:-(s.width - 100),
17626                    bottom:-(s.height - 25)
17627                };
17628            }
17629
17630            var xy = this.el.getConstrainToXY(this.container, true, offsets);
17631            if(xy){
17632                this.setPosition(xy[0], xy[1]);
17633            }
17634        }
17635    },
17636
17637    // private - used for dragging
17638    ghost : function(cls){
17639        var ghost = this.createGhost(cls);
17640        var box = this.getBox(true);
17641        ghost.setLeftTop(box.x, box.y);
17642        ghost.setWidth(box.width);
17643        this.el.hide();
17644        this.activeGhost = ghost;
17645        return ghost;
17646    },
17647
17648    // private
17649    unghost : function(show, matchPosition){
17650        if(show !== false){
17651            this.el.show();
17652            this.focus();
17653	        if(Ext.isMac && Ext.isGecko){ // work around stupid FF 2.0/Mac scroll bar bug
17654	        	this.cascade(this.setAutoScroll);
17655	        }
17656        }
17657        if(matchPosition !== false){
17658            this.setPosition(this.activeGhost.getLeft(true), this.activeGhost.getTop(true));
17659        }
17660        this.activeGhost.hide();
17661        this.activeGhost.remove();
17662        delete this.activeGhost;
17663    },
17664
17665    
17666    minimize : function(){
17667        this.fireEvent('minimize', this);
17668    },
17669
17670    
17671    close : function(){
17672        if(this.fireEvent("beforeclose", this) !== false){
17673            this.hide(null, function(){
17674                this.fireEvent('close', this);
17675                this.destroy();
17676            }, this);
17677        }
17678    },
17679
17680    
17681    maximize : function(){
17682        if(!this.maximized){
17683            this.expand(false);
17684            this.restoreSize = this.getSize();
17685            this.restorePos = this.getPosition(true);
17686            if (this.maximizable){
17687                this.tools.maximize.hide();
17688                this.tools.restore.show();
17689            }
17690            this.maximized = true;
17691            this.el.disableShadow();
17692
17693            if(this.dd){
17694                this.dd.lock();
17695            }
17696            if(this.collapsible){
17697                this.tools.toggle.hide();
17698            }
17699            this.el.addClass('x-window-maximized');
17700            this.container.addClass('x-window-maximized-ct');
17701
17702            this.setPosition(0, 0);
17703            this.fitContainer();
17704            this.fireEvent('maximize', this);
17705        }
17706    },
17707
17708    
17709    restore : function(){
17710        if(this.maximized){
17711            this.el.removeClass('x-window-maximized');
17712            this.tools.restore.hide();
17713            this.tools.maximize.show();
17714            this.setPosition(this.restorePos[0], this.restorePos[1]);
17715            this.setSize(this.restoreSize.width, this.restoreSize.height);
17716            delete this.restorePos;
17717            delete this.restoreSize;
17718            this.maximized = false;
17719            this.el.enableShadow(true);
17720
17721            if(this.dd){
17722                this.dd.unlock();
17723            }
17724            if(this.collapsible){
17725                this.tools.toggle.show();
17726            }
17727            this.container.removeClass('x-window-maximized-ct');
17728
17729            this.doConstrain();
17730            this.fireEvent('restore', this);
17731        }
17732    },
17733
17734    
17735    toggleMaximize : function(){
17736        this[this.maximized ? 'restore' : 'maximize']();
17737    },
17738
17739    // private
17740    fitContainer : function(){
17741        var vs = this.container.getViewSize();
17742        this.setSize(vs.width, vs.height);
17743    },
17744
17745    // private
17746    // z-index is managed by the WindowManager and may be overwritten at any time
17747    setZIndex : function(index){
17748        if(this.modal){
17749            this.mask.setStyle("z-index", index);
17750        }
17751        this.el.setZIndex(++index);
17752        index += 5;
17753
17754        if(this.resizer){
17755            this.resizer.proxy.setStyle("z-index", ++index);
17756        }
17757
17758        this.lastZIndex = index;
17759    },
17760
17761    
17762    alignTo : function(element, position, offsets){
17763        var xy = this.el.getAlignToXY(element, position, offsets);
17764        this.setPagePosition(xy[0], xy[1]);
17765        return this;
17766    },
17767
17768    
17769    anchorTo : function(el, alignment, offsets, monitorScroll){
17770      if(this.doAnchor){
17771          Ext.EventManager.removeResizeListener(this.doAnchor, this);
17772          Ext.EventManager.un(window, 'scroll', this.doAnchor, this);
17773      }
17774      this.doAnchor = function(){
17775          this.alignTo(el, alignment, offsets);
17776      };
17777      Ext.EventManager.onWindowResize(this.doAnchor, this);
17778      
17779      var tm = typeof monitorScroll;
17780      if(tm != 'undefined'){
17781          Ext.EventManager.on(window, 'scroll', this.doAnchor, this,
17782              {buffer: tm == 'number' ? monitorScroll : 50});
17783      }
17784      this.doAnchor();
17785      return this;
17786    },
17787
17788    
17789    toFront : function(e){
17790        if(this.manager.bringToFront(this)){
17791            if(!e || !e.getTarget().focus){
17792                this.focus();
17793            }
17794        }
17795        return this;
17796    },
17797
17798    
17799    setActive : function(active){
17800        if(active){
17801            if(!this.maximized){
17802                this.el.enableShadow(true);
17803            }
17804            this.fireEvent('activate', this);
17805        }else{
17806            this.el.disableShadow();
17807            this.fireEvent('deactivate', this);
17808        }
17809    },
17810
17811    
17812    toBack : function(){
17813        this.manager.sendToBack(this);
17814        return this;
17815    },
17816
17817    
17818    center : function(){
17819        var xy = this.el.getAlignToXY(this.container, 'c-c');
17820        this.setPagePosition(xy[0], xy[1]);
17821        return this;
17822    }
17823
17824    
17825});
17826Ext.reg('window', Ext.Window);
17827
17828// private - custom Window DD implementation
17829Ext.Window.DD = function(win){
17830    this.win = win;
17831    Ext.Window.DD.superclass.constructor.call(this, win.el.id, 'WindowDD-'+win.id);
17832    this.setHandleElId(win.header.id);
17833    this.scroll = false;
17834};
17835
17836Ext.extend(Ext.Window.DD, Ext.dd.DD, {
17837    moveOnly:true,
17838    headerOffsets:[100, 25],
17839    startDrag : function(){
17840        var w = this.win;
17841        this.proxy = w.ghost();
17842        if(w.constrain !== false){
17843            var so = w.el.shadowOffset;
17844            this.constrainTo(w.container, {right: so, left: so, bottom: so});
17845        }else if(w.constrainHeader !== false){
17846            var s = this.proxy.getSize();
17847            this.constrainTo(w.container, {right: -(s.width-this.headerOffsets[0]), bottom: -(s.height-this.headerOffsets[1])});
17848        }
17849    },
17850    b4Drag : Ext.emptyFn,
17851
17852    onDrag : function(e){
17853        this.alignElWithMouse(this.proxy, e.getPageX(), e.getPageY());
17854    },
17855
17856    endDrag : function(e){
17857        this.win.unghost();
17858        this.win.saveState();
17859    }
17860});
17861
17862
17863Ext.WindowGroup = function(){
17864    var list = {};
17865    var accessList = [];
17866    var front = null;
17867
17868    // private
17869    var sortWindows = function(d1, d2){
17870        return (!d1._lastAccess || d1._lastAccess < d2._lastAccess) ? -1 : 1;
17871    };
17872
17873    // private
17874    var orderWindows = function(){
17875        var a = accessList, len = a.length;
17876        if(len > 0){
17877            a.sort(sortWindows);
17878            var seed = a[0].manager.zseed;
17879            for(var i = 0; i < len; i++){
17880                var win = a[i];
17881                if(win && !win.hidden){
17882                    win.setZIndex(seed + (i*10));
17883                }
17884            }
17885        }
17886        activateLast();
17887    };
17888
17889    // private
17890    var setActiveWin = function(win){
17891        if(win != front){
17892            if(front){
17893                front.setActive(false);
17894            }
17895            front = win;
17896            if(win){
17897                win.setActive(true);
17898            }
17899        }
17900    };
17901
17902    // private
17903    var activateLast = function(){
17904        for(var i = accessList.length-1; i >=0; --i) {
17905            if(!accessList[i].hidden){
17906                setActiveWin(accessList[i]);
17907                return;
17908            }
17909        }
17910        // none to activate
17911        setActiveWin(null);
17912    };
17913
17914    return {
17915        
17916        zseed : 9000,
17917
17918        // private
17919        register : function(win){
17920            list[win.id] = win;
17921            accessList.push(win);
17922            win.on('hide', activateLast);
17923        },
17924
17925        // private
17926        unregister : function(win){
17927            delete list[win.id];
17928            win.un('hide', activateLast);
17929            accessList.remove(win);
17930        },
17931
17932        
17933        get : function(id){
17934            return typeof id == "object" ? id : list[id];
17935        },
17936
17937        
17938        bringToFront : function(win){
17939            win = this.get(win);
17940            if(win != front){
17941                win._lastAccess = new Date().getTime();
17942                orderWindows();
17943                return true;
17944            }
17945            return false;
17946        },
17947
17948        
17949        sendToBack : function(win){
17950            win = this.get(win);
17951            win._lastAccess = -(new Date().getTime());
17952            orderWindows();
17953            return win;
17954        },
17955
17956        
17957        hideAll : function(){
17958            for(var id in list){
17959                if(list[id] && typeof list[id] != "function" && list[id].isVisible()){
17960                    list[id].hide();
17961                }
17962            }
17963        },
17964
17965        
17966        getActive : function(){
17967            return front;
17968        },
17969
17970        
17971        getBy : function(fn, scope){
17972            var r = [];
17973            for(var i = accessList.length-1; i >=0; --i) {
17974                var win = accessList[i];
17975                if(fn.call(scope||win, win) !== false){
17976                    r.push(win);
17977                }
17978            }
17979            return r;
17980        },
17981
17982        
17983        each : function(fn, scope){
17984            for(var id in list){
17985                if(list[id] && typeof list[id] != "function"){
17986                    if(fn.call(scope || list[id], list[id]) === false){
17987                        return;
17988                    }
17989                }
17990            }
17991        }
17992    };
17993};
17994
17995
17996
17997Ext.WindowMgr = new Ext.WindowGroup();
17998
17999Ext.dd.PanelProxy = function(panel, config){
18000    this.panel = panel;
18001    this.id = this.panel.id +'-ddproxy';
18002    Ext.apply(this, config);
18003};
18004
18005Ext.dd.PanelProxy.prototype = {
18006    
18007    insertProxy : true,
18008
18009    // private overrides
18010    setStatus : Ext.emptyFn,
18011    reset : Ext.emptyFn,
18012    update : Ext.emptyFn,
18013    stop : Ext.emptyFn,
18014    sync: Ext.emptyFn,
18015
18016    
18017    getEl : function(){
18018        return this.ghost;
18019    },
18020
18021    
18022    getGhost : function(){
18023        return this.ghost;
18024    },
18025
18026    
18027    getProxy : function(){
18028        return this.proxy;
18029    },
18030
18031    
18032    hide : function(){
18033        if(this.ghost){
18034            if(this.proxy){
18035                this.proxy.remove();
18036                delete this.proxy;
18037            }
18038            this.panel.el.dom.style.display = '';
18039            this.ghost.remove();
18040            delete this.ghost;
18041        }
18042    },
18043
18044    
18045    show : function(){
18046        if(!this.ghost){
18047            this.ghost = this.panel.createGhost(undefined, undefined, Ext.getBody());
18048            this.ghost.setXY(this.panel.el.getXY())
18049            if(this.insertProxy){
18050                this.proxy = this.panel.el.insertSibling({cls:'x-panel-dd-spacer'});
18051                this.proxy.setSize(this.panel.getSize());
18052            }
18053            this.panel.el.dom.style.display = 'none';
18054        }
18055    },
18056
18057    // private
18058    repair : function(xy, callback, scope){
18059        this.hide();
18060        if(typeof callback == "function"){
18061            callback.call(scope || this);
18062        }
18063    },
18064
18065    
18066    moveProxy : function(parentNode, before){
18067        if(this.proxy){
18068            parentNode.insertBefore(this.proxy.dom, before);
18069        }
18070    }
18071};
18072
18073// private - DD implementation for Panels
18074Ext.Panel.DD = function(panel, cfg){
18075    this.panel = panel;
18076    this.dragData = {panel: panel};
18077    this.proxy = new Ext.dd.PanelProxy(panel, cfg);
18078    Ext.Panel.DD.superclass.constructor.call(this, panel.el, cfg);
18079    var h = panel.header;
18080    if(h){
18081        this.setHandleElId(h.id);
18082    }
18083    (h ? h : this.panel.body).setStyle('cursor', 'move');
18084    this.scroll = false;
18085};
18086
18087Ext.extend(Ext.Panel.DD, Ext.dd.DragSource, {
18088    showFrame: Ext.emptyFn,
18089    startDrag: Ext.emptyFn,
18090    b4StartDrag: function(x, y) {
18091        this.proxy.show();
18092    },
18093    b4MouseDown: function(e) {
18094        var x = e.getPageX();
18095        var y = e.getPageY();
18096        this.autoOffset(x, y);
18097    },
18098    onInitDrag : function(x, y){
18099        this.onStartDrag(x, y);
18100        return true;
18101    },
18102    createFrame : Ext.emptyFn,
18103    getDragEl : function(e){
18104        return this.proxy.ghost.dom;
18105    },
18106    endDrag : function(e){
18107        this.proxy.hide();
18108        this.panel.saveState();
18109    },
18110
18111    autoOffset : function(x, y) {
18112        x -= this.startPageX;
18113        y -= this.startPageY;
18114        this.setDelta(x, y);
18115    }
18116});
18117
18118Ext.state.Provider = function(){
18119    
18120    this.addEvents("statechange");
18121    this.state = {};
18122    Ext.state.Provider.superclass.constructor.call(this);
18123};
18124Ext.extend(Ext.state.Provider, Ext.util.Observable, {
18125    
18126    get : function(name, defaultValue){
18127        return typeof this.state[name] == "undefined" ?
18128            defaultValue : this.state[name];
18129    },
18130    
18131    
18132    clear : function(name){
18133        delete this.state[name];
18134        this.fireEvent("statechange", this, name, null);
18135    },
18136    
18137    
18138    set : function(name, value){
18139        this.state[name] = value;
18140        this.fireEvent("statechange", this, name, value);
18141    },
18142    
18143    
18144    decodeValue : function(cookie){
18145        var re = /^(a|n|d|b|s|o)\:(.*)$/;
18146        var matches = re.exec(unescape(cookie));
18147        if(!matches || !matches[1]) return; // non state cookie
18148        var type = matches[1];
18149        var v = matches[2];
18150        switch(type){
18151            case "n":
18152                return parseFloat(v);
18153            case "d":
18154                return new Date(Date.parse(v));
18155            case "b":
18156                return (v == "1");
18157            case "a":
18158                var all = [];
18159                var values = v.split("^");
18160                for(var i = 0, len = values.length; i < len; i++){
18161                    all.push(this.decodeValue(values[i]));
18162                }
18163                return all;
18164           case "o":
18165                var all = {};
18166                var values = v.split("^");
18167                for(var i = 0, len = values.length; i < len; i++){
18168                    var kv = values[i].split("=");
18169                    all[kv[0]] = this.decodeValue(kv[1]);
18170                }
18171                return all;
18172           default:
18173                return v;
18174        }
18175    },
18176    
18177    
18178    encodeValue : function(v){
18179        var enc;
18180        if(typeof v == "number"){
18181            enc = "n:" + v;
18182        }else if(typeof v == "boolean"){
18183            enc = "b:" + (v ? "1" : "0");
18184        }else if(Ext.isDate(v)){
18185            enc = "d:" + v.toGMTString();
18186        }else if(Ext.isArray(v)){
18187            var flat = "";
18188            for(var i = 0, len = v.length; i < len; i++){
18189                flat += this.encodeValue(v[i]);
18190                if(i != len-1) flat += "^";
18191            }
18192            enc = "a:" + flat;
18193        }else if(typeof v == "object"){
18194            var flat = "";
18195            for(var key in v){
18196                if(typeof v[key] != "function" && v[key] !== undefined){
18197                    flat += key + "=" + this.encodeValue(v[key]) + "^";
18198                }
18199            }
18200            enc = "o:" + flat.substring(0, flat.length-1);
18201        }else{
18202            enc = "s:" + v;
18203        }
18204        return escape(enc);        
18205    }
18206});
18207
18208
18209Ext.state.Manager = function(){
18210    var provider = new Ext.state.Provider();
18211
18212    return {
18213        
18214        setProvider : function(stateProvider){
18215            provider = stateProvider;
18216        },
18217
18218        
18219        get : function(key, defaultValue){
18220            return provider.get(key, defaultValue);
18221        },
18222
18223        
18224         set : function(key, value){
18225            provider.set(key, value);
18226        },
18227
18228        
18229        clear : function(key){
18230            provider.clear(key);
18231        },
18232
18233        
18234        getProvider : function(){
18235            return provider;
18236        }
18237    };
18238}();
18239
18240
18241Ext.state.CookieProvider = function(config){
18242    Ext.state.CookieProvider.superclass.constructor.call(this);
18243    this.path = "/";
18244    this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); //7 days
18245    this.domain = null;
18246    this.secure = false;
18247    Ext.apply(this, config);
18248    this.state = this.readCookies();
18249};
18250
18251Ext.extend(Ext.state.CookieProvider, Ext.state.Provider, {
18252    // private
18253    set : function(name, value){
18254        if(typeof value == "undefined" || value === null){
18255            this.clear(name);
18256            return;
18257        }
18258        this.setCookie(name, value);
18259        Ext.state.CookieProvider.superclass.set.call(this, name, value);
18260    },
18261
18262    // private
18263    clear : function(name){
18264        this.clearCookie(name);
18265        Ext.state.CookieProvider.superclass.clear.call(this, name);
18266    },
18267
18268    // private
18269    readCookies : function(){
18270        var cookies = {};
18271        var c = document.cookie + ";";
18272        var re = /\s?(.*?)=(.*?);/g;
18273    	var matches;
18274    	while((matches = re.exec(c)) != null){
18275            var name = matches[1];
18276            var value = matches[2];
18277            if(name && name.substring(0,3) == "ys-"){
18278                cookies[name.substr(3)] = this.decodeValue(value);
18279            }
18280        }
18281        return cookies;
18282    },
18283
18284    // private
18285    setCookie : function(name, value){
18286        document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
18287           ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
18288           ((this.path == null) ? "" : ("; path=" + this.path)) +
18289           ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
18290           ((this.secure == true) ? "; secure" : "");
18291    },
18292
18293    // private
18294    clearCookie : function(name){
18295        document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
18296           ((this.path == null) ? "" : ("; path=" + this.path)) +
18297           ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
18298           ((this.secure == true) ? "; secure" : "");
18299    }
18300});
18301
18302Ext.DataView = Ext.extend(Ext.BoxComponent, {
18303    
18304    
18305    
18306    
18307    
18308    
18309    
18310    
18311    
18312    selectedClass : "x-view-selected",
18313    
18314    emptyText : "",
18315
18316    
18317    deferEmptyText: true,
18318    
18319    trackOver: false,
18320
18321    //private
18322    last: false,
18323
18324
18325    // private
18326    initComponent : function(){
18327        Ext.DataView.superclass.initComponent.call(this);
18328        if(typeof this.tpl == "string"){
18329            this.tpl = new Ext.XTemplate(this.tpl);
18330        }
18331
18332        this.addEvents(
18333            
18334            "beforeclick",
18335            
18336            "click",
18337            
18338            "mouseenter",
18339            
18340            "mouseleave",
18341            
18342            "containerclick",
18343            
18344            "dblclick",
18345            
18346            "contextmenu",
18347            
18348            "selectionchange",
18349
18350            
18351            "beforeselect"
18352        );
18353
18354        this.all = new Ext.CompositeElementLite();
18355        this.selected = new Ext.CompositeElementLite();
18356    },
18357
18358    // private
18359    onRender : function(){
18360        if(!this.el){
18361            this.el = document.createElement('div');
18362            this.el.id = this.id;
18363        }
18364        Ext.DataView.superclass.onRender.apply(this, arguments);
18365    },
18366
18367    // private
18368    afterRender : function(){
18369        Ext.DataView.superclass.afterRender.call(this);
18370
18371        this.el.on({
18372            "click": this.onClick,
18373            "dblclick": this.onDblClick,
18374            "contextmenu": this.onContextMenu,
18375            scope:this
18376        });
18377
18378        if(this.overClass || this.trackOver){
18379            this.el.on({
18380                "mouseover": this.onMouseOver,
18381                "mouseout": this.onMouseOut,
18382                scope:this
18383            });
18384        }
18385
18386        if(this.store){
18387            this.setStore(this.store, true);
18388        }
18389    },
18390
18391    
18392    refresh : function(){
18393        this.clearSelections(false, true);
18394        this.el.update("");
18395        var records = this.store.getRange();
18396        if(records.length < 1){
18397            if(!this.deferEmptyText || this.hasSkippedEmptyText){
18398                this.el.update(this.emptyText);
18399            }
18400            this.hasSkippedEmptyText = true;
18401            this.all.clear();
18402            return;
18403        }
18404        this.tpl.overwrite(this.el, this.collectData(records, 0));
18405        this.all.fill(Ext.query(this.itemSelector, this.el.dom));
18406        this.updateIndexes(0);
18407    },
18408
18409    
18410    prepareData : function(data){
18411        return data;
18412    },
18413
18414    
18415    collectData : function(records, startIndex){
18416        var r = [];
18417        for(var i = 0, len = records.length; i < len; i++){
18418            r[r.length] = this.prepareData(records[i].data, startIndex+i, records[i]);
18419        }
18420        return r;
18421    },
18422
18423    // private
18424    bufferRender : function(records){
18425        var div = document.createElement('div');
18426        this.tpl.overwrite(div, this.collectData(records));
18427        return Ext.query(this.itemSelector, div);
18428    },
18429
18430    // private
18431    onUpdate : function(ds, record){
18432        var index = this.store.indexOf(record);
18433        var sel = this.isSelected(index);
18434        var original = this.all.elements[index];
18435        var node = this.bufferRender([record], index)[0];
18436
18437        this.all.replaceElement(index, node, true);
18438        if(sel){
18439            this.selected.replaceElement(original, node);
18440            this.all.item(index).addClass(this.selectedClass);
18441        }
18442        this.updateIndexes(index, index);
18443    },
18444
18445    // private
18446    onAdd : function(ds, records, index){
18447        if(this.all.getCount() == 0){
18448            this.refresh();
18449            return;
18450        }
18451        var nodes = this.bufferRender(records, index), n, a = this.all.elements;
18452        if(index < this.all.getCount()){
18453            n = this.all.item(index).insertSibling(nodes, 'before', true);
18454            a.splice.apply(a, [index, 0].concat(nodes));
18455        }else{
18456            n = this.all.last().insertSibling(nodes, 'after', true);
18457            a.push.apply(a, nodes);
18458        }
18459        this.updateIndexes(index);
18460    },
18461
18462    // private
18463    onRemove : function(ds, record, index){
18464        this.deselect(index);
18465        this.all.removeElement(index, true);
18466        this.updateIndexes(index);
18467    },
18468
18469    
18470    refreshNode : function(index){
18471        this.onUpdate(this.store, this.store.getAt(index));
18472    },
18473
18474    // private
18475    updateIndexes : function(startIndex, endIndex){
18476        var ns = this.all.elements;
18477        startIndex = startIndex || 0;
18478        endIndex = endIndex || ((endIndex === 0) ? 0 : (ns.length - 1));
18479        for(var i = startIndex; i <= endIndex; i++){
18480            ns[i].viewIndex = i;
18481        }
18482    },
18483    
18484    
18485    getStore : function(){
18486        return this.store;
18487    },
18488
18489    
18490    setStore : function(store, initial){
18491        if(!initial && this.store){
18492            this.store.un("beforeload", this.onBeforeLoad, this);
18493            this.store.un("datachanged", this.refresh, this);
18494            this.store.un("add", this.onAdd, this);
18495            this.store.un("remove", this.onRemove, this);
18496            this.store.un("update", this.onUpdate, this);
18497            this.store.un("clear", this.refresh, this);
18498        }
18499        if(store){
18500            store = Ext.StoreMgr.lookup(store);
18501            store.on("beforeload", this.onBeforeLoad, this);
18502            store.on("datachanged", this.refresh, this);
18503            store.on("add", this.onAdd, this);
18504            store.on("remove", this.onRemove, this);
18505            store.on("update", this.onUpdate, this);
18506            store.on("clear", this.refresh, this);
18507        }
18508        this.store = store;
18509        if(store){
18510            this.refresh();
18511        }
18512    },
18513
18514    
18515    findItemFromChild : function(node){
18516        return Ext.fly(node).findParent(this.itemSelector, this.el);
18517    },
18518
18519    // private
18520    onClick : function(e){
18521        var item = e.getTarget(this.itemSelector, this.el);
18522        if(item){
18523            var index = this.indexOf(item);
18524            if(this.onItemClick(item, index, e) !== false){
18525                this.fireEvent("click", this, index, item, e);
18526            }
18527        }else{
18528            if(this.fireEvent("containerclick", this, e) !== false){
18529                this.clearSelections();
18530            }
18531        }
18532    },
18533
18534    // private
18535    onContextMenu : function(e){
18536        var item = e.getTarget(this.itemSelector, this.el);
18537        if(item){
18538            this.fireEvent("contextmenu", this, this.indexOf(item), item, e);
18539        }
18540    },
18541
18542    // private
18543    onDblClick : function(e){
18544        var item = e.getTarget(this.itemSelector, this.el);
18545        if(item){
18546            this.fireEvent("dblclick", this, this.indexOf(item), item, e);
18547        }
18548    },
18549
18550    // private
18551    onMouseOver : function(e){
18552        var item = e.getTarget(this.itemSelector, this.el);
18553        if(item && item !== this.lastItem){
18554            this.lastItem = item;
18555            Ext.fly(item).addClass(this.overClass);
18556            this.fireEvent("mouseenter", this, this.indexOf(item), item, e);
18557        }
18558    },
18559
18560    // private
18561    onMouseOut : function(e){
18562        if(this.lastItem){
18563            if(!e.within(this.lastItem, true, true)){
18564                Ext.fly(this.lastItem).removeClass(this.overClass);
18565                this.fireEvent("mouseleave", this, this.indexOf(this.lastItem), this.lastItem, e);
18566                delete this.lastItem;
18567            }
18568        }
18569    },
18570
18571    // private
18572    onItemClick : function(item, index, e){
18573        if(this.fireEvent("beforeclick", this, index, item, e) === false){
18574            return false;
18575        }
18576        if(this.multiSelect){
18577            this.doMultiSelection(item, index, e);
18578            e.preventDefault();
18579        }else if(this.singleSelect){
18580            this.doSingleSelection(item, index, e);
18581            e.preventDefault();
18582        }
18583        return true;
18584    },
18585
18586    // private
18587    doSingleSelection : function(item, index, e){
18588        if(e.ctrlKey && this.isSelected(index)){
18589            this.deselect(index);
18590        }else{
18591            this.select(index, false);
18592        }
18593    },
18594
18595    // private
18596    doMultiSelection : function(item, index, e){
18597        if(e.shiftKey && this.last !== false){
18598            var last = this.last;
18599            this.selectRange(last, index, e.ctrlKey);
18600            this.last = last; // reset the last
18601        }else{
18602            if((e.ctrlKey||this.simpleSelect) && this.isSelected(index)){
18603                this.deselect(index);
18604            }else{
18605                this.select(index, e.ctrlKey || e.shiftKey || this.simpleSelect);
18606            }
18607        }
18608    },
18609
18610    
18611    getSelectionCount : function(){
18612        return this.selected.getCount()
18613    },
18614
18615    
18616    getSelectedNodes : function(){
18617        return this.selected.elements;
18618    },
18619
18620    
18621    getSelectedIndexes : function(){
18622        var indexes = [], s = this.selected.elements;
18623        for(var i = 0, len = s.length; i < len; i++){
18624            indexes.push(s[i].viewIndex);
18625        }
18626        return indexes;
18627    },
18628
18629    
18630    getSelectedRecords : function(){
18631        var r = [], s = this.selected.elements;
18632        for(var i = 0, len = s.length; i < len; i++){
18633            r[r.length] = this.store.getAt(s[i].viewIndex);
18634        }
18635        return r;
18636    },
18637
18638    
18639    getRecords : function(nodes){
18640        var r = [], s = nodes;
18641        for(var i = 0, len = s.length; i < len; i++){
18642            r[r.length] = this.store.getAt(s[i].viewIndex);
18643        }
18644        return r;
18645    },
18646
18647    
18648    getRecord : function(node){
18649        return this.store.getAt(node.viewIndex);
18650    },
18651
18652    
18653    clearSelections : function(suppressEvent, skipUpdate){
18654        if((this.multiSelect || this.singleSelect) && this.selected.getCount() > 0){
18655            if(!skipUpdate){
18656                this.selected.removeClass(this.selectedClass);
18657            }
18658            this.selected.clear();
18659            this.last = false;
18660            if(!suppressEvent){
18661                this.fireEvent("selectionchange", this, this.selected.elements);
18662            }
18663        }
18664    },
18665
18666    
18667    isSelected : function(node){
18668        return this.selected.contains(this.getNode(node));
18669    },
18670
18671    
18672    deselect : function(node){
18673        if(this.isSelected(node)){
18674            node = this.getNode(node);
18675            this.selected.removeElement(node);
18676            if(this.last == node.viewIndex){
18677                this.last = false;
18678            }
18679            Ext.fly(node).removeClass(this.selectedClass);
18680            this.fireEvent("selectionchange", this, this.selected.elements);
18681        }
18682    },
18683
18684    
18685    select : function(nodeInfo, keepExisting, suppressEvent){
18686        if(Ext.isArray(nodeInfo)){
18687            if(!keepExisting){
18688                this.clearSelections(true);
18689            }
18690            for(var i = 0, len = nodeInfo.length; i < len; i++){
18691                this.select(nodeInfo[i], true, true);
18692            }
18693	        if(!suppressEvent){
18694	            this.fireEvent("selectionchange", this, this.selected.elements);
18695	        }
18696        } else{
18697            var node = this.getNode(nodeInfo);
18698            if(!keepExisting){
18699                this.clearSelections(true);
18700            }
18701            if(node && !this.isSelected(node)){
18702                if(this.fireEvent("beforeselect", this, node, this.selected.elements) !== false){
18703                    Ext.fly(node).addClass(this.selectedClass);
18704                    this.selected.add(node);
18705                    this.last = node.viewIndex;
18706                    if(!suppressEvent){
18707                        this.fireEvent("selectionchange", this, this.selected.elements);
18708                    }
18709                }
18710            }
18711        }
18712    },
18713
18714    
18715    selectRange : function(start, end, keepExisting){
18716        if(!keepExisting){
18717            this.clearSelections(true);
18718        }
18719        this.select(this.getNodes(start, end), true);
18720    },
18721
18722    
18723    getNode : function(nodeInfo){
18724        if(typeof nodeInfo == "string"){
18725            return document.getElementById(nodeInfo);
18726        }else if(typeof nodeInfo == "number"){
18727            return this.all.elements[nodeInfo];
18728        }
18729        return nodeInfo;
18730    },
18731
18732    
18733    getNodes : function(start, end){
18734        var ns = this.all.elements;
18735        start = start || 0;
18736        end = typeof end == "undefined" ? Math.max(ns.length - 1, 0) : end;
18737        var nodes = [], i;
18738        if(start <= end){
18739            for(i = start; i <= end && ns[i]; i++){
18740                nodes.push(ns[i]);
18741            }
18742        } else{
18743            for(i = start; i >= end && ns[i]; i--){
18744                nodes.push(ns[i]);
18745            }
18746        }
18747        return nodes;
18748    },
18749
18750    
18751    indexOf : function(node){
18752        node = this.getNode(node);
18753        if(typeof node.viewIndex == "number"){
18754            return node.viewIndex;
18755        }
18756        return this.all.indexOf(node);
18757    },
18758
18759    // private
18760    onBeforeLoad : function(){
18761        if(this.loadingText){
18762            this.clearSelections(false, true);
18763            this.el.update('<div class="loading-indicator">'+this.loadingText+'</div>');
18764            this.all.clear();
18765        }
18766    },
18767
18768    onDestroy : function(){
18769        Ext.DataView.superclass.onDestroy.call(this);
18770        this.setStore(null);
18771    }
18772});
18773
18774Ext.reg('dataview', Ext.DataView);
18775
18776Ext.ColorPalette = function(config){
18777    Ext.ColorPalette.superclass.constructor.call(this, config);
18778    this.addEvents(
18779        
18780        'select'
18781    );
18782
18783    if(this.handler){
18784        this.on("select", this.handler, this.scope, true);
18785    }
18786};
18787Ext.extend(Ext.ColorPalette, Ext.Component, {
18788	
18789    
18790    itemCls : "x-color-palette",
18791    
18792    value : null,
18793    clickEvent:'click',
18794    // private
18795    ctype: "Ext.ColorPalette",
18796
18797    
18798    allowReselect : false,
18799
18800    
18801    colors : [
18802        "000000", "993300", "333300", "003300", "003366", "000080", "333399", "333333",
18803        "800000", "FF6600", "808000", "008000", "008080", "0000FF", "666699", "808080",
18804        "FF0000", "FF9900", "99CC00", "339966", "33CCCC", "3366FF", "800080", "969696",
18805        "FF00FF", "FFCC00", "FFFF00", "00FF00", "00FFFF", "00CCFF", "993366", "C0C0C0",
18806        "FF99CC", "FFCC99", "FFFF99", "CCFFCC", "CCFFFF", "99CCFF", "CC99FF", "FFFFFF"
18807    ],
18808
18809    // private
18810    onRender : function(container, position){
18811        var t = this.tpl || new Ext.XTemplate(
18812            '<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on">&#160;</span></em></a></tpl>'
18813        );
18814        var el = document.createElement("div");
18815        el.id = this.getId();
18816        el.className = this.itemCls;
18817        t.overwrite(el, this.colors);
18818        container.dom.insertBefore(el, position);
18819        this.el = Ext.get(el);
18820        this.el.on(this.clickEvent, this.handleClick,  this, {delegate: "a"});
18821        if(this.clickEvent != 'click'){
18822            this.el.on('click', Ext.emptyFn,  this, {delegate: "a", preventDefault:true});
18823        }
18824    },
18825
18826    // private
18827    afterRender : function(){
18828        Ext.ColorPalette.superclass.afterRender.call(this);
18829        if(this.value){
18830            var s = this.value;
18831            this.value = null;
18832            this.select(s);
18833        }
18834    },
18835
18836    // private
18837    handleClick : function(e, t){
18838        e.preventDefault();
18839        if(!this.disabled){
18840            var c = t.className.match(/(?:^|\s)color-(.{6})(?:\s|$)/)[1];
18841            this.select(c.toUpperCase());
18842        }
18843    },
18844
18845    
18846    select : function(color){
18847        color = color.replace("#", "");
18848        if(color != this.value || this.allowReselect){
18849            var el = this.el;
18850            if(this.value){
18851                el.child("a.color-"+this.value).removeClass("x-color-palette-sel");
18852            }
18853            el.child("a.color-"+color).addClass("x-color-palette-sel");
18854            this.value = color;
18855            this.fireEvent("select", this, color);
18856        }
18857    }
18858
18859    
18860});
18861Ext.reg('colorpalette', Ext.ColorPalette);
18862
18863Ext.DatePicker = Ext.extend(Ext.Component, {
18864    
18865    todayText : "Hoje",
18866    
18867    okText : "&#160;
18867OK&#160;", // &#160; to give the user extra clicking room
18868    
18869    cancelText : "Cancelar",
18870    
18871    todayTip : "{0} (Spacebar)",
18872    
18873    minText : "Esta data é anterior à data mínima",
18874    
18875    maxText : "Esta data é posterior à data máxima",
18876    
18877    format : "m/d/y",
18878    
18879    disabledDaysText : "Disabled",
18880    
18881    disabledDatesText : "Disabled",
18882    
18883    constrainToViewport : true,
18884    
18885    monthNames : Date.monthNames,
18886    
18887    dayNames : Date.dayNames,
18888    
18889    nextText: 'Próximo Mês (Control+Right)',
18890    
18891    prevText: 'Mês Anterior (Control+Left)',
18892    
18893    monthYearText: 'Escolha um mês  (Control+Up/Down para passar os anos)',
18894    
18895    startDay : 0,
18896    
18897    showToday : true,
18898    
18899    
18900    
18901    
18902    
18903
18904    // private
18905    initComponent : function(){
18906        Ext.DatePicker.superclass.initComponent.call(this);
18907
18908        this.value = this.value ?
18909                 this.value.clearTime() : new Date().clearTime();
18910
18911        this.addEvents(
18912            
18913            'select'
18914        );
18915
18916        if(this.handler){
18917            this.on("select", this.handler,  this.scope || this);
18918        }
18919
18920        this.initDisabledDays();
18921    },
18922
18923    // private
18924    initDisabledDays : function(){
18925        if(!this.disabledDatesRE && this.disabledDates){
18926            var dd = this.disabledDates;
18927            var re = "(?:";
18928            for(var i = 0; i < dd.length; i++){
18929                re += dd[i];
18930                if(i != dd.length-1) re += "|";
18931            }
18932            this.disabledDatesRE = new RegExp(re + ")");
18933        }
18934    },
18935    
18936    
18937    setDisabledDates : function(dd){
18938        if(Ext.isArray(dd)){
18939            this.disabledDates = dd;
18940            this.disabledDatesRE = null;
18941        }else{
18942            this.disabledDatesRE = dd;
18943        }
18944        this.initDisabledDays();
18945        this.update(this.value, true);
18946    },
18947    
18948    
18949    setDisabledDays : function(dd){
18950        this.disabledDays = dd;
18951        this.update(this.value, true);
18952    },
18953    
18954    
18955    setMinDate : function(dt){
18956        this.minDate = dt;
18957        this.update(this.value, true);
18958    },
18959    
18960    
18961    setMaxDate : function(dt){
18962        this.maxDate = dt;
18963        this.update(this.value, true);
18964    },
18965
18966    
18967    setValue : function(value){
18968        var old = this.value;
18969        this.value = value.clearTime(true);
18970        if(this.el){
18971            this.update(this.value);
18972        }
18973    },
18974
18975    
18976    getValue : function(){
18977        return this.value;
18978    },
18979
18980    // private
18981    focus : function(){
18982        if(this.el){
18983            this.update(this.activeDate);
18984        }
18985    },
18986
18987    // private
18988    onRender : function(container, position){
18989        var m = [
18990             '<table cellspacing="0">',
18991                '<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>',
18992                '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'];
18993        var dn = this.dayNames;
18994        for(var i = 0; i < 7; i++){
18995            var d = this.startDay+i;
18996            if(d > 6){
18997                d = d-7;
18998            }
18999            m.push("<th><span>", dn[d].substr(0,1), "</span></th>");
19000        }
19001        m[m.length] = "</tr></thead><tbody><tr>";
19002        for(var i = 0; i < 42; i++) {
19003            if(i % 7 == 0 && i != 0){
19004                m[m.length] = "</tr><tr>";
19005            }
19006            m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
19007        }
19008        m.push('</tr></tbody></table></td></tr>', 
19009                this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>' : '', 
19010                '</table><div class="x-date-mp"></div>');
19011
19012        var el = document.createElement("div");
19013        el.className = "x-date-picker";
19014        el.innerHTML = m.join("");
19015
19016        container.dom.insertBefore(el, position);
19017
19018        this.el = Ext.get(el);
19019        this.eventEl = Ext.get(el.firstChild);
19020
19021        this.leftClickRpt = new Ext.util.ClickRepeater(this.el.child("td.x-date-left a"), {
19022            handler: this.showPrevMonth,
19023            scope: this,
19024            preventDefault:true,
19025            stopDefault:true
19026        });
19027
19028        this.rightClickRpt = new Ext.util.ClickRepeater(this.el.child("td.x-date-right a"), {
19029            handler: this.showNextMonth,
19030            scope: this,
19031            preventDefault:true,
19032            stopDefault:true
19033        });
19034
19035        this.eventEl.on("mousewheel", this.handleMouseWheel,  this);
19036
19037        this.monthPicker = this.el.down('div.x-date-mp');
19038        this.monthPicker.enableDisplayMode('block');
19039        
19040        var kn = new Ext.KeyNav(this.eventEl, {
19041            "left" : function(e){
19042                e.ctrlKey ?
19043                    this.showPrevMonth() :
19044                    this.update(this.activeDate.add("d", -1));
19045            },
19046
19047            "right" : function(e){
19048                e.ctrlKey ?
19049                    this.showNextMonth() :
19050                    this.update(this.activeDate.add("d", 1));
19051            },
19052
19053            "up" : function(e){
19054                e.ctrlKey ?
19055                    this.showNextYear() :
19056                    this.update(this.activeDate.add("d", -7));
19057            },
19058
19059            "down" : function(e){
19060                e.ctrlKey ?
19061                    this.showPrevYear() :
19062                    this.update(this.activeDate.add("d", 7));
19063            },
19064
19065            "pageUp" : function(e){
19066                this.showNextMonth();
19067            },
19068
19069            "pageDown" : function(e){
19070                this.showPrevMonth();
19071            },
19072
19073            "enter" : function(e){
19074                e.stopPropagation();
19075                return true;
19076            },
19077
19078            scope : this
19079        });
19080
19081        this.eventEl.on("click", this.handleDateClick,  this, {delegate: "a.x-date-date"});
19082
19083        this.el.unselectable();
19084        
19085        this.cells = this.el.select("table.x-date-inner tbody td");
19086        this.textNodes = this.el.query("table.x-date-inner tbody span");
19087
19088        this.mbtn = new Ext.Button({
19089            text: "&#160;",
19090            tooltip: this.monthYearText,
19091            renderTo: this.el.child("td.x-date-middle", true)
19092        });
19093
19094        this.mbtn.on('click', this.showMonthPicker, this);
19095        this.mbtn.el.child(this.mbtn.menuClassTarget).addClass("x-btn-with-menu");
19096
19097        if(this.showToday){
19098            this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday,  this);
19099            var today = (new Date()).dateFormat(this.format);
19100            this.todayBtn = new Ext.Button({
19101                renderTo: this.el.child("td.x-date-bottom", true),
19102                text: String.format(this.todayText, today),
19103                tooltip: String.format(this.todayTip, today),
19104                handler: this.selectToday,
19105                scope: this
19106            });
19107        }
19108        
19109        if(Ext.isIE){
19110            this.el.repaint();
19111        }
19112        this.update(this.value);
19113    },
19114
19115    // private
19116    createMonthPicker : function(){
19117        if(!this.monthPicker.dom.firstChild){
19118            var buf = ['<table border="0" cellspacing="0">'];
19119            for(var i = 0; i < 6; i++){
19120                buf.push(
19121                    '<tr><td class="x-date-mp-month"><a href="#">', this.monthNames[i].substr(0, 3), '</a></td>',
19122                    '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', this.monthNames[i+6].substr(0, 3), '</a></td>',
19123                    i == 0 ?
19124                    '<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>' :
19125                    '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'
19126                );
19127            }
19128            buf.push(
19129                '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',
19130                    this.okText,
19131                    '</button><button type="button" class="x-date-mp-cancel">',
19132                    this.cancelText,
19133                    '</button></td></tr>',
19134                '</table>'
19135            );
19136            this.monthPicker.update(buf.join(''));
19137            this.monthPicker.on('click', this.onMonthClick, this);
19138            this.monthPicker.on('dblclick', this.onMonthDblClick, this);
19139
19140            this.mpMonths = this.monthPicker.select('td.x-date-mp-month');
19141            this.mpYears = this.monthPicker.select('td.x-date-mp-year');
19142
19143            this.mpMonths.each(function(m, a, i){
19144                i += 1;
19145                if((i%2) == 0){
19146                    m.dom.xmonth = 5 + Math.round(i * .5);
19147                }else{
19148                    m.dom.xmonth = Math.round((i-1) * .5);
19149                }
19150            });
19151        }
19152    },
19153
19154    // private
19155    showMonthPicker : function(){
19156        this.createMonthPicker();
19157        var size = this.el.getSize();
19158        this.monthPicker.setSize(size);
19159        this.monthPicker.child('table').setSize(size);
19160
19161        this.mpSelMonth = (this.activeDate || this.value).getMonth();
19162        this.updateMPMonth(this.mpSelMonth);
19163        this.mpSelYear = (this.activeDate || this.value).getFullYear();
19164        this.updateMPYear(this.mpSelYear);
19165
19166        this.monthPicker.slideIn('t', {duration:.2});
19167    },
19168
19169    // private
19170    updateMPYear : function(y){
19171        this.mpyear = y;
19172        var ys = this.mpYears.elements;
19173        for(var i = 1; i <= 10; i++){
19174            var td = ys[i-1], y2;
19175            if((i%2) == 0){
19176                y2 = y + Math.round(i * .5);
19177                td.firstChild.innerHTML = y2;
19178                td.xyear = y2;
19179            }else{
19180                y2 = y - (5-Math.round(i * .5));
19181                td.firstChild.innerHTML = y2;
19182                td.xyear = y2;
19183            }
19184            this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');
19185        }
19186    },
19187
19188    // private
19189    updateMPMonth : function(sm){
19190        this.mpMonths.each(function(m, a, i){
19191            m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');
19192        });
19193    },
19194
19195    // private
19196    selectMPMonth: function(m){
19197        
19198    },
19199
19200    // private
19201    onMonthClick : function(e, t){
19202        e.stopEvent();
19203        var el = new Ext.Element(t), pn;
19204        if(el.is('button.x-date-mp-cancel')){
19205            this.hideMonthPicker();
19206        }
19207        else if(el.is('button.x-date-mp-ok')){
19208            var d = new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate());
19209            if(d.getMonth() != this.mpSelMonth){
19210                // "fix" the JS rolling date conversion if needed
19211                d = new Date(this.mpSelYear, this.mpSelMonth, 1).getLastDateOfMonth();
19212            }
19213            this.update(d);
19214            this.hideMonthPicker();
19215        }
19216        else if(pn = el.up('td.x-date-mp-month', 2)){
19217            this.mpMonths.removeClass('x-date-mp-sel');
19218            pn.addClass('x-date-mp-sel');
19219            this.mpSelMonth = pn.dom.xmonth;
19220        }
19221        else if(pn = el.up('td.x-date-mp-year', 2)){
19222            this.mpYears.removeClass('x-date-mp-sel');
19223            pn.addClass('x-date-mp-sel');
19224            this.mpSelYear = pn.dom.xyear;
19225        }
19226        else if(el.is('a.x-date-mp-prev')){
19227            this.updateMPYear(this.mpyear-10);
19228        }
19229        else if(el.is('a.x-date-mp-next')){
19230            this.updateMPYear(this.mpyear+10);
19231        }
19232    },
19233
19234    // private
19235    onMonthDblClick : function(e, t){
19236        e.stopEvent();
19237        var el = new Ext.Element(t), pn;
19238        if(pn = el.up('td.x-date-mp-month', 2)){
19239            this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));
19240            this.hideMonthPicker();
19241        }
19242        else if(pn = el.up('td.x-date-mp-year', 2)){
19243            this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
19244            this.hideMonthPicker();
19245        }
19246    },
19247
19248    // private
19249    hideMonthPicker : function(disableAnim){
19250        if(this.monthPicker){
19251            if(disableAnim === true){
19252                this.monthPicker.hide();
19253            }else{
19254                this.monthPicker.slideOut('t', {duration:.2});
19255            }
19256        }
19257    },
19258
19259    // private
19260    showPrevMonth : function(e){
19261        this.update(this.activeDate.add("mo", -1));
19262    },
19263
19264    // private
19265    showNextMonth : function(e){
19266        this.update(this.activeDate.add("mo", 1));
19267    },
19268
19269    // private
19270    showPrevYear : function(){
19271        this.update(this.activeDate.add("y", -1));
19272    },
19273
19274    // private
19275    showNextYear : function(){
19276        this.update(this.activeDate.add("y", 1));
19277    },
19278
19279    // private
19280    handleMouseWheel : function(e){
19281        var delta = e.getWheelDelta();
19282        if(delta > 0){
19283            this.showPrevMonth();
19284            e.stopEvent();
19285        } else if(delta < 0){
19286            this.showNextMonth();
19287            e.stopEvent();
19288        }
19289    },
19290
19291    // private
19292    handleDateClick : function(e, t){
19293        e.stopEvent();
19294        if(t.dateValue && !Ext.fly(t.parentNode).hasClass("x-date-disabled")){
19295            this.setValue(new Date(t.dateValue));
19296            this.fireEvent("select", this, this.value);
19297        }
19298    },
19299
19300    // private
19301    selectToday : function(){
19302        if(this.todayBtn && !this.todayBtn.disabled){
19303	        this.setValue(new Date().clearTime());
19304	        this.fireEvent("select", this, this.value);
19305        }
19306    },
19307
19308    // private
19309    update : function(date, forceRefresh){
19310        var vd = this.activeDate;
19311        this.activeDate = date;
19312        if(!forceRefresh && vd && this.el){
19313            var t = date.getTime();
19314            if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
19315                this.cells.removeClass("x-date-selected");
19316                this.cells.each(function(c){
19317                   if(c.dom.firstChild.dateValue == t){
19318                       c.addClass("x-date-selected");
19319                       setTimeout(function(){
19320                            try{c.dom.firstChild.focus();}catch(e){}
19321                       }, 50);
19322                       return false;
19323                   }
19324                });
19325                return;
19326            }
19327        }
19328        var days = date.getDaysInMonth();
19329        var firstOfMonth = date.getFirstDateOfMonth();
19330        var startingPos = firstOfMonth.getDay()-this.startDay;
19331
19332        if(startingPos <= this.startDay){
19333            startingPos += 7;
19334        }
19335
19336        var pm = date.add("mo", -1);
19337        var prevStart = pm.getDaysInMonth()-startingPos;
19338
19339        var cells = this.cells.elements;
19340        var textEls = this.textNodes;
19341        days += startingPos;
19342
19343        // convert everything to numbers so it's fast
19344        var day = 86400000;
19345        var d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart)).clearTime();
19346        var today = new Date().clearTime().getTime();
19347        var sel = date.clearTime().getTime();
19348        var min = this.minDate ? this.minDate.clearTime() : Number.NEGATIVE_INFINITY;
19349        var max = this.maxDate ? this.maxDate.clearTime() : Number.POSITIVE_INFINITY;
19350        var ddMatch = this.disabledDatesRE;
19351        var ddText = this.disabledDatesText;
19352        var ddays = this.disabledDays ? this.disabledDays.join("") : false;
19353        var ddaysText = this.disabledDaysText;
19354        var format = this.format;
19355        
19356        if(this.showToday){
19357            var td = new Date().clearTime();
19358            var disable = (td < min || td > max || 
19359                (ddMatch && format && ddMatch.test(td.dateFormat(format))) || 
19360                (ddays && ddays.indexOf(td.getDay()) != -1));
19361                        
19362            this.todayBtn.setDisabled(disable);
19363            this.todayKeyListener[disable ? 'disable' : 'enable']();
19364        }
19365
19366        var setCellClass = function(cal, cell){
19367            cell.title = "";
19368            var t = d.getTime();
19369            cell.firstChild.dateValue = t;
19370            if(t == today){
19371                cell.className += " x-date-today";
19372                cell.title = cal.todayText;
19373            }
19374            if(t == sel){
19375                cell.className += " x-date-selected";
19376                setTimeout(function(){
19377                    try{cell.firstChild.focus();}catch(e){}
19378                }, 50);
19379            }
19380            // disabling
19381            if(t < min) {
19382                cell.className = " x-date-disabled";
19383                cell.title = cal.minText;
19384                return;
19385            }
19386            if(t > max) {
19387                cell.className = " x-date-disabled";
19388                cell.title = cal.maxText;
19389                return;
19390            }
19391            if(ddays){
19392                if(ddays.indexOf(d.getDay()) != -1){
19393                    cell.title = ddaysText;
19394                    cell.className = " x-date-disabled";
19395                }
19396            }
19397            if(ddMatch && format){
19398                var fvalue = d.dateFormat(format);
19399                if(ddMatch.test(fvalue)){
19400                    cell.title = ddText.replace("%0", fvalue);
19401                    cell.className = " x-date-disabled";
19402                }
19403            }
19404        };
19405
19406        var i = 0;
19407        for(; i < startingPos; i++) {
19408            textEls[i].innerHTML = (++prevStart);
19409            d.setDate(d.getDate()+1);
19410            cells[i].className = "x-date-prevday";
19411            setCellClass(this, cells[i]);
19412        }
19413        for(; i < days; i++){
19414            var intDay = i - startingPos + 1;
19415            textEls[i].innerHTML = (intDay);
19416            d.setDate(d.getDate()+1);
19417            cells[i].className = "x-date-active";
19418            setCellClass(this, cells[i]);
19419        }
19420        var extraDays = 0;
19421        for(; i < 42; i++) {
19422             textEls[i].innerHTML = (++extraDays);
19423             d.setDate(d.getDate()+1);
19424             cells[i].className = "x-date-nextday";
19425             setCellClass(this, cells[i]);
19426        }
19427
19428        this.mbtn.setText(this.monthNames[date.getMonth()] + " " + date.getFullYear());
19429
19430        if(!this.internalRender){
19431            var main = this.el.dom.firstChild;
19432            var w = main.offsetWidth;
19433            this.el.setWidth(w + this.el.getBorderWidth("lr"));
19434            Ext.fly(main).setWidth(w);
19435            this.internalRender = true;
19436            // opera does not respect the auto grow header center column
19437            // then, after it gets a width opera refuses to recalculate
19438            // without a second pass
19439            if(Ext.isOpera && !this.secondPass){
19440                main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + "px";
19441                this.secondPass = true;
19442                this.update.defer(10, this, [date]);
19443            }
19444        }
19445    },
19446
19447    // private
19448    beforeDestroy : function() {
19449        if(this.rendered){
19450            Ext.destroy(
19451                this.leftClickRpt,
19452                this.rightClickRpt,
19453                this.monthPicker,
19454                this.eventEl,
19455                this.mbtn,
19456                this.todayBtn
19457            );
19458        }
19459    }
19460
19461    
19462});
19463Ext.reg('datepicker', Ext.DatePicker);
19464
19465Ext.TabPanel = Ext.extend(Ext.Panel,  {
19466    
19467    
19468    
19469    monitorResize : true,
19470    
19471    deferredRender : true,
19472    
19473    tabWidth: 120,
19474    
19475    minTabWidth: 30,
19476    
19477    resizeTabs:false,
19478    
19479    enableTabScroll: false,
19480    
19481    scrollIncrement : 0,
19482    
19483    scrollRepeatInterval : 400,
19484    
19485    scrollDuration : .35,
19486    
19487    animScroll : true,
19488    
19489    tabPosition: 'top',
19490    
19491    baseCls: 'x-tab-panel',
19492    
19493    autoTabs : false,
19494    
19495    autoTabSelector:'div.x-tab',
19496    
19497    activeTab : null,
19498    
19499    tabMargin : 2,
19500    
19501    plain: false,
19502    
19503    wheelIncrement : 20,
19504
19505    
19506    idDelimiter : '__',
19507
19508    // private
19509    itemCls : 'x-tab-item',
19510
19511    // private config overrides
19512    elements: 'body',
19513    headerAsText: false,
19514    frame: false,
19515    hideBorders:true,
19516
19517    // private
19518    initComponent : function(){
19519        this.frame = false;
19520        Ext.TabPanel.superclass.initComponent.call(this);
19521        this.addEvents(
19522            
19523            'beforetabchange',
19524            
19525            'tabchange',
19526            
19527            'contextmenu'
19528        );
19529        this.setLayout(new Ext.layout.CardLayout({
19530            deferredRender: this.deferredRender
19531        }));
19532        if(this.tabPosition == 'top'){
19533            this.elements += ',header';
19534            this.stripTarget = 'header';
19535        }else {
19536            this.elements += ',footer';
19537            this.stripTarget = 'footer';
19538        }
19539        if(!this.stack){
19540            this.stack = Ext.TabPanel.AccessStack();
19541        }
19542        this.initItems();
19543    },
19544
19545    // private
19546    render : function(){
19547        Ext.TabPanel.superclass.render.apply(this, arguments);
19548        if(this.activeTab !== undefined){
19549            var item = this.activeTab;
19550            delete this.activeTab;
19551            this.setActiveTab(item);
19552        }
19553    },
19554
19555    // private
19556    onRender : function(ct, position){
19557        Ext.TabPanel.superclass.onRender.call(this, ct, position);
19558
19559        if(this.plain){
19560            var pos = this.tabPosition == 'top' ? 'header' : 'footer';
19561            this[pos].addClass('x-tab-panel-'+pos+'-plain');
19562        }
19563
19564        var st = this[this.stripTarget];
19565
19566        this.stripWrap = st.createChild({cls:'x-tab-strip-wrap', cn:{
19567            tag:'ul', cls:'x-tab-strip x-tab-strip-'+this.tabPosition}});
19568
19569        var beforeEl = (this.tabPosition=='bottom' ? this.stripWrap : null);
19570        this.stripSpacer = st.createChild({cls:'x-tab-strip-spacer'}, beforeEl);
19571        this.strip = new Ext.Element(this.stripWrap.dom.firstChild);
19572
19573        this.edge = this.strip.createChild({tag:'li', cls:'x-tab-edge'});
19574        this.strip.createChild({cls:'x-clear'});
19575
19576        this.body.addClass('x-tab-panel-body-'+this.tabPosition);
19577
19578        if(!this.itemTpl){
19579            var tt = new Ext.Template(
19580                 '<li class="{cls}" id="{id}"><a class="x-tab-strip-close" onclick="return false;"></a>',
19581                 '<a class="x-tab-right" href="#" onclick="return false;"><em class="x-tab-left">',
19582                 '<span class="x-tab-strip-inner"><span class="x-tab-strip-text {iconCls}">{text}</span></span>',
19583                 '</em></a></li>'
19584            );
19585            tt.disableFormats = true;
19586            tt.compile();
19587            Ext.TabPanel.prototype.itemTpl = tt;
19588        }
19589
19590        this.items.each(this.initTab, this);
19591    },
19592
19593    // private
19594    afterRender : function(){
19595        Ext.TabPanel.superclass.afterRender.call(this);
19596        if(this.autoTabs){
19597            this.readTabs(false);
19598        }
19599    },
19600
19601    // private
19602    initEvents : function(){
19603        Ext.TabPanel.superclass.initEvents.call(this);
19604        this.on('add', this.onAdd, this);
19605        this.on('remove', this.onRemove, this);
19606
19607        this.strip.on('mousedown', this.onStripMouseDown, this);
19608        this.strip.on('contextmenu', this.onStripContextMenu, this);
19609        if(this.enableTabScroll){
19610            this.strip.on('mousewheel', this.onWheel, this);
19611        }
19612    },
19613
19614    // private
19615    findTargets : function(e){
19616        var item = null;
19617        var itemEl = e.getTarget('li', this.strip);
19618        if(itemEl){
19619            item = this.getComponent(itemEl.id.split(this.idDelimiter)[1]);
19620            if(item.disabled){
19621                return {
19622                    close : null,
19623                    item : null,
19624                    el : null
19625                };
19626            }
19627        }
19628        return {
19629            close : e.getTarget('.x-tab-strip-close', this.strip),
19630            item : item,
19631            el : itemEl
19632        };
19633    },
19634
19635    // private
19636    onStripMouseDown : function(e){
19637        if(e.button != 0){
19638            return;
19639        }
19640        e.preventDefault();
19641        var t = this.findTargets(e);
19642        if(t.close){
19643            this.remove(t.item);
19644            return;
19645        }
19646        if(t.item && t.item != this.activeTab){
19647            this.setActiveTab(t.item);
19648        }
19649    },
19650
19651    // private
19652    onStripContextMenu : function(e){
19653        e.preventDefault();
19654        var t = this.findTargets(e);
19655        if(t.item){
19656            this.fireEvent('contextmenu', this, t.item, e);
19657        }
19658    },
19659
19660    
19661    readTabs : function(removeExisting){
19662        if(removeExisting === true){
19663            this.items.each(function(item){
19664                this.remove(item);
19665            }, this);
19666        }
19667        var tabs = this.el.query(this.autoTabSelector);
19668        for(var i = 0, len = tabs.length; i < len; i++){
19669            var tab = tabs[i];
19670            var title = tab.getAttribute('title');
19671            tab.removeAttribute('title');
19672            this.add({
19673                title: title,
19674                el: tab
19675            });
19676        }
19677    },
19678
19679    // private
19680    initTab : function(item, index){
19681        var before = this.strip.dom.childNodes[index];
19682        var cls = item.closable ? 'x-tab-strip-closable' : '';
19683        if(item.disabled){
19684            cls += ' x-item-disabled';
19685        }
19686        if(item.iconCls){
19687            cls += ' x-tab-with-icon';
19688        }
19689        if(item.tabCls){
19690            cls += ' ' + item.tabCls;
19691        }
19692
19693        var p = {
19694            id: this.id + this.idDelimiter + item.getItemId(),
19695            text: item.title,
19696            cls: cls,
19697            iconCls: item.iconCls || ''
19698        };
19699        var el = before ?
19700                 this.itemTpl.insertBefore(before, p) :
19701                 this.itemTpl.append(this.strip, p);
19702
19703        Ext.fly(el).addClassOnOver('x-tab-strip-over');
19704
19705        if(item.tabTip){
19706            Ext.fly(el).child('span.x-tab-strip-text', true).qtip = item.tabTip;
19707        }
19708        item.tabEl = el;
19709
19710        item.on('disable', this.onItemDisabled, this);
19711        item.on('enable', this.onItemEnabled, this);
19712        item.on('titlechange', this.onItemTitleChanged, this);
19713        item.on('iconchange', this.onItemIconChanged, this);
19714        item.on('beforeshow', this.onBeforeShowItem, this);
19715    },
19716
19717    // private
19718    onAdd : function(tp, item, index){
19719        this.initTab(item, index);
19720        if(this.items.getCount() == 1){
19721            this.syncSize();
19722        }
19723        this.delegateUpdates();
19724    },
19725
19726    // private
19727    onBeforeAdd : function(item){
19728        var existing = item.events ? (this.items.containsKey(item.getItemId()) ? item : null) : this.items.get(item);
19729        if(existing){
19730            this.setActiveTab(item);
19731            return false;
19732        }
19733        Ext.TabPanel.superclass.onBeforeAdd.apply(this, arguments);
19734        var es = item.elements;
19735        item.elements = es ? es.replace(',header', '') : es;
19736        item.border = (item.border === true);
19737    },
19738
19739    // private
19740    onRemove : function(tp, item){
19741        Ext.destroy(Ext.get(this.getTabEl(item)));
19742        this.stack.remove(item);
19743        item.un('disable', this.onItemDisabled, this);
19744        item.un('enable', this.onItemEnabled, this);
19745        item.un('titlechange', this.onItemTitleChanged, this);
19746        item.un('iconchange', this.onItemIconChanged, this);
19747        item.un('beforeshow', this.onBeforeShowItem, this);
19748        if(item == this.activeTab){
19749            var next = this.stack.next();
19750            if(next){
19751                this.setActiveTab(next);
19752            }else if(this.items.getCount() > 0){
19753                this.setActiveTab(0);
19754            }else{
19755                this.activeTab = null;
19756            }
19757        }
19758        this.delegateUpdates();
19759    },
19760
19761    // private
19762    onBeforeShowItem : function(item){
19763        if(item != this.activeTab){
19764            this.setActiveTab(item);
19765            return false;
19766        }
19767    },
19768
19769    // private
19770    onItemDisabled : function(item){
19771        var el = this.getTabEl(item);
19772        if(el){
19773            Ext.fly(el).addClass('x-item-disabled');
19774        }
19775        this.stack.remove(item);
19776    },
19777
19778    // private
19779    onItemEnabled : function(item){
19780        var el = this.getTabEl(item);
19781        if(el){
19782            Ext.fly(el).removeClass('x-item-disabled');
19783        }
19784    },
19785
19786    // private
19787    onItemTitleChanged : function(item){
19788        var el = this.getTabEl(item);
19789        if(el){
19790            Ext.fly(el).child('span.x-tab-strip-text', true).innerHTML = item.title;
19791        }
19792    },
19793    
19794    //private
19795    onItemIconChanged: function(item, iconCls, oldCls){
19796        var el = this.getTabEl(item);
19797        if(el){
19798            Ext.fly(el).child('span.x-tab-strip-text').replaceClass(oldCls, iconCls);
19799        }
19800    },
19801
19802    
19803    getTabEl : function(item){
19804        var itemId = (typeof item === 'number')?this.items.items[item].getItemId() : item.getItemId();
19805        return document.getElementById(this.id+this.idDelimiter+itemId);
19806    },
19807
19808    // private
19809    onResize : function(){
19810        Ext.TabPanel.superclass.onResize.apply(this, arguments);
19811        this.delegateUpdates();
19812    },
19813
19814    
19815    beginUpdate : function(){
19816        this.suspendUpdates = true;
19817    },
19818
19819    
19820    endUpdate : function(){
19821        this.suspendUpdates = false;
19822        this.delegateUpdates();
19823    },
19824
19825    
19826    hideTabStripItem : function(item){
19827        item = this.getComponent(item);
19828        var el = this.getTabEl(item);
19829        if(el){
19830            el.style.display = 'none';
19831            this.delegateUpdates();
19832        }
19833        this.stack.remove(item);
19834    },
19835
19836    
19837    unhideTabStripItem : function(item){
19838        item = this.getComponent(item);
19839        var el = this.getTabEl(item);
19840        if(el){
19841            el.style.display = '';
19842            this.delegateUpdates();
19843        }
19844    },
19845
19846    // private
19847    delegateUpdates : function(){
19848        if(this.suspendUpdates){
19849            return;
19850        }
19851        if(this.resizeTabs && this.rendered){
19852            this.autoSizeTabs();
19853        }
19854        if(this.enableTabScroll && this.rendered){
19855            this.autoScrollTabs();
19856        }
19857    },
19858
19859    // private
19860    autoSizeTabs : function(){
19861        var count = this.items.length;
19862        var ce = this.tabPosition != 'bottom' ? 'header' : 'footer';
19863        var ow = this[ce].dom.offsetWidth;
19864        var aw = this[ce].dom.clientWidth;
19865
19866        if(!this.resizeTabs || count < 1 || !aw){ // !aw for display:none
19867            return;
19868        }
19869
19870        var each = Math.max(Math.min(Math.floor((aw-4) / count) - this.tabMargin, this.tabWidth), this.minTabWidth); // -4 for float errors in IE
19871        this.lastTabWidth = each;
19872        var lis = this.stripWrap.dom.getElementsByTagName('li');
19873        for(var i = 0, len = lis.length-1; i < len; i++) { // -1 for the "edge" li
19874            var li = lis[i];
19875            var inner = li.childNodes[1].firstChild.firstChild;
19876            var tw = li.offsetWidth;
19877            var iw = inner.offsetWidth;
19878            inner.style.width = (each - (tw-iw)) + 'px';
19879        }
19880    },
19881
19882    // private
19883    adjustBodyWidth : function(w){
19884        if(this.header){
19885            this.header.setWidth(w);
19886        }
19887        if(this.footer){
19888            this.footer.setWidth(w);
19889        }
19890        return w;
19891    },
19892
19893    
19894    setActiveTab : function(item){
19895        item = this.getComponent(item);
19896        if(!item || this.fireEvent('beforetabchange', this, item, this.activeTab) === false){
19897            return;
19898        }
19899        if(!this.rendered){
19900            this.activeTab = item;
19901            return;
19902        }
19903        if(this.activeTab != item){
19904            if(this.activeTab){
19905                var oldEl = this.getTabEl(this.activeTab);
19906                if(oldEl){
19907                    Ext.fly(oldEl).removeClass('x-tab-strip-active');
19908                }
19909                this.activeTab.fireEvent('deactivate', this.activeTab);
19910            }
19911            var el = this.getTabEl(item);
19912            Ext.fly(el).addClass('x-tab-strip-active');
19913            this.activeTab = item;
19914            this.stack.add(item);
19915
19916            this.layout.setActiveItem(item);
19917            if(this.layoutOnTabChange && item.doLayout){
19918                item.doLayout();
19919            }
19920            if(this.scrolling){
19921                this.scrollToTab(item, this.animScroll);
19922            }
19923
19924            item.fireEvent('activate', item);
19925            this.fireEvent('tabchange', this, item);
19926        }
19927    },
19928
19929    
19930    getActiveTab : function(){
19931        return this.activeTab || null;
19932    },
19933
19934    
19935    getItem : function(item){
19936        return this.getComponent(item);
19937    },
19938
19939    // private
19940    autoScrollTabs : function(){
19941        this.pos = this.tabPosition=='bottom' ? this.footer : this.header;
19942        var count = this.items.length;
19943        var ow = this.pos.dom.offsetWidth;
19944        var tw = this.pos.dom.clientWidth;
19945
19946        var wrap = this.stripWrap;
19947        var wd = wrap.dom;
19948        var cw = wd.offsetWidth;
19949        var pos = this.getScrollPos();
19950        var l = this.edge.getOffsetsTo(this.stripWrap)[0] + pos;
19951
19952        if(!this.enableTabScroll || count < 1 || cw < 20){ // 20 to prevent display:none issues
19953            return;
19954        }
19955        if(l <= tw){
19956            wd.scrollLeft = 0;
19957            wrap.setWidth(tw);
19958            if(this.scrolling){
19959                this.scrolling = false;
19960                this.pos.removeClass('x-tab-scrolling');
19961                this.scrollLeft.hide();
19962                this.scrollRight.hide();
19963                if(Ext.isAir || Ext.isSafari){
19964                    wd.style.marginLeft = '';
19965                    wd.style.marginRight = '';
19966                }
19967            }
19968        }else{
19969            if(!this.scrolling){
19970                this.pos.addClass('x-tab-scrolling');
19971                if(Ext.isAir || Ext.isSafari){
19972                    wd.style.marginLeft = '18px';
19973                    wd.style.marginRight = '18px';
19974                }
19975            }
19976            tw -= wrap.getMargins('lr');
19977            wrap.setWidth(tw > 20 ? tw : 20);
19978            if(!this.scrolling){
19979                if(!this.scrollLeft){
19980                    this.createScrollers();
19981                }else{
19982                    this.scrollLeft.show();
19983                    this.scrollRight.show();
19984                }
19985            }
19986            this.scrolling = true;
19987            if(pos > (l-tw)){ // ensure it stays within bounds
19988                wd.scrollLeft = l-tw;
19989            }else{ // otherwise, make sure the active tab is still visible
19990                this.scrollToTab(this.activeTab, false);
19991            }
19992            this.updateScrollButtons();
19993        }
19994    },
19995
19996    // private
19997    createScrollers : function(){
19998        this.pos.addClass('x-tab-scrolling-' + this.tabPosition);
19999        var h = this.stripWrap.dom.offsetHeight;
20000
20001        // left
20002        var sl = this.pos.insertFirst({
20003            cls:'x-tab-scroller-left'
20004        });
20005        sl.setHeight(h);
20006        sl.addClassOnOver('x-tab-scroller-left-over');
20007        this.leftRepeater = new Ext.util.ClickRepeater(sl, {
20008            interval : this.scrollRepeatInterval,
20009            handler: this.onScrollLeft,
20010            scope: this
20011        });
20012        this.scrollLeft = sl;
20013
20014        // right
20015        var sr = this.pos.insertFirst({
20016            cls:'x-tab-scroller-right'
20017        });
20018        sr.setHeight(h);
20019        sr.addClassOnOver('x-tab-scroller-right-over');
20020        this.rightRepeater = new Ext.util.ClickRepeater(sr, {
20021            interval : this.scrollRepeatInterval,
20022            handler: this.onScrollRight,
20023            scope: this
20024        });
20025        this.scrollRight = sr;
20026    },
20027
20028    // private
20029    getScrollWidth : function(){
20030        return this.edge.getOffsetsTo(this.stripWrap)[0] + this.getScrollPos();
20031    },
20032
20033    // private
20034    getScrollPos : function(){
20035        return parseInt(this.stripWrap.dom.scrollLeft, 10) || 0;
20036    },
20037
20038    // private
20039    getScrollArea : function(){
20040        return parseInt(this.stripWrap.dom.clientWidth, 10) || 0;
20041    },
20042
20043    // private
20044    getScrollAnim : function(){
20045        return {duration:this.scrollDuration, callback: this.updateScrollButtons, scope: this};
20046    },
20047
20048    // private
20049    getScrollIncrement : function(){
20050        return this.scrollIncrement || (this.resizeTabs ? this.lastTabWidth+2 : 100);
20051    },
20052
20053    
20054
20055    scrollToTab : function(item, animate){
20056        if(!item){ return; }
20057        var el = this.getTabEl(item);
20058        var pos = this.getScrollPos(), area = this.getScrollArea();
20059        var left = Ext.fly(el).getOffsetsTo(this.stripWrap)[0] + pos;
20060        var right = left + el.offsetWidth;
20061        if(left < pos){
20062            this.scrollTo(left, animate);
20063        }else if(right > (pos + area)){
20064            this.scrollTo(right - area, animate);
20065        }
20066    },
20067
20068    // private
20069    scrollTo : function(pos, animate){
20070        this.stripWrap.scrollTo('left', pos, animate ? this.getScrollAnim() : false);
20071        if(!animate){
20072            this.updateScrollButtons();
20073        }
20074    },
20075
20076    onWheel : function(e){
20077        var d = e.getWheelDelta()*this.wheelIncrement*-1;
20078        e.stopEvent();
20079
20080        var pos = this.getScrollPos();
20081        var newpos = pos + d;
20082        var sw = this.getScrollWidth()-this.getScrollArea();
20083
20084        var s = Math.max(0, Math.min(sw, newpos));
20085        if(s != pos){
20086            this.scrollTo(s, false);
20087        }
20088    },
20089
20090    // private
20091    onScrollRight : function(){
20092        var sw = this.getScrollWidth()-this.getScrollArea();
20093        var pos = this.getScrollPos();
20094        var s = Math.min(sw, pos + this.getScrollIncrement());
20095        if(s != pos){
20096            this.scrollTo(s, this.animScroll);
20097        }
20098    },
20099
20100    // private
20101    onScrollLeft : function(){
20102        var pos = this.getScrollPos();
20103        var s = Math.max(0, pos - this.getScrollIncrement());
20104        if(s != pos){
20105            this.scrollTo(s, this.animScroll);
20106        }
20107    },
20108
20109    // private
20110    updateScrollButtons : function(){
20111        var pos = this.getScrollPos();
20112        this.scrollLeft[pos == 0 ? 'addClass' : 'removeClass']('x-tab-scroller-left-disabled');
20113        this.scrollRight[pos >= (this.getScrollWidth()-this.getScrollArea()) ? 'addClass' : 'removeClass']('x-tab-scroller-right-disabled');
20114    },
20115
20116    // private
20117    beforeDestroy : function() {
20118        if(this.items){
20119            this.items.each(function(item){
20120                if(item && item.tabEl){
20121                    Ext.get(item.tabEl).removeAllListeners();
20122                    item.tabEl = null;
20123                }
20124            }, this);
20125        }
20126        if(this.strip){
20127            this.strip.removeAllListeners();
20128        }
20129        Ext.TabPanel.superclass.beforeDestroy.apply(this);
20130    }
20131
20132    
20133    
20134    
20135    
20136    
20137    
20138    
20139    
20140    
20141    
20142    
20143
20144});
20145Ext.reg('tabpanel', Ext.TabPanel);
20146
20147
20148Ext.TabPanel.prototype.activate = Ext.TabPanel.prototype.setActiveTab;
20149
20150// private utility class used by TabPanel
20151Ext.TabPanel.AccessStack = function(){
20152    var items = [];
20153    return {
20154        add : function(item){
20155            items.push(item);
20156            if(items.length > 10){
20157                items.shift();
20158            }
20159        },
20160
20161        remove : function(item){
20162            var s = [];
20163            for(var i = 0, len = items.length; i < len; i++) {
20164                if(items[i] != item){
20165                    s.push(items[i]);
20166                }
20167            }
20168            items = s;
20169        },
20170
20171        next : function(){
20172            return items.pop();
20173        }
20174    };
20175};
20176
20177
20178
20179
20180Ext.Button = Ext.extend(Ext.Component, {
20181    
20182    hidden : false,
20183    
20184    disabled : false,
20185    
20186    pressed : false,
20187    
20188
20189    
20190
20191    
20192
20193    
20194    enableToggle: false,
20195    
20196    
20197    
20198    menuAlign : "tl-bl?",
20199
20200    
20201    
20202    type : 'button',
20203
20204    // private
20205    menuClassTarget: 'tr',
20206
20207    
20208    clickEvent : 'click',
20209
20210    
20211    handleMouseEvents : true,
20212
20213    
20214    tooltipType : 'qtip',
20215
20216    
20217    buttonSelector : "button:first-child",
20218
20219    
20220    
20221
20222    initComponent : function(){
20223        Ext.Button.superclass.initComponent.call(this);
20224
20225        this.addEvents(
20226            
20227            "click",
20228            
20229            "toggle",
20230            
20231            'mouseover',
20232            
20233            'mouseout',
20234            
20235            'menushow',
20236            
20237            'menuhide',
20238            
20239            'menutriggerover',
20240            
20241            'menutriggerout'
20242        );
20243        if(this.menu){
20244            this.menu = Ext.menu.MenuMgr.get(this.menu);
20245        }
20246        if(typeof this.toggleGroup === 'string'){
20247            this.enableToggle = true;
20248        }
20249    },
20250
20251    // private
20252    onRender : function(ct, position){
20253        if(!this.template){
20254            if(!Ext.Button.buttonTemplate){
20255                // hideous table template
20256                Ext.Button.buttonTemplate = new Ext.Template(
20257                    '<table border="0" cellpadding="0" cellspacing="0" class="x-btn-wrap"><tbody><tr>',
20258                    '<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>',
20259                    "</tr></tbody></table>");
20260            }
20261            this.template = Ext.Button.buttonTemplate;
20262        }
20263        var btn, targs = [this.text || '&#160;', this.type];
20264
20265        if(position){
20266            btn = this.template.insertBefore(position, targs, true);
20267        }else{
20268            btn = this.template.append(ct, targs, true);
20269        }
20270        var btnEl = btn.child(this.buttonSelector);
20271        btnEl.on('focus', this.onFocus, this);
20272        btnEl.on('blur', this.onBlur, this);
20273
20274        this.initButtonEl(btn, btnEl);
20275
20276        if(this.menu){
20277            this.el.child(this.menuClassTarget).addClass("x-btn-with-menu");
20278        }
20279        Ext.ButtonToggleMgr.register(this);
20280    },
20281
20282    // private
20283    initButtonEl : function(btn, btnEl){
20284
20285        this.el = btn;
20286        btn.addClass("x-btn");
20287
20288        if(this.id){
20289            this.el.dom.id = this.el.id = this.id;
20290        }
20291        if(this.icon){
20292            btnEl.setStyle('background-image', 'url(' +this.icon +')');
20293        }
20294        if(this.iconCls){
20295            btnEl.addClass(this.iconCls);
20296            if(!this.cls){
20297                btn.addClass(this.text ? 'x-btn-text-icon' : 'x-btn-icon');
20298            }
20299        }
20300        if(this.tabIndex !== undefined){
20301            btnEl.dom.tabIndex = this.tabIndex;
20302        }
20303        if(this.tooltip){
20304            if(typeof this.tooltip == 'object'){
20305                Ext.QuickTips.register(Ext.apply({
20306                      target: btnEl.id
20307                }, this.tooltip));
20308            } else {
20309                btnEl.dom[this.tooltipType] = this.tooltip;
20310            }
20311        }
20312
20313        if(this.pressed){
20314            this.el.addClass("x-btn-pressed");
20315        }
20316
20317        if(this.handleMouseEvents){
20318            btn.on("mouseover", this.onMouseOver, this);
20319            // new functionality for monitoring on the document level
20320            //btn.on("mouseout", this.onMouseOut, this);
20321            btn.on("mousedown", this.onMouseDown, this);
20322        }
20323
20324        if(this.menu){
20325            this.menu.on("show", this.onMenuShow, this);
20326            this.menu.on("hide", this.onMenuHide, this);
20327        }
20328
20329        if(this.repeat){
20330            var repeater = new Ext.util.ClickRepeater(btn,
20331                typeof this.repeat == "object" ? this.repeat : {}
20332            );
20333            repeater.on("click", this.onClick,  this);
20334        }
20335
20336        btn.on(this.clickEvent, this.onClick, this);
20337    },
20338
20339    // private
20340    afterRender : function(){
20341        Ext.Button.superclass.afterRender.call(this);
20342        if(Ext.isIE6){
20343            this.autoWidth.defer(1, this);
20344        }else{
20345            this.autoWidth();
20346        }
20347    },
20348
20349    
20350    setIconClass : function(cls){
20351        if(this.el){
20352            this.el.child(this.buttonSelector).replaceClass(this.iconCls, cls);
20353        }
20354        this.iconCls = cls;
20355    },
20356
20357    // private
20358    beforeDestroy: function(){
20359    	if(this.rendered){
20360            var btnEl = this.el.child(this.buttonSelector);
20361            if(btnEl){
20362                if(this.tooltip){
20363                    Ext.QuickTips.unregister(btnEl);
20364                }
20365                btnEl.removeAllListeners();
20366            }
20367	    }
20368        if(this.menu){
20369            Ext.destroy(this.menu);
20370        }
20371    },
20372
20373    // private
20374    onDestroy : function(){
20375        if(this.rendered){
20376            Ext.ButtonToggleMgr.unregister(this);
20377        }
20378    },
20379
20380    // private
20381    autoWidth : function(){
20382        if(this.el){
20383            this.el.setWidth("auto");
20384            if(Ext.isIE7 && Ext.isStrict){
20385                var ib = this.el.child(this.buttonSelector);
20386                if(ib && ib.getWidth() > 20){
20387                    ib.clip();
20388                    ib.setWidth(Ext.util.TextMetrics.measure(ib, this.text).width+ib.getFrameWidth('lr'));
20389                }
20390            }
20391            if(this.minWidth){
20392                if(this.el.getWidth() < this.minWidth){
20393                    this.el.setWidth(this.minWidth);
20394                }
20395            }
20396        }
20397    },
20398
20399    
20400    setHandler : function(handler, scope){
20401        this.handler = handler;
20402        this.scope = scope;
20403    },
20404
20405    
20406    setText : function(text){
20407        this.text = text;
20408        if(this.el){
20409            this.el.child("td.x-btn-center " + this.buttonSelector).update(text);
20410        }
20411        this.autoWidth();
20412    },
20413
20414    
20415    getText : function(){
20416        return this.text;
20417    },
20418
20419    
20420    toggle : function(state){
20421        state = state === undefined ? !this.pressed : state;
20422        if(state != this.pressed){
20423            if(state){
20424                this.el.addClass("x-btn-pressed");
20425                this.pressed = true;
20426                this.fireEvent("toggle", this, true);
20427            }else{
20428                this.el.removeClass("x-btn-pressed");
20429                this.pressed = false;
20430                this.fireEvent("toggle", this, false);
20431            }
20432            if(this.toggleHandler){
20433                this.toggleHandler.call(this.scope || this, this, state);
20434            }
20435        }
20436    },
20437
20438    
20439    focus : function(){
20440        this.el.child(this.buttonSelector).focus();
20441    },
20442
20443    // private
20444    onDisable : function(){
20445        if(this.el){
20446            if(!Ext.isIE6 || !this.text){
20447                this.el.addClass(this.disabledClass);
20448            }
20449            this.el.dom.disabled = true;
20450        }
20451        this.disabled = true;
20452    },
20453
20454    // private
20455    onEnable : function(){
20456        if(this.el){
20457            if(!Ext.isIE6 || !this.text){
20458                this.el.removeClass(this.disabledClass);
20459            }
20460            this.el.dom.disabled = false;
20461        }
20462        this.disabled = false;
20463    },
20464
20465    
20466    showMenu : function(){
20467        if(this.menu){
20468            this.menu.show(this.el, this.menuAlign);
20469        }
20470        return this;
20471    },
20472
20473    
20474    hideMenu : function(){
20475        if(this.menu){
20476            this.menu.hide();
20477        }
20478        return this;
20479    },
20480
20481    
20482    hasVisibleMenu : function(){
20483        return this.menu && this.menu.isVisible();
20484    },
20485
20486    // private
20487    onClick : function(e){
20488        if(e){
20489            e.preventDefault();
20490        }
20491        if(e.button != 0){
20492            return;
20493        }
20494        if(!this.disabled){
20495            if(this.enableToggle && (this.allowDepress !== false || !this.pressed)){
20496                this.toggle();
20497            }
20498            if(this.menu && !this.menu.isVisible() && !this.ignoreNextClick){
20499                this.showMenu();
20500            }
20501            this.fireEvent("click", this, e);
20502            if(this.handler){
20503                //this.el.removeClass("x-btn-over");
20504                this.handler.call(this.scope || this, this, e);
20505            }
20506        }
20507    },
20508
20509    // private
20510    isMenuTriggerOver : function(e, internal){
20511        return this.menu && !internal;
20512    },
20513
20514    // private
20515    isMenuTriggerOut : function(e, internal){
20516        return this.menu && !internal;
20517    },
20518
20519    // private
20520    onMouseOver : function(e){
20521        if(!this.disabled){
20522            var internal = e.within(this.el,  true);
20523            if(!internal){
20524                this.el.addClass("x-btn-over");
20525                if(!this.monitoringMouseOver){
20526                    Ext.getDoc().on('mouseover', this.monitorMouseOver, this);
20527                    this.monitoringMouseOver = true;
20528                }
20529                this.fireEvent('mouseover', this, e);
20530            }
20531            if(this.isMenuTriggerOver(e, internal)){
20532                this.fireEvent('menutriggerover', this, this.menu, e);
20533            }
20534        }
20535    },
20536
20537    // private
20538    monitorMouseOver : function(e){
20539        if(e.target != this.el.dom && !e.within(this.el)){
20540            if(this.monitoringMouseOver){
20541                Ext.getDoc().un('mouseover', this.monitorMouseOver, this);
20542                this.monitoringMouseOver = false;
20543            }
20544            this.onMouseOut(e);
20545        }
20546    },
20547
20548    // private
20549    onMouseOut : function(e){
20550        var internal = e.within(this.el) && e.target != this.el.dom;
20551        this.el.removeClass("x-btn-over");
20552        this.fireEvent('mouseout', this, e);
20553        if(this.isMenuTriggerOut(e, internal)){
20554            this.fireEvent('menutriggerout', this, this.menu, e);
20555        }
20556    },
20557    // private
20558    onFocus : function(e){
20559        if(!this.disabled){
20560            this.el.addClass("x-btn-focus");
20561        }
20562    },
20563    // private
20564    onBlur : function(e){
20565        this.el.removeClass("x-btn-focus");
20566    },
20567
20568    // private
20569    getClickEl : function(e, isUp){
20570       return this.el;
20571    },
20572
20573    // private
20574    onMouseDown : function(e){
20575        if(!this.disabled && e.button == 0){
20576            this.getClickEl(e).addClass("x-btn-click");
20577            Ext.getDoc().on('mouseup', this.onMouseUp, this);
20578        }
20579    },
20580    // private
20581    onMouseUp : function(e){
20582        if(e.button == 0){
20583            this.getClickEl(e, true).removeClass("x-btn-click");
20584            Ext.getDoc().un('mouseup', this.onMouseUp, this);
20585        }
20586    },
20587    // private
20588    onMenuShow : function(e){
20589        this.ignoreNextClick = 0;
20590        this.el.addClass("x-btn-menu-active");
20591        this.fireEvent('menushow', this, this.menu);
20592    },
20593    // private
20594    onMenuHide : function(e){
20595        this.el.removeClass("x-btn-menu-active");
20596        this.ignoreNextClick = this.restoreClick.defer(250, this);
20597        this.fireEvent('menuhide', this, this.menu);
20598    },
20599
20600    // private
20601    restoreClick : function(){
20602        this.ignoreNextClick = 0;
20603    }
20604
20605
20606
20607    
20608});
20609Ext.reg('button', Ext.Button);
20610
20611// Private utility class used by Button
20612Ext.ButtonToggleMgr = function(){
20613   var groups = {};
20614
20615   function toggleGroup(btn, state){
20616       if(state){
20617           var g = groups[btn.toggleGroup];
20618           for(var i = 0, l = g.length; i < l; i++){
20619               if(g[i] != btn){
20620                   g[i].toggle(false);
20621               }
20622           }
20623       }
20624   }
20625
20626   return {
20627       register : function(btn){
20628           if(!btn.toggleGroup){
20629               return;
20630           }
20631           var g = groups[btn.toggleGroup];
20632           if(!g){
20633               g = groups[btn.toggleGroup] = [];
20634           }
20635           g.push(btn);
20636           btn.on("toggle", toggleGroup);
20637       },
20638
20639       unregister : function(btn){
20640           if(!btn.toggleGroup){
20641               return;
20642           }
20643           var g = groups[btn.toggleGroup];
20644           if(g){
20645               g.remove(btn);
20646               btn.un("toggle", toggleGroup);
20647           }
20648       }
20649   };
20650}();
20651
20652Ext.SplitButton = Ext.extend(Ext.Button, {
20653	// private
20654    arrowSelector : 'button:last',
20655
20656    // private
20657    initComponent : function(){
20658        Ext.SplitButton.superclass.initComponent.call(this);
20659        
20660        this.addEvents("arrowclick");
20661    },
20662
20663    // private
20664    onRender : function(ct, position){
20665        // this is one sweet looking template!
20666        var tpl = new Ext.Template(
20667            '<table cellspacing="0" class="x-btn-menu-wrap x-btn"><tr><td>',
20668            '<table cellspacing="0" class="x-btn-wrap x-btn-menu-text-wrap"><tbody>',
20669            '<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>',
20670            "</tbody></table></td><td>",
20671            '<table cellspacing="0" class="x-btn-wrap x-btn-menu-arrow-wrap"><tbody>',
20672            '<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>',
20673            "</tbody></table></td></tr></table>"
20674        );
20675        var btn, targs = [this.text || '&#160;', this.type];
20676        if(position){
20677            btn = tpl.insertBefore(position, targs, true);
20678        }else{
20679            btn = tpl.append(ct, targs, true);
20680        }
20681        var btnEl = btn.child(this.buttonSelector);
20682
20683        this.initButtonEl(btn, btnEl);
20684        this.arrowBtnTable = btn.child("table:last");
20685        if(this.arrowTooltip){
20686            btn.child(this.arrowSelector).dom[this.tooltipType] = this.arrowTooltip;
20687        }
20688    },
20689
20690    // private
20691    autoWidth : function(){
20692        if(this.el){
20693            var tbl = this.el.child("table:first");
20694            var tbl2 = this.el.child("table:last");
20695            this.el.setWidth("auto");
20696            tbl.setWidth("auto");
20697            if(Ext.isIE7 && Ext.isStrict){
20698                var ib = this.el.child(this.buttonSelector);
20699                if(ib && ib.getWidth() > 20){
20700                    ib.clip();
20701                    ib.setWidth(Ext.util.TextMetrics.measure(ib, this.text).width+ib.getFrameWidth('lr'));
20702                }
20703            }
20704            if(this.minWidth){
20705                if((tbl.getWidth()+tbl2.getWidth()) < this.minWidth){
20706                    tbl.setWidth(this.minWidth-tbl2.getWidth());
20707                }
20708            }
20709            this.el.setWidth(tbl.getWidth()+tbl2.getWidth());
20710        } 
20711    },
20712
20713    
20714    setArrowHandler : function(handler, scope){
20715        this.arrowHandler = handler;
20716        this.scope = scope;  
20717    },
20718
20719    // private
20720    onClick : function(e){
20721        e.preventDefault();
20722        if(!this.disabled){
20723            if(e.getTarget(".x-btn-menu-arrow-wrap")){
20724                if(this.menu && !this.menu.isVisible() && !this.ignoreNextClick){
20725                    this.showMenu();
20726                }
20727                this.fireEvent("arrowclick", this, e);
20728                if(this.arrowHandler){
20729                    this.arrowHandler.call(this.scope || this, this, e);
20730                }
20731            }else{
20732                if(this.enableToggle){
20733                    this.toggle();
20734                }
20735                this.fireEvent("click", this, e);
20736                if(this.handler){
20737                    this.handler.call(this.scope || this, this, e);
20738                }
20739            }
20740        }
20741    },
20742
20743    // private
20744    getClickEl : function(e, isUp){
20745        if(!isUp){
20746            return (this.lastClickEl = e.getTarget("table", 10, true));
20747        }
20748        return this.lastClickEl;
20749    },
20750
20751    // private
20752    onDisable : function(){
20753        if(this.el){
20754            if(!Ext.isIE6){
20755                this.el.addClass("x-item-disabled");
20756            }
20757            this.el.child(this.buttonSelector).dom.disabled = true;
20758            this.el.child(this.arrowSelector).dom.disabled = true;
20759        }
20760        this.disabled = true;
20761    },
20762
20763    // private
20764    onEnable : function(){
20765        if(this.el){
20766            if(!Ext.isIE6){
20767                this.el.removeClass("x-item-disabled");
20768            }
20769            this.el.child(this.buttonSelector).dom.disabled = false;
20770            this.el.child(this.arrowSelector).dom.disabled = false;
20771        }
20772        this.disabled = false;
20773    },
20774
20775    // private
20776    isMenuTriggerOver : function(e){
20777        return this.menu && e.within(this.arrowBtnTable) && !e.within(this.arrowBtnTable, true);
20778    },
20779
20780    // private
20781    isMenuTriggerOut : function(e, internal){
20782        return this.menu && !e.within(this.arrowBtnTable);
20783    },
20784
20785    // private
20786    onDestroy : function(){
20787        Ext.destroy(this.arrowBtnTable);
20788        Ext.SplitButton.superclass.onDestroy.call(this);
20789    }
20790});
20791
20792// backwards compat
20793Ext.MenuButton = Ext.SplitButton;
20794
20795
20796Ext.reg('splitbutton', Ext.SplitButton);
20797
20798Ext.CycleButton = Ext.extend(Ext.SplitButton, {
20799    
20800    
20801    
20802    
20803	
20804
20805    // private
20806    getItemText : function(item){
20807        if(item && this.showText === true){
20808            var text = '';
20809            if(this.prependText){
20810                text += this.prependText;
20811            }
20812            text += item.text;
20813            return text;
20814        }
20815        return undefined;
20816    },
20817
20818    
20819    setActiveItem : function(item, suppressEvent){
20820        if(typeof item != 'object'){
20821            item = this.menu.items.get(item);
20822        }
20823        if(item){
20824            if(!this.rendered){
20825                this.text = this.getItemText(item);
20826                this.iconCls = item.iconCls;
20827            }else{
20828                var t = this.getItemText(item);
20829                if(t){
20830                    this.setText(t);
20831                }
20832                this.setIconClass(item.iconCls);
20833            }
20834            this.activeItem = item;
20835            if(!item.checked){
20836                item.setChecked(true, true);
20837            }
20838            if(this.forceIcon){
20839                this.setIconClass(this.forceIcon);
20840            }
20841            if(!suppressEvent){
20842                this.fireEvent('change', this, item);
20843            }
20844        }
20845    },
20846
20847    
20848    getActiveItem : function(){
20849        return this.activeItem;
20850    },
20851
20852    // private
20853    initComponent : function(){
20854        this.addEvents(
20855            
20856            "change"
20857        );
20858
20859        if(this.changeHandler){
20860            this.on('change', this.changeHandler, this.scope||this);
20861            delete this.changeHandler;
20862        }
20863
20864        this.itemCount = this.items.length;
20865
20866        this.menu = {cls:'x-cycle-menu', items:[]};
20867        var checked;
20868        for(var i = 0, len = this.itemCount; i < len; i++){
20869            var item = this.items[i];
20870            item.group = item.group || this.id;
20871            item.itemIndex = i;
20872            item.checkHandler = this.checkHandler;
20873            item.scope = this;
20874            item.checked = item.checked || false;
20875            this.menu.items.push(item);
20876            if(item.checked){
20877                checked = item;
20878            }
20879        }
20880        this.setActiveItem(checked, true);
20881        Ext.CycleButton.superclass.initComponent.call(this);
20882
20883        this.on('click', this.toggleSelected, this);
20884    },
20885
20886    // private
20887    checkHandler : function(item, pressed){
20888        if(pressed){
20889            this.setActiveItem(item);
20890        }
20891    },
20892
20893    
20894    toggleSelected : function(){
20895        this.menu.render();
20896		
20897		var nextIdx, checkItem;
20898		for (var i = 1; i < this.itemCount; i++) {
20899			nextIdx = (this.activeItem.itemIndex + i) % this.itemCount;
20900			// check the potential item
20901			checkItem = this.menu.items.itemAt(nextIdx);
20902			// if its not disabled then check it.
20903			if (!checkItem.disabled) {
20904				checkItem.setChecked(true);
20905				break;
20906			}
20907		}
20908    }
20909});
20910Ext.reg('cycle', Ext.CycleButton);
20911 
20912 Ext.Toolbar = function(config){
20913    if(Ext.isArray(config)){
20914        config = {buttons:config};
20915    }
20916    Ext.Toolbar.superclass.constructor.call(this, config);
20917};
20918
20919(function(){
20920
20921var T = Ext.Toolbar;
20922
20923Ext.extend(T, Ext.BoxComponent, {
20924
20925    trackMenus : true,
20926
20927    // private
20928    initComponent : function(){
20929        T.superclass.initComponent.call(this);
20930
20931        if(this.items){
20932            this.buttons = this.items;
20933        }
20934        
20935        this.items = new Ext.util.MixedCollection(false, function(o){
20936            return o.itemId || o.id || Ext.id();
20937        });
20938    },
20939
20940    // private
20941    autoCreate: {
20942        cls:'x-toolbar x-small-editor',
20943        html:'<table cellspacing="0"><tr></tr></table>'
20944    },
20945
20946    // private
20947    onRender : function(ct, position){
20948        this.el = ct.createChild(Ext.apply({ id: this.id },this.autoCreate), position);
20949        this.tr = this.el.child("tr", true);
20950    },
20951
20952    // private
20953    afterRender : function(){
20954        T.superclass.afterRender.call(this);
20955        if(this.buttons){
20956            this.add.apply(this, this.buttons);
20957            delete this.buttons;
20958        }
20959    },
20960
20961    
20962    add : function(){
20963        var a = arguments, l = a.length;
20964        for(var i = 0; i < l; i++){
20965            var el = a[i];
20966            if(el.isFormField){ // some kind of form field
20967                this.addField(el);
20968            }else if(el.render){ // some kind of Toolbar.Item
20969                this.addItem(el);
20970            }else if(typeof el == "string"){ // string
20971                if(el == "separator" || el == "-"){
20972                    this.addSeparator();
20973                }else if(el == " "){
20974                    this.addSpacer();
20975                }else if(el == "->"){
20976                    this.addFill();
20977                }else{
20978                    this.addText(el);
20979                }
20980            }else if(el.tagName){ // element
20981                this.addElement(el);
20982            }else if(typeof el == "object"){ // must be button config?
20983                if(el.xtype){
20984                    this.addField(Ext.ComponentMgr.create(el, 'button'));
20985                }else{
20986                    this.addButton(el);
20987                }
20988            }
20989        }
20990    },
20991    
20992    
20993    addSeparator : function(){
20994        return this.addItem(new T.Separator());
20995    },
20996
20997    
20998    addSpacer : function(){
20999        return this.addItem(new T.Spacer());
21000    },
21001
21002    
21003    addFill : function(){
21004        return this.addItem(new T.Fill());
21005    },
21006
21007    
21008    addElement : function(el){
21009        return this.addItem(new T.Item(el));
21010    },
21011    
21012    
21013    addItem : function(item){
21014        var td = this.nextBlock();
21015        this.initMenuTracking(item);
21016        item.render(td);
21017        this.items.add(item);
21018        return item;
21019    },
21020    
21021    
21022    addButton : function(config){
21023        if(Ext.isArray(config)){
21024            var buttons = [];
21025            for(var i = 0, len = config.length; i < len; i++) {
21026                buttons.push(this.addButton(config[i]));
21027            }
21028            return buttons;
21029        }
21030        var b = config;
21031        if(!(config instanceof T.Button)){
21032            b = config.split ? 
21033                new T.SplitButton(config) :
21034                new T.Button(config);
21035        }
21036        var td = this.nextBlock();
21037        this.initMenuTracking(b);
21038        b.render(td);
21039        this.items.add(b);
21040        return b;
21041    },
21042
21043    // private
21044    initMenuTracking : function(item){
21045        if(this.trackMenus && item.menu){
21046            item.on({
21047                'menutriggerover' : this.onButtonTriggerOver,
21048                'menushow' : this.onButtonMenuShow,
21049                'menuhide' : this.onButtonMenuHide,
21050                scope: this
21051            })
21052        }
21053    },
21054
21055    
21056    addText : function(text){
21057        return this.addItem(new T.TextItem(text));
21058    },
21059    
21060    
21061    insertButton : function(index, item){
21062        if(Ext.isArray(item)){
21063            var buttons = [];
21064            for(var i = 0, len = item.length; i < len; i++) {
21065               buttons.push(this.insertButton(index + i, item[i]));
21066            }
21067            return buttons;
21068        }
21069        if (!(item instanceof T.Button)){
21070           item = new T.Button(item);
21071        }
21072        var td = document.createElement("td");
21073        this.tr.insertBefore(td, this.tr.childNodes[index]);
21074        this.initMenuTracking(item);
21075        item.render(td);
21076        this.items.insert(index, item);
21077        return item;
21078    },
21079    
21080    
21081    addDom : function(config, returnEl){
21082        var td = this.nextBlock();
21083        Ext.DomHelper.overwrite(td, config);
21084        var ti = new T.Item(td.firstChild);
21085        ti.render(td);
21086        this.items.add(ti);
21087        return ti;
21088    },
21089
21090    
21091    addField : function(field){
21092        var td = this.nextBlock();
21093        field.render(td);
21094        var ti = new T.Item(td.firstChild);
21095        ti.render(td);
21096        this.items.add(field);
21097        return ti;
21098    },
21099
21100    // private
21101    nextBlock : function(){
21102        var td = document.createElement("td");
21103        this.tr.appendChild(td);
21104        return td;
21105    },
21106
21107    // private
21108    onDestroy : function(){
21109        Ext.Toolbar.superclass.onDestroy.call(this);
21110        if(this.rendered){
21111            if(this.items){ // rendered?
21112                Ext.destroy.apply(Ext, this.items.items);
21113            }
21114            Ext.Element.uncache(this.tr);
21115        }
21116    },
21117
21118    // private
21119    onDisable : function(){
21120        this.items.each(function(item){
21121             if(item.disable){
21122                 item.disable();
21123             }
21124        });
21125    },
21126
21127    // private
21128    onEnable : function(){
21129        this.items.each(function(item){
21130             if(item.enable){
21131                 item.enable();
21132             }
21133        });
21134    },
21135
21136    // private
21137    onButtonTriggerOver : function(btn){
21138        if(this.activeMenuBtn && this.activeMenuBtn != btn){
21139            this.activeMenuBtn.hideMenu();
21140            btn.showMenu();
21141            this.activeMenuBtn = btn;
21142        }
21143    },
21144
21145    // private
21146    onButtonMenuShow : function(btn){
21147        this.activeMenuBtn = btn;
21148    },
21149
21150    // private
21151    onButtonMenuHide : function(btn){
21152        delete this.activeMenuBtn;
21153    }
21154
21155    
21156});
21157Ext.reg('toolbar', Ext.Toolbar);
21158
21159
21160T.Item = function(el){
21161    this.el = Ext.getDom(el);
21162    this.id = Ext.id(this.el);
21163    this.hidden = false;
21164};
21165
21166T.Item.prototype = {
21167    
21168    
21169    getEl : function(){
21170       return this.el;  
21171    },
21172
21173    // private
21174    render : function(td){
21175        this.td = td;
21176        td.appendChild(this.el);
21177    },
21178    
21179    
21180    destroy : function(){
21181        if(this.el){
21182            var el = Ext.get(this.el);
21183            Ext.destroy(el);
21184        }
21185        Ext.removeNode(this.td);
21186    },
21187    
21188    
21189    show: function(){
21190        this.hidden = false;
21191        this.td.style.display = "";
21192    },
21193    
21194    
21195    hide: function(){
21196        this.hidden = true;
21197        this.td.style.display = "none";
21198    },
21199    
21200    
21201    setVisible: function(visible){
21202        if(visible) {
21203            this.show();
21204        }else{
21205            this.hide();
21206        }
21207    },
21208    
21209    
21210    focus : function(){
21211        Ext.fly(this.el).focus();
21212    },
21213    
21214    
21215    disable : function(){
21216        Ext.fly(this.td).addClass("x-item-disabled");
21217        this.disabled = true;
21218        this.el.disabled = true;
21219    },
21220    
21221    
21222    enable : function(){
21223        Ext.fly(this.td).removeClass("x-item-disabled");
21224        this.disabled = false;
21225        this.el.disabled = false;
21226    }
21227};
21228Ext.reg('tbitem', T.Item);
21229
21230
21231
21232T.Separator = function(){
21233    var s = document.createElement("span");
21234    s.className = "ytb-sep";
21235    T.Separator.superclass.constructor.call(this, s);
21236};
21237Ext.extend(T.Separator, T.Item, {
21238    enable:Ext.emptyFn,
21239    disable:Ext.emptyFn,
21240    focus:Ext.emptyFn
21241});
21242Ext.reg('tbseparator', T.Separator);
21243
21244
21245T.Spacer = function(){
21246    var s = document.createElement("div");
21247    s.className = "ytb-spacer";
21248    T.Spacer.superclass.constructor.call(this, s);
21249};
21250Ext.extend(T.Spacer, T.Item, {
21251    enable:Ext.emptyFn,
21252    disable:Ext.emptyFn,
21253    focus:Ext.emptyFn
21254});
21255
21256Ext.reg('tbspacer', T.Spacer);
21257
21258
21259T.Fill = Ext.extend(T.Spacer, {
21260    // private
21261    render : function(td){
21262        td.style.width = '100%';
21263        T.Fill.superclass.render.call(this, td);
21264    }
21265});
21266Ext.reg('tbfill', T.Fill);
21267
21268
21269T.TextItem = function(t){
21270    var s = document.createElement("span");
21271    s.className = "ytb-text";
21272    s.innerHTML = t.text ? t.text : t;
21273    T.TextItem.superclass.constructor.call(this, s);
21274};
21275Ext.extend(T.TextItem, T.Item, {
21276    enable:Ext.emptyFn,
21277    disable:Ext.emptyFn,
21278    focus:Ext.emptyFn
21279});
21280Ext.reg('tbtext', T.TextItem);
21281
21282
21283
21284T.Button = Ext.extend(Ext.Button, {
21285    hideParent : true,
21286
21287    onDestroy : function(){
21288        T.Button.superclass.onDestroy.call(this);
21289        if(this.container){
21290            this.container.remove();
21291        }
21292    }
21293});
21294Ext.reg('tbbutton', T.Button);
21295
21296
21297T.SplitButton = Ext.extend(Ext.SplitButton, {
21298    hideParent : true,
21299
21300    onDestroy : function(){
21301        T.SplitButton.superclass.onDestroy.call(this);
21302        if(this.container){
21303            this.container.remove();
21304        }
21305    }
21306});
21307
21308Ext.reg('tbsplit', T.SplitButton);
21309// backwards compat
21310T.MenuButton = T.SplitButton;
21311
21312})();
21313
21314
21315Ext.PagingToolbar = Ext.extend(Ext.Toolbar, {
21316    
21317    
21318    
21319    pageSize: 20,
21320    
21321    displayMsg : 'A mostrar {0} - {1} de {2}',
21322    
21323    emptyMsg : 'No data to display',
21324    
21325    beforePageText : "Página",
21326    
21327    afterPageText : "de {0}",
21328    
21329    firstText : "Primeira Página",
21330    
21331    prevText : "Página Anterior",
21332    
21333    nextText : "Próxima Página",
21334    
21335    lastText : "Última Página",
21336    
21337    refreshText : "Refrescar",
21338
21339    
21340    paramNames : {start: 'start', limit: 'limit'},
21341
21342    // private
21343    initComponent : function(){
21344        this.addEvents(
21345            
21346            'change',
21347            
21348            'beforechange'
21349        );
21350        Ext.PagingToolbar.superclass.initComponent.call(this);
21351        this.cursor = 0;
21352        this.bind(this.store);
21353    },
21354
21355    // private
21356    onRender : function(ct, position){
21357        Ext.PagingToolbar.superclass.onRender.call(this, ct, position);
21358        this.first = this.addButton({
21359            tooltip: this.firstText,
21360            iconCls: "x-tbar-page-first",
21361            disabled: true,
21362            handler: this.onClick.createDelegate(this, ["first"])
21363        });
21364        this.prev = this.addButton({
21365            tooltip: this.prevText,
21366            iconCls: "x-tbar-page-prev",
21367            disabled: true,
21368            handler: this.onClick.createDelegate(this, ["prev"])
21369        });
21370        this.addSeparator();
21371        this.add(this.beforePageText);
21372        this.field = Ext.get(this.addDom({
21373           tag: "input",
21374           type: "text",
21375           size: "3",
21376           value: "1",
21377           cls: "x-tbar-page-number"
21378        }).el);
21379        this.field.on("keydown", this.onPagingKeydown, this);
21380        this.field.on("focus", function(){this.dom.select();});
21381        this.field.on("blur", this.onPagingBlur, this);
21382        this.afterTextEl = this.addText(String.format(this.afterPageText, 1));
21383        this.field.setHeight(18);
21384        this.addSeparator();
21385        this.next = this.addButton({
21386            tooltip: this.nextText,
21387            iconCls: "x-tbar-page-next",
21388            disabled: true,
21389            handler: this.onClick.createDelegate(this, ["next"])
21390        });
21391        this.last = this.addButton({
21392            tooltip: this.lastText,
21393            iconCls: "x-tbar-page-last",
21394            disabled: true,
21395            handler: this.onClick.createDelegate(this, ["last"])
21396        });
21397        this.addSeparator();
21398        this.loading = this.addButton({
21399            tooltip: this.refreshText,
21400            iconCls: "x-tbar-loading",
21401            handler: this.onClick.createDelegate(this, ["refresh"])
21402        });
21403
21404        if(this.displayInfo){
21405            this.displayEl = Ext.fly(this.el.dom).createChild({cls:'x-paging-info'});
21406        }
21407        if(this.dsLoaded){
21408            this.onLoad.apply(this, this.dsLoaded);
21409        }
21410    },
21411
21412    // private
21413    updateInfo : function(){
21414        if(this.displayEl){
21415            var count = this.store.getCount();
21416            var msg = count == 0 ?
21417                this.emptyMsg :
21418                String.format(
21419                    this.displayMsg,
21420                    this.cursor+1, this.cursor+count, this.store.getTotalCount()
21421                );
21422            this.displayEl.update(msg);
21423        }
21424    },
21425
21426    // private
21427    onLoad : function(store, r, o){
21428        if(!this.rendered){
21429            this.dsLoaded = [store, r, o];
21430            return;
21431        }
21432       this.cursor = o.params ? o.params[this.paramNames.start] : 0;
21433       var d = this.getPageData(), ap = d.activePage, ps = d.pages;
21434
21435        this.afterTextEl.el.innerHTML = String.format(this.afterPageText, d.pages);
21436        this.field.dom.value = ap;
21437        this.first.setDisabled(ap == 1);
21438        this.prev.setDisabled(ap == 1);
21439        this.next.setDisabled(ap == ps);
21440        this.last.setDisabled(ap == ps);
21441        this.loading.enable();
21442        this.updateInfo();
21443        this.fireEvent('change', this, d);
21444    },
21445
21446    // private
21447    getPageData : function(){
21448        var total = this.store.getTotalCount();
21449        return {
21450            total : total,
21451            activePage : Math.ceil((this.cursor+this.pageSize)/this.pageSize),
21452            pages :  total < this.pageSize ? 1 : Math.ceil(total/this.pageSize)
21453        };
21454    },
21455
21456    // private
21457    onLoadError : function(){
21458        if(!this.rendered){
21459            return;
21460        }
21461        this.loading.enable();
21462    },
21463
21464    // private
21465    readPage : function(d){
21466        var v = this.field.dom.value, pageNum;
21467        if (!v || isNaN(pageNum = parseInt(v, 10))) {
21468            this.field.dom.value = d.activePage;
21469            return false;
21470        }
21471        return pageNum;
21472    },
21473
21474    //private
21475    onPagingBlur: function(e){
21476        this.field.dom.value = this.getPageData().activePage;
21477    },
21478
21479    // private
21480    onPagingKeydown : function(e){
21481        var k = e.getKey(), d = this.getPageData(), pageNum;
21482        if (k == e.RETURN) {
21483            e.stopEvent();
21484            pageNum = this.readPage(d);
21485            if(pageNum !== false){
21486                pageNum = Math.min(Math.max(1, pageNum), d.pages) - 1;
21487                this.doLoad(pageNum * this.pageSize);
21488            }
21489        }else if (k == e.HOME || k == e.END){
21490            e.stopEvent();
21491            pageNum = k == e.HOME ? 1 : d.pages;
21492            this.field.dom.value = pageNum;
21493        }else if (k == e.UP || k == e.PAGEUP || k == e.DOWN || k == e.PAGEDOWN){
21494            e.stopEvent();
21495            if(pageNum = this.readPage(d)){
21496                var increment = e.shiftKey ? 10 : 1;
21497                if(k == e.DOWN || k == e.PAGEDOWN){
21498                    increment *= -1;
21499                }
21500                pageNum += increment;
21501                if(pageNum >= 1 & pageNum <= d.pages){
21502                    this.field.dom.value = pageNum;
21503                }
21504            }
21505        }
21506    },
21507
21508    // private
21509    beforeLoad : function(){
21510        if(this.rendered && this.loading){
21511            this.loading.disable();
21512        }
21513    },
21514
21515    // private
21516    doLoad : function(start){
21517        var o = {}, pn = this.paramNames;
21518        o[pn.start] = start;
21519        o[pn.limit] = this.pageSize;
21520        if(this.fireEvent('beforechange', this, o) !== false){
21521            this.store.load({params:o});
21522        }
21523    },
21524
21525    
21526    changePage: function(page){
21527        this.doLoad(((page-1) * this.pageSize).constrain(0, this.store.getTotalCount()));
21528    },
21529
21530    // private
21531    onClick : function(which){
21532        var store = this.store;
21533        switch(which){
21534            case "first":
21535                this.doLoad(0);
21536            break;
21537            case "prev":
21538                this.doLoad(Math.max(0, this.cursor-this.pageSize));
21539            break;
21540            case "next":
21541                this.doLoad(this.cursor+this.pageSize);
21542            break;
21543            case "last":
21544                var total = store.getTotalCount();
21545                var extra = total % this.pageSize;
21546                var lastStart = extra ? (total - extra) : total-this.pageSize;
21547                this.doLoad(lastStart);
21548            break;
21549            case "refresh":
21550                this.doLoad(this.cursor);
21551            break;
21552        }
21553    },
21554
21555    
21556    unbind : function(store){
21557        store = Ext.StoreMgr.lookup(store);
21558        store.un("beforeload", this.beforeLoad, this);
21559        store.un("load", this.onLoad, this);
21560        store.un("loadexception", this.onLoadError, this);
21561        this.store = undefined;
21562    },
21563
21564    
21565    bind : function(store){
21566        store = Ext.StoreMgr.lookup(store);
21567        store.on("beforeload", this.beforeLoad, this);
21568        store.on("load", this.onLoad, this);
21569        store.on("loadexception", this.onLoadError, this);
21570        this.store = store;
21571    },
21572
21573    // private
21574    onDestroy : function(){
21575        if(this.store){
21576            this.unbind(this.store);
21577        }
21578        Ext.PagingToolbar.superclass.onDestroy.call(this);
21579    }
21580});
21581Ext.reg('paging', Ext.PagingToolbar);
21582
21583Ext.Resizable = function(el, config){
21584    this.el = Ext.get(el);
21585    
21586    if(config && config.wrap){
21587        config.resizeChild = this.el;
21588        this.el = this.el.wrap(typeof config.wrap == "object" ? config.wrap : {cls:"xresizable-wrap"});
21589        this.el.id = this.el.dom.id = config.resizeChild.id + "-rzwrap";
21590        this.el.setStyle("overflow", "hidden");
21591        this.el.setPositioning(config.resizeChild.getPositioning());
21592        config.resizeChild.clearPositioning();
21593        if(!config.width || !config.height){
21594            var csize = config.resizeChild.getSize();
21595            this.el.setSize(csize.width, csize.height);
21596        }
21597        if(config.pinned && !config.adjustments){
21598            config.adjustments = "auto";
21599        }
21600    }
21601
21602    
21603    this.proxy = this.el.createProxy({tag: "div", cls: "x-resizable-proxy", id: this.el.id + "-rzproxy"}, Ext.getBody());
21604    this.proxy.unselectable();
21605    this.proxy.enableDisplayMode('block');
21606
21607    Ext.apply(this, config);
21608    
21609    if(this.pinned){
21610        this.disableTrackOver = true;
21611        this.el.addClass("x-resizable-pinned");
21612    }
21613    // if the element isn't positioned, make it relative
21614    var position = this.el.getStyle("position");
21615    if(position != "absolute" && position != "fixed"){
21616        this.el.setStyle("position", "relative");
21617    }
21618    if(!this.handles){ // no handles passed, must be legacy style
21619        this.handles = 's,e,se';
21620        if(this.multiDirectional){
21621            this.handles += ',n,w';
21622        }
21623    }
21624    if(this.handles == "all"){
21625        this.handles = "n s e w ne nw se sw";
21626    }
21627    var hs = this.handles.split(/\s*?[,;]\s*?| /);
21628    var ps = Ext.Resizable.positions;
21629    for(var i = 0, len = hs.length; i < len; i++){
21630        if(hs[i] && ps[hs[i]]){
21631            var pos = ps[hs[i]];
21632            this[pos] = new Ext.Resizable.Handle(this, pos, this.disableTrackOver, this.transparent);
21633        }
21634    }
21635    // legacy
21636    this.corner = this.southeast;
21637    
21638    if(this.handles.indexOf("n") != -1 || this.handles.indexOf("w") != -1){
21639        this.updateBox = true;
21640    }   
21641   
21642    this.activeHandle = null;
21643    
21644    if(this.resizeChild){
21645        if(typeof this.resizeChild == "boolean"){
21646            this.resizeChild = Ext.get(this.el.dom.firstChild, true);
21647        }else{
21648            this.resizeChild = Ext.get(this.resizeChild, true);
21649        }
21650    }
21651    
21652    if(this.adjustments == "auto"){
21653        var rc = this.resizeChild;
21654        var hw = this.west, he = this.east, hn = this.north, hs = this.south;
21655        if(rc && (hw || hn)){
21656            rc.position("relative");
21657            rc.setLeft(hw ? hw.el.getWidth() : 0);
21658            rc.setTop(hn ? hn.el.getHeight() : 0);
21659        }
21660        this.adjustments = [
21661            (he ? -he.el.getWidth() : 0) + (hw ? -hw.el.getWidth() : 0),
21662            (hn ? -hn.el.getHeight() : 0) + (hs ? -hs.el.getHeight() : 0) -1 
21663        ];
21664    }
21665    
21666    if(this.draggable){
21667        this.dd = this.dynamic ? 
21668            this.el.initDD(null) : this.el.initDDProxy(null, {dragElId: this.proxy.id});
21669        this.dd.setHandleElId(this.resizeChild ? this.resizeChild.id : this.el.id);
21670    }
21671    
21672    // public events
21673    this.addEvents(
21674        "beforeresize",
21675        "resize"
21676    );
21677    
21678    if(this.width !== null && this.height !== null){
21679        this.resizeTo(this.width, this.height);
21680    }else{
21681        this.updateChildSize();
21682    }
21683    if(Ext.isIE){
21684        this.el.dom.style.zoom = 1;
21685    }
21686    Ext.Resizable.superclass.constructor.call(this);
21687};
21688
21689Ext.extend(Ext.Resizable, Ext.util.Observable, {
21690        resizeChild : false,
21691        adjustments : [0, 0],
21692        minWidth : 5,
21693        minHeight : 5,
21694        maxWidth : 10000,
21695        maxHeight : 10000,
21696        enabled : true,
21697        animate : false,
21698        duration : .35,
21699        dynamic : false,
21700        handles : false,
21701        multiDirectional : false,
21702        disableTrackOver : false,
21703        easing : 'easeOutStrong',
21704        widthIncrement : 0,
21705        heightIncrement : 0,
21706        pinned : false,
21707        width : null,
21708        height : null,
21709        preserveRatio : false,
21710        transparent: false,
21711        minX: 0,
21712        minY: 0,
21713        draggable: false,
21714
21715        
21716        
21717
21718        
21719        
21720    
21721    
21722    resizeTo : function(width, height){
21723        this.el.setSize(width, height);
21724        this.updateChildSize();
21725        this.fireEvent("resize", this, width, height, null);
21726    },
21727
21728    // private
21729    startSizing : function(e, handle){
21730        this.fireEvent("beforeresize", this, e);
21731        if(this.enabled){ // 2nd enabled check in case disabled before beforeresize handler
21732
21733            if(!this.overlay){
21734                this.overlay = this.el.createProxy({tag: "div", cls: "x-resizable-overlay", html: "&#160;"}, Ext.getBody());
21735                this.overlay.unselectable();
21736                this.overlay.enableDisplayMode("block");
21737                this.overlay.on("mousemove", this.onMouseMove, this);
21738                this.overlay.on("mouseup", this.onMouseUp, this);
21739            }
21740            this.overlay.setStyle("cursor", handle.el.getStyle("cursor"));
21741
21742            this.resizing = true;
21743            this.startBox = this.el.getBox();
21744            this.startPoint = e.getXY();
21745            this.offsets = [(this.startBox.x + this.startBox.width) - this.startPoint[0],
21746                            (this.startBox.y + this.startBox.height) - this.startPoint[1]];
21747
21748            this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
21749            this.overlay.show();
21750
21751            if(this.constrainTo) {
21752                var ct = Ext.get(this.constrainTo);
21753                this.resizeRegion = ct.getRegion().adjust(
21754                    ct.getFrameWidth('t'),
21755                    ct.getFrameWidth('l'),
21756                    -ct.getFrameWidth('b'),
21757                    -ct.getFrameWidth('r')
21758                );
21759            }
21760
21761            this.proxy.setStyle('visibility', 'hidden'); // workaround display none
21762            this.proxy.show();
21763            this.proxy.setBox(this.startBox);
21764            if(!this.dynamic){
21765                this.proxy.setStyle('visibility', 'visible');
21766            }
21767        }
21768    },
21769
21770    // private
21771    onMouseDown : function(handle, e){
21772        if(this.enabled){
21773            e.stopEvent();
21774            this.activeHandle = handle;
21775            this.startSizing(e, handle);
21776        }          
21777    },
21778
21779    // private
21780    onMouseUp : function(e){
21781        var size = this.resizeElement();
21782        this.resizing = false;
21783        this.handleOut();
21784        this.overlay.hide();
21785        this.proxy.hide();
21786        this.fireEvent("resize", this, size.width, size.height, e);
21787    },
21788
21789    // private
21790    updateChildSize : function(){
21791        if(this.resizeChild){
21792            var el = this.el;
21793            var child = this.resizeChild;
21794            var adj = this.adjustments;
21795            if(el.dom.offsetWidth){
21796                var b = el.getSize(true);
21797                child.setSize(b.width+adj[0], b.height+adj[1]);
21798            }
21799            // Second call here for IE
21800            // The first call enables instant resizing and
21801            // the second call corrects scroll bars if they
21802            // exist
21803            if(Ext.isIE){
21804                setTimeout(function(){
21805                    if(el.dom.offsetWidth){
21806                        var b = el.getSize(true);
21807                        child.setSize(b.width+adj[0], b.height+adj[1]);
21808                    }
21809                }, 10);
21810            }
21811        }
21812    },
21813
21814    // private
21815    snap : function(value, inc, min){
21816        if(!inc || !value) return value;
21817        var newValue = value;
21818        var m = value % inc;
21819        if(m > 0){
21820            if(m > (inc/2)){
21821                newValue = value + (inc-m);
21822            }else{
21823                newValue = value - m;
21824            }
21825        }
21826        return Math.max(min, newValue);
21827    },
21828
21829    
21830    resizeElement : function(){
21831        var box = this.proxy.getBox();
21832        if(this.updateBox){
21833            this.el.setBox(box, false, this.animate, this.duration, null, this.easing);
21834        }else{
21835            this.el.setSize(box.width, box.height, this.animate, this.duration, null, this.easing);
21836        }
21837        this.updateChildSize();
21838        if(!this.dynamic){
21839            this.proxy.hide();
21840        }
21841        return box;
21842    },
21843
21844    // private
21845    constrain : function(v, diff, m, mx){
21846        if(v - diff < m){
21847            diff = v - m;    
21848        }else if(v - diff > mx){
21849            diff = mx - v; 
21850        }
21851        return diff;                
21852    },
21853
21854    // private
21855    onMouseMove : function(e){
21856        if(this.enabled){
21857            try{// try catch so if something goes wrong the user doesn't get hung
21858
21859            if(this.resizeRegion && !this.resizeRegion.contains(e.getPoint())) {
21860                return;
21861            }
21862
21863            //var curXY = this.startPoint;
21864            var curSize = this.curSize || this.startBox;
21865            var x = this.startBox.x, y = this.startBox.y;
21866            var ox = x, oy = y;
21867            var w = curSize.width, h = curSize.height;
21868            var ow = w, oh = h;
21869            var mw = this.minWidth, mh = this.minHeight;
21870            var mxw = this.maxWidth, mxh = this.maxHeight;
21871            var wi = this.widthIncrement;
21872            var hi = this.heightIncrement;
21873            
21874            var eventXY = e.getXY();
21875            var diffX = -(this.startPoint[0] - Math.max(this.minX, eventXY[0]));
21876            var diffY = -(this.startPoint[1] - Math.max(this.minY, eventXY[1]));
21877            
21878            var pos = this.activeHandle.position;
21879            
21880            switch(pos){
21881                case "east":
21882                    w += diffX; 
21883                    w = Math.min(Math.max(mw, w), mxw);
21884                    break;
21885                case "south":
21886                    h += diffY;
21887                    h = Math.min(Math.max(mh, h), mxh);
21888                    break;
21889                case "southeast":
21890                    w += diffX; 
21891                    h += diffY;
21892                    w = Math.min(Math.max(mw, w), mxw);
21893                    h = Math.min(Math.max(mh, h), mxh);
21894                    break;
21895                case "north":
21896                    diffY = this.constrain(h, diffY, mh, mxh);
21897                    y += diffY;
21898                    h -= diffY;
21899                    break;
21900                case "west":
21901                    diffX = this.constrain(w, diffX, mw, mxw);
21902                    x += diffX;
21903                    w -= diffX;
21904                    break;
21905                case "northeast":
21906                    w += diffX; 
21907                    w = Math.min(Math.max(mw, w), mxw);
21908                    diffY = this.constrain(h, diffY, mh, mxh);
21909                    y += diffY;
21910                    h -= diffY;
21911                    break;
21912                case "northwest":
21913                    diffX = this.constrain(w, diffX, mw, mxw);
21914                    diffY = this.constrain(h, diffY, mh, mxh);
21915                    y += diffY;
21916                    h -= diffY;
21917                    x += diffX;
21918                    w -= diffX;
21919                    break;
21920               case "southwest":
21921                    diffX = this.constrain(w, diffX, mw, mxw);
21922                    h += diffY;
21923                    h = Math.min(Math.max(mh, h), mxh);
21924                    x += diffX;
21925                    w -= diffX;
21926                    break;
21927            }
21928            
21929            var sw = this.snap(w, wi, mw);
21930            var sh = this.snap(h, hi, mh);
21931            if(sw != w || sh != h){
21932                switch(pos){
21933                    case "northeast":
21934                        y -= sh - h;
21935                    break;
21936                    case "north":
21937                        y -= sh - h;
21938                        break;
21939                    case "southwest":
21940                        x -= sw - w;
21941                    break;
21942                    case "west":
21943                        x -= sw - w;
21944                        break;
21945                    case "northwest":
21946                        x -= sw - w;
21947                        y -= sh - h;
21948                    break;
21949                }
21950                w = sw;
21951                h = sh;
21952            }
21953            
21954            if(this.preserveRatio){
21955                switch(pos){
21956                    case "southeast":
21957                    case "east":
21958                        h = oh * (w/ow);
21959                        h = Math.min(Math.max(mh, h), mxh);
21960                        w = ow * (h/oh);
21961                       break;
21962                    case "south":
21963                        w = ow * (h/oh);
21964                        w = Math.min(Math.max(mw, w), mxw);
21965                        h = oh * (w/ow);
21966                        break;
21967                    case "northeast":
21968                        w = ow * (h/oh);
21969                        w = Math.min(Math.max(mw, w), mxw);
21970                        h = oh * (w/ow);
21971                    break;
21972                    case "north":
21973                        var tw = w;
21974                        w = ow * (h/oh);
21975                        w = Math.min(Math.max(mw, w), mxw);
21976                        h = oh * (w/ow);
21977                        x += (tw - w) / 2;
21978                        break;
21979                    case "southwest":
21980                        h = oh * (w/ow);
21981                        h = Math.min(Math.max(mh, h), mxh);
21982                        var tw = w;
21983                        w = ow * (h/oh);
21984                        x += tw - w;
21985                        break;
21986                    case "west":
21987                        var th = h;
21988                        h = oh * (w/ow);
21989                        h = Math.min(Math.max(mh, h), mxh);
21990                        y += (th - h) / 2;
21991                        var tw = w;
21992                        w = ow * (h/oh);
21993                        x += tw - w;
21994                       break;
21995                    case "northwest":
21996                        var tw = w;
21997                        var th = h;
21998                        h = oh * (w/ow);
21999                        h = Math.min(Math.max(mh, h), mxh);
22000                        w = ow * (h/oh);
22001                        y += th - h;
22002                         x += tw - w;
22003                       break;
22004                        
22005                }
22006            }
22007            this.proxy.setBounds(x, y, w, h);
22008            if(this.dynamic){
22009                this.resizeElement();
22010            }
22011            }catch(e){}
22012        }
22013    },
22014
22015    // private
22016    handleOver : function(){
22017        if(this.enabled){
22018            this.el.addClass("x-resizable-over");
22019        }
22020    },
22021
22022    // private
22023    handleOut : function(){
22024        if(!this.resizing){
22025            this.el.removeClass("x-resizable-over");
22026        }
22027    },
22028    
22029    
22030    getEl : function(){
22031        return this.el;
22032    },
22033    
22034    
22035    getResizeChild : function(){
22036        return this.resizeChild;
22037    },
22038    
22039    
22040    destroy : function(removeEl){
22041        if(this.dd){
22042            this.dd.destroy();
22043        }
22044        if(this.overlay){
22045            Ext.destroy(this.overlay);
22046            this.overlay = null;
22047        }
22048        Ext.destroy(this.proxy);
22049        this.proxy = null;
22050        
22051        var ps = Ext.Resizable.positions;
22052        for(var k in ps){
22053            if(typeof ps[k] != "function" && this[ps[k]]){
22054                this[ps[k]].destroy();
22055            }
22056        }
22057        if(removeEl){
22058            this.el.update("");
22059            Ext.destroy(this.el);
22060            this.el = null;
22061        }
22062    },
22063
22064    syncHandleHeight : function(){
22065        var h = this.el.getHeight(true);
22066        if(this.west){
22067            this.west.el.setHeight(h);
22068        }
22069        if(this.east){
22070            this.east.el.setHeight(h);
22071        }
22072    }
22073});
22074
22075// private
22076// hash to map config positions to true positions
22077Ext.Resizable.positions = {
22078    n: "north", s: "south", e: "east", w: "west", se: "southeast", sw: "southwest", nw: "northwest", ne: "northeast"
22079};
22080
22081// private
22082Ext.Resizable.Handle = function(rz, pos, disableTrackOver, transparent){
22083    if(!this.tpl){
22084        // only initialize the template if resizable is used
22085        var tpl = Ext.DomHelper.createTemplate(
22086            {tag: "div", cls: "x-resizable-handle x-resizable-handle-{0}"}
22087        );
22088        tpl.compile();
22089        Ext.Resizable.Handle.prototype.tpl = tpl;
22090    }
22091    this.position = pos;
22092    this.rz = rz;
22093    this.el = this.tpl.append(rz.el.dom, [this.position], true);
22094    this.el.unselectable();
22095    if(transparent){
22096        this.el.setOpacity(0);
22097    }
22098    this.el.on("mousedown", this.onMouseDown, this);
22099    if(!disableTrackOver){
22100        this.el.on("mouseover", this.onMouseOver, this);
22101        this.el.on("mouseout", this.onMouseOut, this);
22102    }
22103};
22104
22105// private
22106Ext.Resizable.Handle.prototype = {
22107    // private
22108    afterResize : function(rz){
22109        // do nothing    
22110    },
22111    // private
22112    onMouseDown : function(e){
22113        this.rz.onMouseDown(this, e);
22114    },
22115    // private
22116    onMouseOver : function(e){
22117        this.rz.handleOver(this, e);
22118    },
22119    // private
22120    onMouseOut : function(e){
22121        this.rz.handleOut(this, e);
22122    },
22123    // private
22124    destroy : function(){
22125        Ext.destroy(this.el);
22126        this.el = null;
22127    }
22128};
22129
22130
22131
22132
22133
22134Ext.Editor = function(field, config){
22135    this.field = field;
22136    Ext.Editor.superclass.constructor.call(this, config);
22137};
22138
22139Ext.extend(Ext.Editor, Ext.Component, {
22140    
22141    
22142    
22143    
22144    
22145    value : "",
22146    
22147    alignment: "c-c?",
22148    
22149    shadow : "frame",
22150    
22151    constrain : false,
22152    
22153    swallowKeys : true,
22154    
22155    completeOnEnter : false,
22156    
22157    cancelOnEsc : false,
22158    
22159    updateEl : false,
22160
22161    initComponent : function(){
22162        Ext.Editor.superclass.initComponent.call(this);
22163        this.addEvents(
22164            
22165            "beforestartedit",
22166            
22167            "startedit",
22168            
22169            "beforecomplete",
22170            
22171            "complete",
22172            
22173            "canceledit",
22174            
22175            "specialkey"
22176        );
22177    },
22178
22179    // private
22180    onRender : function(ct, position){
22181        this.el = new Ext.Layer({
22182            shadow: this.shadow,
22183            cls: "x-editor",
22184            parentEl : ct,
22185            shim : this.shim,
22186            shadowOffset:4,
22187            id: this.id,
22188            constrain: this.constrain
22189        });
22190        this.el.setStyle("overflow", Ext.isGecko ? "auto" : "hidden");
22191        if(this.field.msgTarget != 'title'){
22192            this.field.msgTarget = 'qtip';
22193        }
22194        this.field.inEditor = true;
22195        this.field.render(this.el);
22196        if(Ext.isGecko){
22197            this.field.el.dom.setAttribute('autocomplete', 'off');
22198        }
22199        this.field.on("specialkey", this.onSpecialKey, this);
22200        if(this.swallowKeys){
22201            this.field.el.swallowEvent(['keydown','keypress']);
22202        }
22203        this.field.show();
22204        this.field.on("blur", this.onBlur, this);
22205        if(this.field.grow){
22206            this.field.on("autosize", this.el.sync,  this.el, {delay:1});
22207        }
22208    },
22209
22210    // private
22211    onSpecialKey : function(field, e){
22212        var key = e.getKey();
22213        if(this.completeOnEnter && key == e.ENTER){
22214            e.stopEvent();
22215            this.completeEdit();
22216        }else if(this.cancelOnEsc && key == e.ESC){
22217            this.cancelEdit();
22218        }else{
22219            this.fireEvent('specialkey', field, e);
22220        }
22221        if(this.field.triggerBlur && (key == e.ENTER || key == e.ESC || key == e.TAB)){
22222            this.field.triggerBlur();
22223        }
22224    },
22225
22226    
22227    startEdit : function(el, value){
22228        if(this.editing){
22229            this.completeEdit();
22230        }
22231        this.boundEl = Ext.get(el);
22232        var v = value !== undefined ? value : this.boundEl.dom.innerHTML;
22233        if(!this.rendered){
22234            this.render(this.parentEl || document.body);
22235        }
22236        if(this.fireEvent("beforestartedit", this, this.boundEl, v) === false){
22237            return;
22238        }
22239        this.startValue = v;
22240        this.field.setValue(v);
22241        this.doAutoSize();
22242        this.el.alignTo(this.boundEl, this.alignment);
22243        this.editing = true;
22244        this.show();
22245    },
22246
22247    // private
22248    doAutoSize : function(){
22249        if(this.autoSize){
22250            var sz = this.boundEl.getSize();
22251            switch(this.autoSize){
22252                case "width":
22253                    this.setSize(sz.width,  "");
22254                break;
22255                case "height":
22256                    this.setSize("",  sz.height);
22257                break;
22258                default:
22259                    this.setSize(sz.width,  sz.height);
22260            }
22261        }
22262    },
22263
22264    
22265    setSize : function(w, h){
22266        delete this.field.lastSize;
22267        this.field.setSize(w, h);
22268        if(this.el){
22269	        if(Ext.isGecko2 || Ext.isOpera){
22270	            // prevent layer scrollbars
22271	            this.el.setSize(w, h);
22272	        }
22273            this.el.sync();
22274        }
22275    },
22276
22277    
22278    realign : function(){
22279        this.el.alignTo(this.boundEl, this.alignment);
22280    },
22281
22282    
22283    completeEdit : function(remainVisible){
22284        if(!this.editing){
22285            return;
22286        }
22287        var v = this.getValue();
22288        if(this.revertInvalid !== false && !this.field.isValid()){
22289            v = this.startValue;
22290            this.cancelEdit(true);
22291        }
22292        if(String(v) === String(this.startValue) && this.ignoreNoChange){
22293            this.editing = false;
22294            this.hide();
22295            return;
22296        }
22297        if(this.fireEvent("beforecomplete", this, v, this.startValue) !== false){
22298            this.editing = false;
22299            if(this.updateEl && this.boundEl){
22300                this.boundEl.update(v);
22301            }
22302            if(remainVisible !== true){
22303                this.hide();
22304            }
22305            this.fireEvent("complete", this, v, this.startValue);
22306        }
22307    },
22308
22309    // private
22310    onShow : function(){
22311        this.el.show();
22312        if(this.hideEl !== false){
22313            this.boundEl.hide();
22314        }
22315        this.field.show();
22316        if(Ext.isIE && !this.fixIEFocus){ // IE has problems with focusing the first time
22317            this.fixIEFocus = true;
22318            this.deferredFocus.defer(50, this);
22319        }else{
22320            this.field.focus();
22321        }
22322        this.fireEvent("startedit", this.boundEl, this.startValue);
22323    },
22324
22325    deferredFocus : function(){
22326        if(this.editing){
22327            this.field.focus();
22328        }
22329    },
22330
22331    
22332    cancelEdit : function(remainVisible){
22333        if(this.editing){
22334            var v = this.getValue();
22335            this.setValue(this.startValue);
22336            if(remainVisible !== true){
22337                this.hide();
22338            }
22339            this.fireEvent("canceledit", this, v, this.startValue);
22340        }
22341    },
22342
22343    // private
22344    onBlur : function(){
22345        if(this.allowBlur !== true && this.editing){
22346            this.completeEdit();
22347        }
22348    },
22349
22350    // private
22351    onHide : function(){
22352        if(this.editing){
22353            this.completeEdit();
22354            return;
22355        }
22356        this.field.blur();
22357        if(this.field.collapse){
22358            this.field.collapse();
22359        }
22360        this.el.hide();
22361        if(this.hideEl !== false){
22362            this.boundEl.show();
22363        }
22364    },
22365
22366    
22367    setValue : function(v){
22368        this.field.setValue(v);
22369    },
22370
22371    
22372    getValue : function(){
22373        return this.field.getValue();
22374    },
22375
22376    beforeDestroy : function(){
22377        Ext.destroy(this.field);
22378        this.field = null;
22379    }
22380});
22381Ext.reg('editor', Ext.Editor);
22382
22383Ext.MessageBox = function(){
22384    var dlg, opt, mask, waitTimer;
22385    var bodyEl, msgEl, textboxEl, textareaEl, progressBar, pp, iconEl, spacerEl;
22386    var buttons, activeTextEl, bwidth, iconCls = '';
22387
22388    // private
22389    var handleButton = function(button){
22390        if(dlg.isVisible()){
22391            dlg.hide();
22392            Ext.callback(opt.fn, opt.scope||window, [button, activeTextEl.dom.value, opt], 1);
22393        }
22394    };
22395
22396    // private
22397    var handleHide = function(){
22398        if(opt && opt.cls){
22399            dlg.el.removeClass(opt.cls);
22400        }
22401        progressBar.reset();
22402    };
22403
22404    // private
22405    var handleEsc = function(d, k, e){
22406        if(opt && opt.closable !== false){
22407            dlg.hide();
22408        }
22409        if(e){
22410            e.stopEvent();
22411        }
22412    };
22413
22414    // private
22415    var updateButtons = function(b){
22416        var width = 0;
22417        if(!b){
22418            buttons["ok"].hide();
22419            buttons["cancel"].hide();
22420            buttons["yes"].hide();
22421            buttons["no"].hide();
22422            return width;
22423        }
22424        dlg.footer.dom.style.display = '';
22425        for(var k in buttons){
22426            if(typeof buttons[k] != "function"){
22427                if(b[k]){
22428                    buttons[k].show();
22429                    buttons[k].setText(typeof b[k] == "string" ? b[k] : Ext.MessageBox.buttonText[k]);
22430                    width += buttons[k].el.getWidth()+15;
22431                }else{
22432                    buttons[k].hide();
22433                }
22434            }
22435        }
22436        return width;
22437    };
22438
22439    return {
22440        
22441        getDialog : function(titleText){
22442           if(!dlg){
22443                dlg = new Ext.Window({
22444                    autoCreate : true,
22445                    title:titleText,
22446                    resizable:false,
22447                    constrain:true,
22448                    constrainHeader:true,
22449                    minimizable : false,
22450                    maximizable : false,
22451                    stateful: false,
22452                    modal: true,
22453                    shim:true,
22454                    buttonAlign:"center",
22455                    width:400,
22456                    height:100,
22457                    minHeight: 80,
22458                    plain:true,
22459                    footer:true,
22460                    closable:true,
22461                    close : function(){
22462                        if(opt && opt.buttons && opt.buttons.no && !opt.buttons.cancel){
22463                            handleButton("no");
22464                        }else{
22465                            handleButton("cancel");
22466                        }
22467                    }
22468                });
22469                buttons = {};
22470                var bt = this.buttonText;
22471                //TODO: refactor this block into a buttons config to pass into the Window constructor
22472                buttons["ok"] = dlg.addButton(bt["ok"], handleButton.createCallback("ok"));
22473                buttons["yes"] = dlg.addButton(bt["yes"], handleButton.createCallback("yes"));
22474                buttons["no"] = dlg.addButton(bt["no"], handleButton.createCallback("no"));
22475                buttons["cancel"] = dlg.addButton(bt["cancel"], handleButton.createCallback("cancel"));
22476                buttons["ok"].hideMode = buttons["yes"].hideMode = buttons["no"].hideMode = buttons["cancel"].hideMode = 'offsets';
22477                dlg.render(document.body);
22478                dlg.getEl().addClass('x-window-dlg');
22479                mask = dlg.mask;
22480                bodyEl = dlg.body.createChild({
22481                    html:'<div class="ext-mb-icon"></div><div class="ext-mb-content"><span class="ext-mb-text"></span><br /><div class="ext-mb-fix-cursor"><input type="text" class="ext-mb-input" /><textarea class="ext-mb-textarea"></textarea></div></div>'
22482                });
22483                iconEl = Ext.get(bodyEl.dom.firstChild);
22484                var contentEl = bodyEl.dom.childNodes[1];
22485                msgEl = Ext.get(contentEl.firstChild);
22486                textboxEl = Ext.get(contentEl.childNodes[2].firstChild);
22487                textboxEl.enableDisplayMode();
22488                textboxEl.addKeyListener([10,13], function(){
22489                    if(dlg.isVisible() && opt && opt.buttons){
22490                        if(opt.buttons.ok){
22491                            handleButton("ok");
22492                        }else if(opt.buttons.yes){
22493                            handleButton("yes");
22494                        }
22495                    }
22496                });
22497                textareaEl = Ext.get(contentEl.childNodes[2].childNodes[1]);
22498                textareaEl.enableDisplayMode();
22499                progressBar = new Ext.ProgressBar({
22500                    renderTo:bodyEl
22501                });
22502               bodyEl.createChild({cls:'x-clear'});
22503            }
22504            return dlg;
22505        },
22506
22507        
22508        updateText : function(text){
22509            if(!dlg.isVisible() && !opt.width){
22510                dlg.setSize(this.maxWidth, 100); // resize first so content is never clipped from previous shows
22511            }
22512            msgEl.update(text || '&#160;');
22513
22514            var iw = iconCls != '' ? (iconEl.getWidth() + iconEl.getMargins('lr')) : 0;
22515            var mw = msgEl.getWidth() + msgEl.getMargins('lr');
22516            var fw = dlg.getFrameWidth('lr');
22517            var bw = dlg.body.getFrameWidth('lr');
22518            if (Ext.isIE && iw > 0){
22519                //3 pixels get subtracted in the icon CSS for an IE margin issue,
22520                //so we have to add it back here for the overall width to be consistent
22521                iw += 3;
22522            }
22523            var w = Math.max(Math.min(opt.width || iw+mw+fw+bw, this.maxWidth),
22524                        Math.max(opt.minWidth || this.minWidth, bwidth || 0));
22525
22526            if(opt.prompt === true){
22527                activeTextEl.setWidth(w-iw-fw-bw);
22528            }
22529            if(opt.progress === true || opt.wait === true){
22530                progressBar.setSize(w-iw-fw-bw);
22531            }
22532            if(Ext.isIE && w == bwidth){
22533                w += 4; //Add offset when the content width is smaller than the buttons.    
22534            }
22535            dlg.setSize(w, 'auto').center();
22536            return this;
22537        },
22538
22539        
22540        updateProgress : function(value, progressText, msg){
22541            progressBar.updateProgress(value, progressText);
22542            if(msg){
22543                this.updateText(msg);
22544            }
22545            return this;
22546        },
22547
22548        
22549        isVisible : function(){
22550            return dlg && dlg.isVisible();
22551        },
22552
22553        
22554        hide : function(){
22555            var proxy = dlg.activeGhost;
22556            if(this.isVisible() || proxy) {
22557                dlg.hide();
22558                handleHide();
22559                if (proxy) {
22560                    proxy.hide();
22561                } 
22562            }
22563            return this;
22564        },
22565
22566        
22567        show : function(options){
22568            if(this.isVisible()){
22569                this.hide();
22570            }
22571            opt = options;
22572            var d = this.getDialog(opt.title || "&#160;");
22573
22574            d.setTitle(opt.title || "&#160;");
22575            var allowClose = (opt.closable !== false && opt.progress !== true && opt.wait !== true);
22576            d.tools.close.setDisplayed(allowClose);
22577            activeTextEl = textboxEl;
22578            opt.prompt = opt.prompt || (opt.multiline ? true : false);
22579            if(opt.prompt){
22580                if(opt.multiline){
22581                    textboxEl.hide();
22582                    textareaEl.show();
22583                    textareaEl.setHeight(typeof opt.multiline == "number" ?
22584                        opt.multiline : this.defaultTextHeight);
22585                    activeTextEl = textareaEl;
22586                }else{
22587                    textboxEl.show();
22588                    textareaEl.hide();
22589                }
22590            }else{
22591                textboxEl.hide();
22592                textareaEl.hide();
22593            }
22594            activeTextEl.dom.value = opt.value || "";
22595            if(opt.prompt){
22596                d.focusEl = activeTextEl;
22597            }else{
22598                var bs = opt.buttons;
22599                var db = null;
22600                if(bs && bs.ok){
22601                    db = buttons["ok"];
22602                }else if(bs && bs.yes){
22603                    db = buttons["yes"];
22604                }
22605                if (db){
22606                    d.focusEl = db;
22607                }
22608            }
22609            if(opt.iconCls){
22610              d.setIconClass(opt.iconCls);
22611            }
22612            this.setIcon(opt.icon);
22613            bwidth = updateButtons(opt.buttons);
22614            progressBar.setVisible(opt.progress === true || opt.wait === true);
22615            this.updateProgress(0, opt.progressText);
22616            this.updateText(opt.msg);
22617            if(opt.cls){
22618                d.el.addClass(opt.cls);
22619            }
22620            d.proxyDrag = opt.proxyDrag === true;
22621            d.modal = opt.modal !== false;
22622            d.mask = opt.modal !== false ? mask : false;
22623            if(!d.isVisible()){
22624                // force it to the end of the z-index stack so it gets a cursor in FF
22625                document.body.appendChild(dlg.el.dom);
22626                d.setAnimateTarget(opt.animEl);
22627                d.show(opt.animEl);
22628            }
22629
22630            //workaround for window internally enabling keymap in afterShow
22631            d.on('show', function(){
22632                if(allowClose === true){
22633                    d.keyMap.enable();
22634                }else{
22635                    d.keyMap.disable();
22636                }
22637            }, this, {single:true});
22638
22639            if(opt.wait === true){
22640                progressBar.wait(opt.waitConfig);
22641            }
22642            return this;
22643        },
22644
22645        
22646        setIcon : function(icon){
22647            if(icon && icon != ''){
22648                iconEl.removeClass('x-hidden');
22649                iconEl.replaceClass(iconCls, icon);
22650                iconCls = icon;
22651            }else{
22652                iconEl.replaceClass(iconCls, 'x-hidden');
22653                iconCls = '';
22654            }
22655            return this;
22656        },
22657
22658        
22659        progress : function(title, msg, progressText){
22660            this.show({
22661                title : title,
22662                msg : msg,
22663                buttons: false,
22664                progress:true,
22665                closable:false,
22666                minWidth: this.minProgressWidth,
22667                progressText: progressText
22668            });
22669            return this;
22670        },
22671
22672        
22673        wait : function(msg, title, config){
22674            this.show({
22675                title : title,
22676                msg : msg,
22677                buttons: false,
22678                closable:false,
22679                wait:true,
22680                modal:true,
22681                minWidth: this.minProgressWidth,
22682                waitConfig: config
22683            });
22684            return this;
22685        },
22686
22687        
22688        alert : function(title, msg, fn, scope){
22689            this.show({
22690                title : title,
22691                msg : msg,
22692                buttons: this.OK,
22693                fn: fn,
22694                scope : scope
22695            });
22696            return this;
22697        },
22698
22699        
22700        confirm : function(title, msg, fn, scope){
22701            this.show({
22702                title : title,
22703                msg : msg,
22704                buttons: this.YESNO,
22705                fn: fn,
22706                scope : scope,
22707                icon: this.QUESTION
22708            });
22709            return this;
22710        },
22711
22712        
22713        prompt : function(title, msg, fn, scope, multiline, value){
22714            this.show({
22715                title : title,
22716                msg : msg,
22717                buttons: this.OKCANCEL,
22718                fn: fn,
22719                minWidth:250,
22720                scope : scope,
22721                prompt:true,
22722                multiline: multiline,
22723                value: value
22724            });
22725            return this;
22726        },
22727
22728        
22729        OK : {ok:true},
22730        
22731        CANCEL : {cancel:true},
22732        
22733        OKCANCEL : {ok:true, cancel:true},
22734        
22735        YESNO : {yes:true, no:true},
22736        
22737        YESNOCANCEL : {yes:true, no:true, cancel:true},
22738        
22739        INFO : 'ext-mb-info',
22740        
22741        WARNING : 'ext-mb-warning',
22742        
22743        QUESTION : 'ext-mb-question',
22744        
22745        ERROR : 'ext-mb-error',
22746
22747        
22748        defaultTextHeight : 75,
22749        
22750        maxWidth : 600,
22751        
22752        minWidth : 100,
22753        
22754        minProgressWidth : 250,
22755        
22756        buttonText : {
22757            ok : "OK",
22758            cancel : "Cancelar",
22759            yes : "Sim",
22760            no : "Não"
22761        }
22762    };
22763}();
22764
22765
22766Ext.Msg = Ext.MessageBox;
22767
22768Ext.Tip = Ext.extend(Ext.Panel, {
22769    
22770    
22771    
22772    minWidth : 40,
22773    
22774    maxWidth : 300,
22775    
22776    shadow : "sides",
22777    
22778    defaultAlign : "tl-bl?",
22779    autoRender: true,
22780    quickShowInterval : 250,
22781
22782    // private panel overrides
22783    frame:true,
22784    hidden:true,
22785    baseCls: 'x-tip',
22786    floating:{shadow:true,shim:true,useDisplay:true,constrain:false},
22787    autoHeight:true,
22788
22789    // private
22790    initComponent : function(){
22791        Ext.Tip.superclass.initComponent.call(this);
22792        if(this.closable && !this.title){
22793            this.elements += ',header';
22794        }
22795    },
22796
22797    // private
22798    afterRender : function(){
22799        Ext.Tip.superclass.afterRender.call(this);
22800        if(this.closable){
22801            this.addTool({
22802                id: 'close',
22803                handler: this.hide,
22804                scope: this
22805            });
22806        }
22807    },
22808
22809    
22810    showAt : function(xy){
22811        Ext.Tip.superclass.show.call(this);
22812        if(this.measureWidth !== false && (!this.initialConfig || typeof this.initialConfig.width != 'number')){
22813            this.doAutoWidth();
22814        }
22815        if(this.constrainPosition){
22816            xy = this.el.adjustForConstraints(xy);
22817        }
22818        this.setPagePosition(xy[0], xy[1]);
22819    },
22820
22821    // protected
22822    doAutoWidth : function(){
22823        var bw = this.body.getTextWidth();
22824        if(this.title){
22825            bw = Math.max(bw, this.header.child('span').getTextWidth(this.title));
22826        }
22827        bw += this.getFrameWidth() + (this.closable ? 20 : 0) + this.body.getPadding("lr");
22828        this.setWidth(bw.constrain(this.minWidth, this.maxWidth));
22829        
22830        // IE7 repaint bug on initial show
22831        if(Ext.isIE7 && !this.repainted){
22832            this.el.repaint();
22833            this.repainted = true;
22834        }
22835    },
22836
22837    
22838    showBy : function(el, pos){
22839        if(!this.rendered){
22840            this.render(Ext.getBody());
22841        }
22842        this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign));
22843    },
22844
22845    initDraggable : function(){
22846        this.dd = new Ext.Tip.DD(this, typeof this.draggable == 'boolean' ? null : this.draggable);
22847        this.header.addClass('x-tip-draggable');
22848    }
22849});
22850
22851// private - custom Tip DD implementation
22852Ext.Tip.DD = function(tip, config){
22853    Ext.apply(this, config);
22854    this.tip = tip;
22855    Ext.Tip.DD.superclass.constructor.call(this, tip.el.id, 'WindowDD-'+tip.id);
22856    this.setHandleElId(tip.header.id);
22857    this.scroll = false;
22858};
22859
22860Ext.extend(Ext.Tip.DD, Ext.dd.DD, {
22861    moveOnly:true,
22862    scroll:false,
22863    headerOffsets:[100, 25],
22864    startDrag : function(){
22865        this.tip.el.disableShadow();
22866    },
22867    endDrag : function(e){
22868        this.tip.el.enableShadow(true);
22869    }
22870});
22871
22872Ext.ToolTip = Ext.extend(Ext.Tip, {
22873    
22874    
22875    
22876    showDelay: 500,
22877    
22878    hideDelay: 200,
22879    
22880    dismissDelay: 5000,
22881    
22882    mouseOffset: [15,18],
22883    
22884    trackMouse : false,
22885    constrainPosition: true,
22886
22887    // private
22888    initComponent: function(){
22889        Ext.ToolTip.superclass.initComponent.call(this);
22890        this.lastActive = new Date();
22891        this.initTarget();
22892    },
22893
22894    // private
22895    initTarget : function(){
22896        if(this.target){
22897            this.target = Ext.get(this.target);
22898            this.target.on('mouseover', this.onTargetOver, this);
22899            this.target.on('mouseout', this.onTargetOut, this);
22900            this.target.on('mousemove', this.onMouseMove, this);
22901        }
22902    },
22903
22904    // private
22905    onMouseMove : function(e){
22906        this.targetXY = e.getXY();
22907        if(!this.hidden && this.trackMouse){
22908            this.setPagePosition(this.getTargetXY());
22909        }
22910    },
22911
22912    // private
22913    getTargetXY : function(){
22914        return [this.targetXY[0]+this.mouseOffset[0], this.targetXY[1]+this.mouseOffset[1]];
22915    },
22916
22917    // private
22918    onTargetOver : function(e){
22919        if(this.disabled || e.within(this.target.dom, true)){
22920            return;
22921        }
22922        this.clearTimer('hide');
22923        this.targetXY = e.getXY();
22924        this.delayShow();
22925    },
22926
22927    // private
22928    delayShow : function(){
22929        if(this.hidden && !this.showTimer){
22930            if(this.lastActive.getElapsed() < this.quickShowInterval){
22931                this.show();
22932            }else{
22933                this.showTimer = this.show.defer(this.showDelay, this);
22934            }
22935        }else if(!this.hidden && this.autoHide !== false){
22936            this.show();
22937        }
22938    },
22939
22940    // private
22941    onTargetOut : function(e){
22942        if(this.disabled || e.within(this.target.dom, true)){
22943            return;
22944        }
22945        this.clearTimer('show');
22946        if(this.autoHide !== false){
22947            this.delayHide();
22948        }
22949    },
22950
22951    // private
22952    delayHide : function(){
22953        if(!this.hidden && !this.hideTimer){
22954            this.hideTimer = this.hide.defer(this.hideDelay, this);
22955        }
22956    },
22957
22958    
22959    hide: function(){
22960        this.clearTimer('dismiss');
22961        this.lastActive = new Date();
22962        Ext.ToolTip.superclass.hide.call(this);
22963    },
22964
22965    
22966    show : function(){
22967        this.showAt(this.getTargetXY());
22968    },
22969
22970    // inherit docs
22971    showAt : function(xy){
22972        this.lastActive = new Date();
22973        this.clearTimers();
22974        Ext.ToolTip.superclass.showAt.call(this, xy);
22975        if(this.dismissDelay && this.autoHide !== false){
22976            this.dismissTimer = this.hide.defer(this.dismissDelay, this);
22977        }
22978    },
22979
22980    // private
22981    clearTimer : function(name){
22982        name = name + 'Timer';
22983        clearTimeout(this[name]);
22984        delete this[name];
22985    },
22986
22987    // private
22988    clearTimers : function(){
22989        this.clearTimer('show');
22990        this.clearTimer('dismiss');
22991        this.clearTimer('hide');
22992    },
22993
22994    // private
22995    onShow : function(){
22996        Ext.ToolTip.superclass.onShow.call(this);
22997        Ext.getDoc().on('mousedown', this.onDocMouseDown, this);
22998    },
22999
23000    // private
23001    onHide : function(){
23002        Ext.ToolTip.superclass.onHide.call(this);
23003        Ext.getDoc().un('mousedown', this.onDocMouseDown, this);
23004    },
23005
23006    // private
23007    onDocMouseDown : function(e){
23008        if(this.autoHide !== false && !e.within(this.el.dom)){
23009            this.disable();
23010            this.enable.defer(100, this);
23011        }
23012    },
23013
23014    // private
23015    onDisable : function(){
23016        this.clearTimers();
23017        this.hide();
23018    },
23019
23020    // private
23021    adjustPosition : function(x, y){
23022        // keep the position from being under the mouse
23023        var ay = this.targetXY[1], h = this.getSize().height;
23024        if(this.constrainPosition && y <= ay && (y+h) >= ay){
23025            y = ay-h-5;
23026        }
23027        return {x : x, y: y};
23028    },
23029
23030    // private
23031    onDestroy : function(){
23032        Ext.ToolTip.superclass.onDestroy.call(this);
23033        if(this.target){
23034            this.target.un('mouseover', this.onTargetOver, this);
23035            this.target.un('mouseout', this.onTargetOut, this);
23036            this.target.un('mousemove', this.onMouseMove, this);
23037        }
23038    }
23039});
23040
23041Ext.QuickTip = Ext.extend(Ext.ToolTip, {
23042    
23043    
23044    interceptTitles : false,
23045
23046    // private
23047    tagConfig : {
23048        namespace : "ext",
23049        attribute : "qtip",
23050        width : "qwidth",
23051        target : "target",
23052        title : "qtitle",
23053        hide : "hide",
23054        cls : "qclass",
23055        align : "qalign"
23056    },
23057
23058    // private
23059    initComponent : function(){
23060        this.target = this.target || Ext.getDoc();
23061        this.targets = this.targets || {};
23062        Ext.QuickTip.superclass.initComponent.call(this);
23063    },
23064
23065    
23066    register : function(config){
23067        var cs = Ext.isArray(config) ? config : arguments;
23068        for(var i = 0, len = cs.length; i < len; i++){
23069            var c = cs[i];
23070            var target = c.target;
23071            if(target){
23072                if(Ext.isArray(target)){
23073                    for(var j = 0, jlen = target.length; j < jlen; j++){
23074                        this.targets[Ext.id(target[j])] = c;
23075                    }
23076                } else{
23077                    this.targets[Ext.id(target)] = c;
23078                }
23079            }
23080        }
23081    },
23082
23083    
23084    unregister : function(el){
23085        delete this.targets[Ext.id(el)];
23086    },
23087
23088    // private
23089    onTargetOver : function(e){
23090        if(this.disabled){
23091            return;
23092        }
23093        this.targetXY = e.getXY();
23094        var t = e.getTarget();
23095        if(!t || t.nodeType !== 1 || t == document || t == document.body){
23096            return;
23097        }
23098        if(this.activeTarget && t == this.activeTarget.el){
23099            this.clearTimer('hide');
23100            this.show();
23101            return;
23102        }
23103        if(t && this.targets[t.id]){
23104            this.activeTarget = this.targets[t.id];
23105            this.activeTarget.el = t;
23106            this.delayShow();
23107            return;
23108        }
23109        var ttp, et = Ext.fly(t), cfg = this.tagConfig;
23110        var ns = cfg.namespace;
23111        if(this.interceptTitles && t.title){
23112            ttp = t.title;
23113            t.qtip = ttp;
23114            t.removeAttribute("title");
23115            e.preventDefault();
23116        } else{
23117            ttp = t.qtip || et.getAttributeNS(ns, cfg.attribute);
23118        }
23119        if(ttp){
23120            var autoHide = et.getAttributeNS(ns, cfg.hide);
23121            this.activeTarget = {
23122                el: t,
23123                text: ttp,
23124                width: et.getAttributeNS(ns, cfg.width),
23125                autoHide: autoHide != "user" && autoHide !== 'false',
23126                title: et.getAttributeNS(ns, cfg.title),
23127                cls: et.getAttributeNS(ns, cfg.cls),
23128                align: et.getAttributeNS(ns, cfg.align)
23129            };
23130            this.delayShow();
23131        }
23132    },
23133
23134    // private
23135    onTargetOut : function(e){
23136        this.clearTimer('show');
23137        if(this.autoHide !== false){
23138            this.delayHide();
23139        }
23140    },
23141
23142    // inherit docs
23143    showAt : function(xy){
23144        var t = this.activeTarget;
23145        if(t){
23146            if(!this.rendered){
23147                this.render(Ext.getBody());
23148                this.activeTarget = t;
23149            }
23150            if(t.width){
23151                this.setWidth(t.width);
23152                this.body.setWidth(this.adjustBodyWidth(t.width - this.getFrameWidth()));
23153                this.measureWidth = false;
23154            } else{
23155                this.measureWidth = true;
23156            }
23157            this.setTitle(t.title || '');
23158            this.body.update(t.text);
23159            this.autoHide = t.autoHide;
23160            this.dismissDelay = t.dismissDelay || this.dismissDelay;
23161            if(this.lastCls){
23162                this.el.removeClass(this.lastCls);
23163                delete this.lastCls;
23164            }
23165            if(t.cls){
23166                this.el.addClass(t.cls);
23167                this.lastCls = t.cls;
23168            }
23169            if(t.align){ // TODO: this doesn't seem to work consistently
23170                xy = this.el.getAlignToXY(t.el, t.align);
23171                this.constrainPosition = false;
23172            } else{
23173                this.constrainPosition = true;
23174            }
23175        }
23176        Ext.QuickTip.superclass.showAt.call(this, xy);
23177    },
23178
23179    // inherit docs
23180    hide: function(){
23181        delete this.activeTarget;
23182        Ext.QuickTip.superclass.hide.call(this);
23183    }
23184});
23185
23186Ext.QuickTips = function(){
23187    var tip, locks = [];
23188    return {
23189        
23190        init : function(autoRender){
23191		    if(!tip){
23192		        if(!Ext.isReady){
23193		            Ext.onReady(function(){
23194		                Ext.QuickTips.init(autoRender);
23195		            });
23196		            return;
23197		        }
23198		        tip = new Ext.QuickTip({elements:'header,body'});
23199		        if(autoRender !== false){
23200		            tip.render(Ext.getBody());
23201		        }
23202		    }
23203        },
23204
23205        
23206        enable : function(){
23207            if(tip){
23208                locks.pop();
23209                if(locks.length < 1){
23210                    tip.enable();
23211                }
23212            }
23213        },
23214
23215        
23216        disable : function(){
23217            if(tip){
23218                tip.disable();
23219            }
23220            locks.push(1);
23221        },
23222
23223        
23224        isEnabled : function(){
23225            return tip !== undefined && !tip.disabled;
23226        },
23227
23228        
23229        getQuickTip : function(){
23230            return tip;
23231        },
23232
23233        
23234        register : function(){
23235            tip.register.apply(tip, arguments);
23236        },
23237
23238        
23239        unregister : function(){
23240            tip.unregister.apply(tip, arguments);
23241        },
23242
23243        
23244        tips :function(){
23245            tip.register.apply(tip, arguments);
23246        }
23247    }
23248}();
23249
23250Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
23251    rootVisible : true,
23252    animate: Ext.enableFx,
23253    lines : true,
23254    enableDD : false,
23255    hlDrop : Ext.enableFx,
23256    pathSeparator: "/",
23257
23258    initComponent : function(){
23259        Ext.tree.TreePanel.superclass.initComponent.call(this);
23260
23261        if(!this.eventModel){
23262            this.eventModel = new Ext.tree.TreeEventModel(this);
23263        }
23264        
23265        // initialize the loader
23266        var l = this.loader;
23267        if(!l){
23268            l = new Ext.tree.TreeLoader({
23269                dataUrl: this.dataUrl
23270            });
23271        }else if(typeof l == 'object' && !l.load){
23272            l = new Ext.tree.TreeLoader(l);
23273        }
23274        this.loader = l;
23275        
23276        this.nodeHash = {};
23277
23278        
23279        if(this.root){
23280           this.setRootNode(this.root);
23281        }
23282
23283        this.addEvents(
23284
23285            
23286           "append",
23287           
23288           "remove",
23289           
23290           "movenode",
23291           
23292           "insert",
23293           
23294           "beforeappend",
23295           
23296           "beforeremove",
23297           
23298           "beforemovenode",
23299           
23300            "beforeinsert",
23301
23302            
23303            "beforeload",
23304            
23305            "load",
23306            
23307            "textchange",
23308            
23309            "beforeexpandnode",
23310            
23311            "beforecollapsenode",
23312            
23313            "expandnode",
23314            
23315            "disabledchange",
23316            
23317            "collapsenode",
23318            
23319            "beforeclick",
23320            
23321            "click",
23322            
23323            "checkchange",
23324            
23325            "dblclick",
23326            
23327            "contextmenu",
23328            
23329            "beforechildrenrendered",
23330           
23331            "startdrag",
23332            
23333            "enddrag",
23334            
23335            "dragdrop",
23336            
23337            "beforenodedrop",
23338            
23339            "nodedrop",
23340             
23341            "nodedragover"
23342        );
23343        if(this.singleExpand){
23344            this.on("beforeexpandnode", this.restrictExpand, this);
23345        }
23346    },
23347
23348    // private
23349    proxyNodeEvent : function(ename, a1, a2, a3, a4, a5, a6){
23350        if(ename == 'collapse' || ename == 'expand' || ename == 'beforecollapse' || ename == 'beforeexpand' || ename == 'move' || ename == 'beforemove'){
23351            ename = ename+'node';
23352        }
23353        // args inline for performance while bubbling events
23354        return this.fireEvent(ename, a1, a2, a3, a4, a5, a6);
23355    },
23356
23357
23358    
23359    getRootNode : function(){
23360        return this.root;
23361    },
23362
23363    
23364    setRootNode : function(node){
23365        if(!node.render){ // attributes passed
23366            node = this.loader.createNode(node);
23367        }
23368        this.root = node;
23369        node.ownerTree = this;
23370        node.isRoot = true;
23371        this.registerNode(node);
23372        if(!this.rootVisible){
23373        	var uiP = node.attributes.uiProvider;
23374        	node.ui = uiP ? new uiP(node) : new Ext.tree.RootTreeNodeUI(node); 
23375        }
23376        return node;
23377    },
23378
23379    
23380    getNodeById : function(id){
23381        return this.nodeHash[id];
23382    },
23383
23384    // private
23385    registerNode : function(node){
23386        this.nodeHash[node.id] = node;
23387    },
23388
23389    // private
23390    unregisterNode : function(node){
23391        delete this.nodeHash[node.id];
23392    },
23393
23394    // private
23395    toString : function(){
23396        return "[Tree"+(this.id?" "+this.id:"")+"]";
23397    },
23398
23399    // private
23400    restrictExpand : function(node){
23401        var p = node.parentNode;
23402        if(p){
23403            if(p.expandedChild && p.expandedChild.parentNode == p){
23404                p.expandedChild.collapse();
23405            }
23406            p.expandedChild = node;
23407        }
23408    },
23409
23410    
23411    getChecked : function(a, startNode){
23412        startNode = startNode || this.root;
23413        var r = [];
23414        var f = function(){
23415            if(this.attributes.checked){
23416                r.push(!a ? this : (a == 'id' ? this.id : this.attributes[a]));
23417            }
23418        }
23419        startNode.cascade(f);
23420        return r;
23421    },
23422
23423    
23424    getEl : function(){
23425        return this.el;
23426    },
23427
23428    
23429    getLoader : function(){
23430        return this.loader;
23431    },
23432
23433    
23434    expandAll : function(){
23435        this.root.expand(true);
23436    },
23437
23438    
23439    collapseAll : function(){
23440        this.root.collapse(true);
23441    },
23442
23443    
23444    getSelectionModel : function(){
23445        if(!this.selModel){
23446            this.selModel = new Ext.tree.DefaultSelectionModel();
23447        }
23448        return this.selModel;
23449    },
23450
23451    
23452    expandPath : function(path, attr, callback){
23453        attr = attr || "id";
23454        var keys = path.split(this.pathSeparator);
23455        var curNode = this.root;
23456        if(curNode.attributes[attr] != keys[1]){ // invalid root
23457            if(callback){
23458                callback(false, null);
23459            }
23460            return;
23461        }
23462        var index = 1;
23463        var f = function(){
23464            if(++index == keys.length){
23465                if(callback){
23466                    callback(true, curNode);
23467                }
23468                return;
23469            }
23470            var c = curNode.findChild(attr, keys[index]);
23471            if(!c){
23472                if(callback){
23473                    callback(false, curNode);
23474                }
23475                return;
23476            }
23477            curNode = c;
23478            c.expand(false, false, f);
23479        };
23480        curNode.expand(false, false, f);
23481    },
23482
23483    
23484    selectPath : function(path, attr, callback){
23485        attr = attr || "id";
23486        var keys = path.split(this.pathSeparator);
23487        var v = keys.pop();
23488        if(keys.length > 0){
23489            var f = function(success, node){
23490                if(success && node){
23491                    var n = node.findChild(attr, v);
23492                    if(n){
23493                        n.select();
23494                        if(callback){
23495                            callback(true, n);
23496                        }
23497                    }else if(callback){
23498                        callback(false, n);
23499                    }
23500                }else{
23501                    if(callback){
23502                        callback(false, n);
23503                    }
23504                }
23505            };
23506            this.expandPath(keys.join(this.pathSeparator), attr, f);
23507        }else{
23508            this.root.select();
23509            if(callback){
23510                callback(true, this.root);
23511            }
23512        }
23513    },
23514
23515    
23516    getTreeEl : function(){
23517        return this.body;
23518    },
23519
23520    // private
23521    onRender : function(ct, position){
23522        Ext.tree.TreePanel.superclass.onRender.call(this, ct, position);
23523        this.el.addClass('x-tree');
23524        this.innerCt = this.body.createChild({tag:"ul",
23525               cls:"x-tree-root-ct " +
23526               (this.useArrows ? 'x-tree-arrows' : this.lines ? "x-tree-lines" : "x-tree-no-lines")});
23527    },
23528
23529    // private
23530    initEvents : function(){
23531        Ext.tree.TreePanel.superclass.initEvents.call(this);
23532
23533        if(this.containerScroll){
23534            Ext.dd.ScrollManager.register(this.body);
23535        }
23536        if((this.enableDD || this.enableDrop) && !this.dropZone){
23537           
23538             this.dropZone = new Ext.tree.TreeDropZone(this, this.dropConfig || {
23539               ddGroup: this.ddGroup || "TreeDD", appendOnly: this.ddAppendOnly === true
23540           });
23541        }
23542        if((this.enableDD || this.enableDrag) && !this.dragZone){
23543           
23544            this.dragZone = new Ext.tree.TreeDragZone(this, this.dragConfig || {
23545               ddGroup: this.ddGroup || "TreeDD",
23546               scroll: this.ddScroll
23547           });
23548        }
23549        this.getSelectionModel().init(this);
23550    },
23551
23552    // private
23553    afterRender : function(){
23554        Ext.tree.TreePanel.superclass.afterRender.call(this);
23555        this.root.render();
23556        if(!this.rootVisible){
23557            this.root.renderChildren();
23558        }
23559    },
23560
23561    onDestroy : function(){
23562        if(this.rendered){
23563            this.body.removeAllListeners();
23564            Ext.dd.ScrollManager.unregister(this.body);
23565            if(this.dropZone){
23566                this.dropZone.unreg();
23567            }
23568            if(this.dragZone){
23569               this.dragZone.unreg();
23570            }
23571        }
23572        this.root.destroy();
23573        this.nodeHash = null;
23574        Ext.tree.TreePanel.superclass.onDestroy.call(this);
23575    }
23576    
23577    
23578    
23579    
23580    
23581    
23582    
23583    
23584    
23585    
23586    
23587    
23588    
23589    
23590    
23591    
23592    
23593    
23594    
23595    
23596    
23597    
23598    
23599    
23600    
23601    
23602    
23603    
23604    
23605    
23606    
23607    
23608
23609
23610
23611    
23612    
23613    
23614    
23615    
23616    
23617    
23618    
23619    
23620    
23621    
23622    
23623});
23624
23625Ext.tree.TreePanel.nodeTypes = {};
23626
23627Ext.reg('treepanel', Ext.tree.TreePanel);
23628Ext.tree.TreeEventModel = function(tree){
23629    this.tree = tree;
23630    this.tree.on('render', this.initEvents, this);
23631}
23632
23633Ext.tree.TreeEventModel.prototype = {
23634    initEvents : function(){
23635        var el = this.tree.getTreeEl();
23636        el.on('click', this.delegateClick, this);
23637        if(this.tree.trackMouseOver !== false){
23638            el.on('mouseover', this.delegateOver, this);
23639            el.on('mouseout', this.delegateOut, this);
23640        }
23641        el.on('dblclick', this.delegateDblClick, this);
23642        el.on('contextmenu', this.delegateContextMenu, this);
23643    },
23644
23645    getNode : function(e){
23646        var t;
23647        if(t = e.getTarget('.x-tree-node-el', 10)){
23648            var id = Ext.fly(t, '_treeEvents').getAttributeNS('ext', 'tree-node-id');
23649            if(id){
23650                return this.tree.getNodeById(id);
23651            }
23652        }
23653        return null;
23654    },
23655
23656    getNodeTarget : function(e){
23657        var t = e.getTarget('.x-tree-node-icon', 1);
23658        if(!t){
23659            t = e.getTarget('.x-tree-node-el', 6);
23660        }
23661        return t;
23662    },
23663
23664    delegateOut : function(e, t){
23665        if(!this.beforeEvent(e)){
23666            return;
23667        }
23668        if(e.getTarget('.x-tree-ec-icon', 1)){
23669            var n = this.getNode(e);
23670            this.onIconOut(e, n);
23671            if(n == this.lastEcOver){
23672                delete this.lastEcOver;
23673            }
23674        }
23675        if((t = this.getNodeTarget(e)) && !e.within(t, true)){
23676            this.onNodeOut(e, this.getNode(e));
23677        }
23678    },
23679
23680    delegateOver : function(e, t){
23681        if(!this.beforeEvent(e)){
23682            return;
23683        }
23684        if(this.lastEcOver){ // prevent hung highlight
23685            this.onIconOut(e, this.lastEcOver);
23686            delete this.lastEcOver;
23687        }
23688        if(e.getTarget('.x-tree-ec-icon', 1)){
23689            this.lastEcOver = this.getNode(e);
23690            this.onIconOver(e, this.lastEcOver);
23691        }
23692        if(t = this.getNodeTarget(e)){
23693            this.onNodeOver(e, this.getNode(e));
23694        }
23695    },
23696
23697    delegateClick : function(e, t){
23698        if(!this.beforeEvent(e)){
23699            return;
23700        }
23701
23702        if(e.getTarget('input[type=checkbox]', 1)){
23703            this.onCheckboxClick(e, this.getNode(e));
23704        }
23705        else if(e.getTarget('.x-tree-ec-icon', 1)){
23706            this.onIconClick(e, this.getNode(e));
23707        }
23708        else if(this.getNodeTarget(e)){
23709            this.onNodeClick(e, this.getNode(e));
23710        }
23711    },
23712
23713    delegateDblClick : function(e, t){
23714        if(this.beforeEvent(e) && this.getNodeTarget(e)){
23715            this.onNodeDblClick(e, this.getNode(e));
23716        }
23717    },
23718
23719    delegateContextMenu : function(e, t){
23720        if(this.beforeEvent(e) && this.getNodeTarget(e)){
23721            this.onNodeContextMenu(e, this.getNode(e));
23722        }
23723    },
23724
23725    onNodeClick : function(e, node){
23726        node.ui.onClick(e);
23727    },
23728
23729    onNodeOver : function(e, node){
23730        node.ui.onOver(e);
23731    },
23732
23733    onNodeOut : function(e, node){
23734        node.ui.onOut(e);
23735    },
23736
23737    onIconOver : function(e, node){
23738        node.ui.addClass('x-tree-ec-over');
23739    },
23740
23741    onIconOut : function(e, node){
23742        node.ui.removeClass('x-tree-ec-over');
23743    },
23744
23745    onIconClick : function(e, node){
23746        node.ui.ecClick(e);
23747    },
23748
23749    onCheckboxClick : function(e, node){
23750        node.ui.onCheckChange(e);
23751    },
23752
23753    onNodeDblClick : function(e, node){
23754        node.ui.onDblClick(e);
23755    },
23756
23757    onNodeContextMenu : function(e, node){
23758        node.ui.onContextMenu(e);
23759    },
23760
23761    beforeEvent : function(e){
23762        if(this.disabled){
23763            e.stopEvent();
23764            return false;
23765        }
23766        return true;
23767    },
23768
23769    disable: function(){
23770        this.disabled = true;
23771    },
23772
23773    enable: function(){
23774        this.disabled = false;
23775    }
23776};
23777
23778Ext.tree.DefaultSelectionModel = function(config){
23779   this.selNode = null;
23780   
23781   this.addEvents(
23782       
23783       "selectionchange",
23784
23785       
23786       "beforeselect"
23787   );
23788
23789    Ext.apply(this, config);
23790    Ext.tree.DefaultSelectionModel.superclass.constructor.call(this);
23791};
23792
23793Ext.extend(Ext.tree.DefaultSelectionModel, Ext.util.Observable, {
23794    init : function(tree){
23795        this.tree = tree;
23796        tree.getTreeEl().on("keydown", this.onKeyDown, this);
23797        tree.on("click", this.onNodeClick, this);
23798    },
23799    
23800    onNodeClick : function(node, e){
23801        this.select(node);
23802    },
23803    
23804    
23805    select : function(node){
23806        var last = this.selNode;
23807        if(last != node && this.fireEvent('beforeselect', this, node, last) !== false){
23808            if(last){
23809                last.ui.onSelectedChange(false);
23810            }
23811            this.selNode = node;
23812            node.ui.onSelectedChange(true);
23813            this.fireEvent("selectionchange", this, node, last);
23814        }
23815        return node;
23816    },
23817    
23818    
23819    unselect : function(node){
23820        if(this.selNode == node){
23821            this.clearSelections();
23822        }    
23823    },
23824    
23825    
23826    clearSelections : function(){
23827        var n = this.selNode;
23828        if(n){
23829            n.ui.onSelectedChange(false);
23830            this.selNode = null;
23831            this.fireEvent("selectionchange", this, null);
23832        }
23833        return n;
23834    },
23835    
23836    
23837    getSelectedNode : function(){
23838        return this.selNode;    
23839    },
23840    
23841    
23842    isSelected : function(node){
23843        return this.selNode == node;  
23844    },
23845
23846    
23847    selectPrevious : function(){
23848        var s = this.selNode || this.lastSelNode;
23849        if(!s){
23850            return null;
23851        }
23852        var ps = s.previousSibling;
23853        if(ps){
23854            if(!ps.isExpanded() || ps.childNodes.length < 1){
23855                return this.select(ps);
23856            } else{
23857                var lc = ps.lastChild;
23858                while(lc && lc.isExpanded() && lc.childNodes.length > 0){
23859                    lc = lc.lastChild;
23860                }
23861                return this.select(lc);
23862            }
23863        } else if(s.parentNode && (this.tree.rootVisible || !s.parentNode.isRoot)){
23864            return this.select(s.parentNode);
23865        }
23866        return null;
23867    },
23868
23869    
23870    selectNext : function(){
23871        var s = this.selNode || this.lastSelNode;
23872        if(!s){
23873            return null;
23874        }
23875        if(s.firstChild && s.isExpanded()){
23876             return this.select(s.firstChild);
23877         }else if(s.nextSibling){
23878             return this.select(s.nextSibling);
23879         }else if(s.parentNode){
23880            var newS = null;
23881            s.parentNode.bubble(function(){
23882                if(this.nextSibling){
23883                    newS = this.getOwnerTree().selModel.select(this.nextSibling);
23884                    return false;
23885                }
23886            });
23887            return newS;
23888         }
23889        return null;
23890    },
23891
23892    onKeyDown : function(e){
23893        var s = this.selNode || this.lastSelNode;
23894        // undesirable, but required
23895        var sm = this;
23896        if(!s){
23897            return;
23898        }
23899        var k = e.getKey();
23900        switch(k){
23901             case e.DOWN:
23902                 e.stopEvent();
23903                 this.selectNext();
23904             break;
23905             case e.UP:
23906                 e.stopEvent();
23907                 this.selectPrevious();
23908             break;
23909             case e.RIGHT:
23910                 e.preventDefault();
23911                 if(s.hasChildNodes()){
23912                     if(!s.isExpanded()){
23913                         s.expand();
23914                     }else if(s.firstChild){
23915                         this.select(s.firstChild, e);
23916                     }
23917                 }
23918             break;
23919             case e.LEFT:
23920                 e.preventDefault();
23921                 if(s.hasChildNodes() && s.isExpanded()){
23922                     s.collapse();
23923                 }else if(s.parentNode && (this.tree.rootVisible || s.parentNode != this.tree.getRootNode())){
23924                     this.select(s.parentNode, e);
23925                 }
23926             break;
23927        };
23928    }
23929});
23930
23931
23932Ext.tree.MultiSelectionModel = function(config){
23933   this.selNodes = [];
23934   this.selMap = {};
23935   this.addEvents(
23936       
23937       "selectionchange"
23938   );
23939    Ext.apply(this, config);
23940    Ext.tree.MultiSelectionModel.superclass.constructor.call(this);
23941};
23942
23943Ext.extend(Ext.tree.MultiSelectionModel, Ext.util.Observable, {
23944    init : function(tree){
23945        this.tree = tree;
23946        tree.getTreeEl().on("keydown", this.onKeyDown, this);
23947        tree.on("click", this.onNodeClick, this);
23948    },
23949    
23950    onNodeClick : function(node, e){
23951        this.select(node, e, e.ctrlKey);
23952    },
23953    
23954    
23955    select : function(node, e, keepExisting){
23956        if(keepExisting !== true){
23957            this.clearSelections(true);
23958        }
23959        if(this.isSelected(node)){
23960            this.lastSelNode = node;
23961            return node;
23962        }
23963        this.selNodes.push(node);
23964        this.selMap[node.id] = node;
23965        this.lastSelNode = node;
23966        node.ui.onSelectedChange(true);
23967        this.fireEvent("selectionchange", this, this.selNodes);
23968        return node;
23969    },
23970    
23971    
23972    unselect : function(node){
23973        if(this.selMap[node.id]){
23974            node.ui.onSelectedChange(false);
23975            var sn = this.selNodes;
23976            var index = sn.indexOf(node);
23977            if(index != -1){
23978                this.selNodes.splice(index, 1);
23979            }
23980            delete this.selMap[node.id];
23981            this.fireEvent("selectionchange", this, this.selNodes);
23982        }
23983    },
23984    
23985    
23986    clearSelections : function(suppressEvent){
23987        var sn = this.selNodes;
23988        if(sn.length > 0){
23989            for(var i = 0, len = sn.length; i < len; i++){
23990                sn[i].ui.onSelectedChange(false);
23991            }
23992            this.selNodes = [];
23993            this.selMap = {};
23994            if(suppressEvent !== true){
23995                this.fireEvent("selectionchange", this, this.selNodes);
23996            }
23997        }
23998    },
23999    
24000    
24001    isSelected : function(node){
24002        return this.selMap[node.id] ? true : false;  
24003    },
24004    
24005    
24006    getSelectedNodes : function(){
24007        return this.selNodes;    
24008    },
24009
24010    onKeyDown : Ext.tree.DefaultSelectionModel.prototype.onKeyDown,
24011
24012    selectNext : Ext.tree.DefaultSelectionModel.prototype.selectNext,
24013
24014    selectPrevious : Ext.tree.DefaultSelectionModel.prototype.selectPrevious
24015});
24016
24017Ext.tree.TreeNode = function(attributes){
24018    attributes = attributes || {};
24019    if(typeof attributes == "string"){
24020        attributes = {text: attributes};
24021    }
24022    this.childrenRendered = false;
24023    this.rendered = false;
24024    Ext.tree.TreeNode.superclass.constructor.call(this, attributes);
24025    this.expanded = attributes.expanded === true;
24026    this.isTarget = attributes.isTarget !== false;
24027    this.draggable = attributes.draggable !== false && attributes.allowDrag !== false;
24028    this.allowChildren = attributes.allowChildren !== false && attributes.allowDrop !== false;
24029
24030    
24031    this.text = attributes.text;
24032    
24033    this.disabled = attributes.disabled === true;
24034
24035    this.addEvents(
24036        
24037        "textchange",
24038        
24039        "beforeexpand",
24040        
24041        "beforecollapse",
24042        
24043        "expand",
24044        
24045        "disabledchange",
24046        
24047        "collapse",
24048        
24049        "beforeclick",
24050        
24051        "click",
24052        
24053        "checkchange",
24054        
24055        "dblclick",
24056        
24057        "contextmenu",
24058        
24059        "beforechildrenrendered"
24060    );
24061
24062    var uiClass = this.attributes.uiProvider || this.defaultUI || Ext.tree.TreeNodeUI;
24063
24064    
24065    this.ui = new uiClass(this);
24066};
24067Ext.extend(Ext.tree.TreeNode, Ext.data.Node, {
24068    preventHScroll: true,
24069    
24070    isExpanded : function(){
24071        return this.expanded;
24072    },
24073
24074
24075    getUI : function(){
24076        return this.ui;
24077    },
24078
24079    getLoader : function(){
24080        var owner;
24081        return this.loader || ((owner = this.getOwnerTree()) && owner.loader ? owner.loader : new Ext.tree.TreeLoader());
24082    },
24083
24084    // private override
24085    setFirstChild : function(node){
24086        var of = this.firstChild;
24087        Ext.tree.TreeNode.superclass.setFirstChild.call(this, node);
24088        if(this.childrenRendered && of && node != of){
24089            of.renderIndent(true, true);
24090        }
24091        if(this.rendered){
24092            this.renderIndent(true, true);
24093        }
24094    },
24095
24096    // private override
24097    setLastChild : function(node){
24098        var ol = this.lastChild;
24099        Ext.tree.TreeNode.superclass.setLastChild.call(this, node);
24100        if(this.childrenRendered && ol && node != ol){
24101            ol.renderIndent(true, true);
24102        }
24103        if(this.rendered){
24104            this.renderIndent(true, true);
24105        }
24106    },
24107
24108    // these methods are overridden to provide lazy rendering support
24109    // private override
24110    appendChild : function(n){
24111        if(!n.render && !Ext.isArray(n)){
24112            n = this.getLoader().createNode(n);
24113        }
24114        var node = Ext.tree.TreeNode.superclass.appendChild.call(this, n);
24115        if(node && this.childrenRendered){
24116            node.render();
24117        }
24118        this.ui.updateExpandIcon();
24119        return node;
24120    },
24121
24122    // private override
24123    removeChild : function(node){
24124        this.ownerTree.getSelectionModel().unselect(node);
24125        Ext.tree.TreeNode.superclass.removeChild.apply(this, arguments);
24126        // if it's been rendered remove dom node
24127        if(this.childrenRendered){
24128            node.ui.remove();
24129        }
24130        if(this.childNodes.length < 1){
24131            this.collapse(false, false);
24132        }else{
24133            this.ui.updateExpandIcon();
24134        }
24135        if(!this.firstChild && !this.isHiddenRoot()) {
24136            this.childrenRendered = false;
24137        }
24138        return node;
24139    },
24140
24141    // private override
24142    insertBefore : function(node, refNode){
24143        if(!node.render){ 
24144            node = this.getLoader().createNode(node);
24145        }
24146        var newNode = Ext.tree.TreeNode.superclass.insertBefore.apply(this, arguments);
24147        if(newNode && refNode && this.childrenRendered){
24148            node.render();
24149        }
24150        this.ui.updateExpandIcon();
24151        return newNode;
24152    },
24153
24154    
24155    setText : function(text){
24156        var oldText = this.text;
24157        this.text = text;
24158        this.attributes.text = text;
24159        if(this.rendered){ // event without subscribing
24160            this.ui.onTextChange(this, text, oldText);
24161        }
24162        this.fireEvent("textchange", this, text, oldText);
24163    },
24164
24165    
24166    select : function(){
24167        this.getOwnerTree().getSelectionModel().select(this);
24168    },
24169
24170    
24171    unselect : function(){
24172        this.getOwnerTree().getSelectionModel().unselect(this);
24173    },
24174
24175    
24176    isSelected : function(){
24177        return this.getOwnerTree().getSelectionModel().isSelected(this);
24178    },
24179
24180    
24181    expand : function(deep, anim, callback){
24182        if(!this.expanded){
24183            if(this.fireEvent("beforeexpand", this, deep, anim) === false){
24184                return;
24185            }
24186            if(!this.childrenRendered){
24187                this.renderChildren();
24188            }
24189            this.expanded = true;
24190            if(!this.isHiddenRoot() && (this.getOwnerTree().animate && anim !== false) || anim){
24191                this.ui.animExpand(function(){
24192                    this.fireEvent("expand", this);
24193                    if(typeof callback == "function"){
24194                        callback(this);
24195                    }
24196                    if(deep === true){
24197                        this.expandChildNodes(true);
24198                    }
24199                }.createDelegate(this));
24200                return;
24201            }else{
24202                this.ui.expand();
24203                this.fireEvent("expand", this);
24204                if(typeof callback == "function"){
24205                    callback(this);
24206                }
24207            }
24208        }else{
24209           if(typeof callback == "function"){
24210               callback(this);
24211           }
24212        }
24213        if(deep === true){
24214            this.expandChildNodes(true);
24215        }
24216    },
24217
24218    isHiddenRoot : function(){
24219        return this.isRoot && !this.getOwnerTree().rootVisible;
24220    },
24221
24222    
24223    collapse : function(deep, anim){
24224        if(this.expanded && !this.isHiddenRoot()){
24225            if(this.fireEvent("beforecollapse", this, deep, anim) === false){
24226                return;
24227            }
24228            this.expanded = false;
24229            if((this.getOwnerTree().animate && anim !== false) || anim){
24230                this.ui.animCollapse(function(){
24231                    this.fireEvent("collapse", this);
24232                    if(deep === true){
24233                        this.collapseChildNodes(true);
24234                    }
24235                }.createDelegate(this));
24236                return;
24237            }else{
24238                this.ui.collapse();
24239                this.fireEvent("collapse", this);
24240            }
24241        }
24242        if(deep === true){
24243            var cs = this.childNodes;
24244            for(var i = 0, len = cs.length; i < len; i++) {
24245            	cs[i].collapse(true, false);
24246            }
24247        }
24248    },
24249
24250    // private
24251    delayedExpand : function(delay){
24252        if(!this.expandProcId){
24253            this.expandProcId = this.expand.defer(delay, this);
24254        }
24255    },
24256
24257    // private
24258    cancelExpand : function(){
24259        if(this.expandProcId){
24260            clearTimeout(this.expandProcId);
24261        }
24262        this.expandProcId = false;
24263    },
24264
24265    
24266    toggle : function(){
24267        if(this.expanded){
24268            this.collapse();
24269        }else{
24270            this.expand();
24271        }
24272    },
24273
24274    
24275    ensureVisible : function(callback){
24276        var tree = this.getOwnerTree();
24277        tree.expandPath(this.parentNode ? this.parentNode.getPath() : this.getPath(), false, function(){
24278            var node = tree.getNodeById(this.id);  // Somehow if we don't do this, we lose changes that happened to node in the meantime
24279            tree.getTreeEl().scrollChildIntoView(node.ui.anchor);
24280            Ext.callback(callback);
24281        }.createDelegate(this));
24282    },
24283
24284    
24285    expandChildNodes : function(deep){
24286        var cs = this.childNodes;
24287        for(var i = 0, len = cs.length; i < len; i++) {
24288        	cs[i].expand(deep);
24289        }
24290    },
24291
24292    
24293    collapseChildNodes : function(deep){
24294        var cs = this.childNodes;
24295        for(var i = 0, len = cs.length; i < len; i++) {
24296        	cs[i].collapse(deep);
24297        }
24298    },
24299
24300    
24301    disable : function(){
24302        this.disabled = true;
24303        this.unselect();
24304        if(this.rendered && this.ui.onDisableChange){ // event without subscribing
24305            this.ui.onDisableChange(this, true);
24306        }
24307        this.fireEvent("disabledchange", this, true);
24308    },
24309
24310    
24311    enable : function(){
24312        this.disabled = false;
24313        if(this.rendered && this.ui.onDisableChange){ // event without subscribing
24314            this.ui.onDisableChange(this, false);
24315        }
24316        this.fireEvent("disabledchange", this, false);
24317    },
24318
24319    // private
24320    renderChildren : function(suppressEvent){
24321        if(suppressEvent !== false){
24322            this.fireEvent("beforechildrenrendered", this);
24323        }
24324        var cs = this.childNodes;
24325        for(var i = 0, len = cs.length; i < len; i++){
24326            cs[i].render(true);
24327        }
24328        this.childrenRendered = true;
24329    },
24330
24331    // private
24332    sort : function(fn, scope){
24333        Ext.tree.TreeNode.superclass.sort.apply(this, arguments);
24334        if(this.childrenRendered){
24335            var cs = this.childNodes;
24336            for(var i = 0, len = cs.length; i < len; i++){
24337                cs[i].render(true);
24338            }
24339        }
24340    },
24341
24342    // private
24343    render : function(bulkRender){
24344        this.ui.render(bulkRender);
24345        if(!this.rendered){
24346            // make sure it is registered
24347            this.getOwnerTree().registerNode(this);
24348            this.rendered = true;
24349            if(this.expanded){
24350                this.expanded = false;
24351                this.expand(false, false);
24352            }
24353        }
24354    },
24355
24356    // private
24357    renderIndent : function(deep, refresh){
24358        if(refresh){
24359            this.ui.childIndent = null;
24360        }
24361        this.ui.renderIndent();
24362        if(deep === true && this.childrenRendered){
24363            var cs = this.childNodes;
24364            for(var i = 0, len = cs.length; i < len; i++){
24365                cs[i].renderIndent(true, refresh);
24366            }
24367        }
24368    },
24369
24370    beginUpdate : function(){
24371        this.childrenRendered = false;
24372    },
24373
24374    endUpdate : function(){
24375        if(this.expanded && this.rendered){
24376            this.renderChildren();
24377        }
24378    },
24379
24380    destroy : function(){
24381        if(this.childNodes){
24382	        for(var i = 0,l = this.childNodes.length; i < l; i++){
24383	            this.childNodes[i].destroy();
24384	        }
24385            this.childNodes = null;
24386        }
24387        if(this.ui.destroy){
24388            this.ui.destroy();
24389        }
24390    }
24391});
24392
24393Ext.tree.TreePanel.nodeTypes.node = Ext.tree.TreeNode;
24394
24395 Ext.tree.AsyncTreeNode = function(config){
24396    this.loaded = config && config.loaded === true;
24397    this.loading = false;
24398    Ext.tree.AsyncTreeNode.superclass.constructor.apply(this, arguments);
24399    
24400    this.addEvents('beforeload', 'load');
24401    
24402    
24403};
24404Ext.extend(Ext.tree.AsyncTreeNode, Ext.tree.TreeNode, {
24405    expand : function(deep, anim, callback){
24406        if(this.loading){ // if an async load is already running, waiting til it's done
24407            var timer;
24408            var f = function(){
24409                if(!this.loading){ // done loading
24410                    clearInterval(timer);
24411                    this.expand(deep, anim, callback);
24412                }
24413            }.createDelegate(this);
24414            timer = setInterval(f, 200);
24415            return;
24416        }
24417        if(!this.loaded){
24418            if(this.fireEvent("beforeload", this) === false){
24419                return;
24420            }
24421            this.loading = true;
24422            this.ui.beforeLoad(this);
24423            var loader = this.loader || this.attributes.loader || this.getOwnerTree().getLoader();
24424            if(loader){
24425                loader.load(this, this.loadComplete.createDelegate(this, [deep, anim, callback]));
24426                return;
24427            }
24428        }
24429        Ext.tree.AsyncTreeNode.superclass.expand.call(this, deep, anim, callback);
24430    },
24431    
24432    
24433    isLoading : function(){
24434        return this.loading;  
24435    },
24436    
24437    loadComplete : function(deep, anim, callback){
24438        this.loading = false;
24439        this.loaded = true;
24440        this.ui.afterLoad(this);
24441        this.fireEvent("load", this);
24442        this.expand(deep, anim, callback);
24443    },
24444    
24445    
24446    isLoaded : function(){
24447        return this.loaded;
24448    },
24449    
24450    hasChildNodes : function(){
24451        if(!this.isLeaf() && !this.loaded){
24452            return true;
24453        }else{
24454            return Ext.tree.AsyncTreeNode.superclass.hasChildNodes.call(this);
24455        }
24456    },
24457
24458    
24459    reload : function(callback){
24460        this.collapse(false, false);
24461        while(this.firstChild){
24462            this.removeChild(this.firstChild).destroy();
24463        }
24464        this.childrenRendered = false;
24465        this.loaded = false;
24466        if(this.isHiddenRoot()){
24467            this.expanded = false;
24468        }
24469        this.expand(false, false, callback);
24470    }
24471});
24472
24473Ext.tree.TreePanel.nodeTypes.async = Ext.tree.AsyncTreeNode;
24474
24475Ext.tree.TreeNodeUI = function(node){
24476    this.node = node;
24477    this.rendered = false;
24478    this.animating = false;
24479    this.wasLeaf = true;
24480    this.ecc = 'x-tree-ec-icon x-tree-elbow';
24481    this.emptyIcon = Ext.BLANK_IMAGE_URL;
24482};
24483
24484Ext.tree.TreeNodeUI.prototype = {
24485    // private
24486    removeChild : function(node){
24487        if(this.rendered){
24488            this.ctNode.removeChild(node.ui.getEl());
24489        } 
24490    },
24491
24492    // private
24493    beforeLoad : function(){
24494         this.addClass("x-tree-node-loading");
24495    },
24496
24497    // private
24498    afterLoad : function(){
24499         this.removeClass("x-tree-node-loading");
24500    },
24501
24502    // private
24503    onTextChange : function(node, text, oldText){
24504        if(this.rendered){
24505            this.textNode.innerHTML = text;
24506        }
24507    },
24508
24509    // private
24510    onDisableChange : function(node, state){
24511        this.disabled = state;
24512		if (this.checkbox) {
24513			this.checkbox.disabled = state;
24514		}        
24515        if(state){
24516            this.addClass("x-tree-node-disabled");
24517        }else{
24518            this.removeClass("x-tree-node-disabled");
24519        } 
24520    },
24521
24522    // private
24523    onSelectedChange : function(state){
24524        if(state){
24525            this.focus();
24526            this.addClass("x-tree-selected");
24527        }else{
24528            //this.blur();
24529            this.removeClass("x-tree-selected");
24530        }
24531    },
24532
24533    // private
24534    onMove : function(tree, node, oldParent, newParent, index, refNo
24534de){
24535        this.childIndent = null;
24536        if(this.rendered){
24537            var targetNode = newParent.ui.getContainer();
24538            if(!targetNode){//target not rendered
24539                this.holder = document.createElement("div");
24540                this.holder.appendChild(this.wrap);
24541                return;
24542            }
24543            var insertBefore = refNode ? refNode.ui.getEl() : null;
24544            if(insertBefore){
24545                targetNode.insertBefore(this.wrap, insertBefore);
24546            }else{
24547                targetNode.appendChild(this.wrap);
24548            }
24549            this.node.renderIndent(true);
24550        }
24551    },
24552
24553
24554    addClass : function(cls){
24555        if(this.elNode){
24556            Ext.fly(this.elNode).addClass(cls);
24557        }
24558    },
24559
24560
24561    removeClass : function(cls){
24562        if(this.elNode){
24563            Ext.fly(this.elNode).removeClass(cls);  
24564        }
24565    },
24566
24567    // private
24568    remove : function(){
24569        if(this.rendered){
24570            this.holder = document.createElement("div");
24571            this.holder.appendChild(this.wrap);
24572        }  
24573    },
24574
24575    // private
24576    fireEvent : function(){
24577        return this.node.fireEvent.apply(this.node, arguments);  
24578    },
24579
24580    // private
24581    initEvents : function(){
24582        this.node.on("move", this.onMove, this);
24583
24584        if(this.node.disabled){
24585            this.addClass("x-tree-node-disabled");
24586			if (this.checkbox) {
24587				this.checkbox.disabled = true;
24588			}            
24589        }
24590        if(this.node.hidden){
24591            this.hide();
24592        }
24593        var ot = this.node.getOwnerTree();
24594        var dd = ot.enableDD || ot.enableDrag || ot.enableDrop;
24595        if(dd && (!this.node.isRoot || ot.rootVisible)){
24596            Ext.dd.Registry.register(this.elNode, {
24597                node: this.node,
24598                handles: this.getDDHandles(),
24599                isHandle: false
24600            });
24601        }
24602    },
24603
24604    // private
24605    getDDHandles : function(){
24606        return [this.iconNode, this.textNode, this.elNode];
24607    },
24608
24609
24610    hide : function(){
24611        this.node.hidden = true;
24612        if(this.wrap){
24613            this.wrap.style.display = "none";
24614        }
24615    },
24616
24617
24618    show : function(){
24619        this.node.hidden = false;
24620        if(this.wrap){
24621            this.wrap.style.display = "";
24622        } 
24623    },
24624
24625    // private
24626    onContextMenu : function(e){
24627        if (this.node.hasListener("contextmenu") || this.node.getOwnerTree().hasListener("contextmenu")) {
24628            e.preventDefault();
24629            this.focus();
24630            this.fireEvent("contextmenu", this.node, e);
24631        }
24632    },
24633
24634    // private
24635    onClick : function(e){
24636        if(this.dropping){
24637            e.stopEvent();
24638            return;
24639        }
24640        if(this.fireEvent("beforeclick", this.node, e) !== false){
24641            var a = e.getTarget('a');
24642            if(!this.disabled && this.node.attributes.href && a){
24643                this.fireEvent("click", this.node, e);
24644                return;
24645            }else if(a && e.ctrlKey){
24646                e.stopEvent();
24647            }
24648            e.preventDefault();
24649            if(this.disabled){
24650                return;
24651            }
24652
24653            if(this.node.attributes.singleClickExpand && !this.animating && this.node.isExpandable()){
24654                this.node.toggle();
24655            }
24656
24657            this.fireEvent("click", this.node, e);
24658        }else{
24659            e.stopEvent();
24660        }
24661    },
24662
24663    // private
24664    onDblClick : function(e){
24665        e.preventDefault();
24666        if(this.disabled){
24667            return;
24668        }
24669        if(this.checkbox){
24670            this.toggleCheck();
24671        }
24672        if(!this.animating && this.node.isExpandable()){
24673            this.node.toggle();
24674        }
24675        this.fireEvent("dblclick", this.node, e);
24676    },
24677
24678    onOver : function(e){
24679        this.addClass('x-tree-node-over');
24680    },
24681
24682    onOut : function(e){
24683        this.removeClass('x-tree-node-over');
24684    },
24685
24686    // private
24687    onCheckChange : function(){
24688        var checked = this.checkbox.checked;
24689		// fix for IE6
24690		this.checkbox.defaultChecked = checked;
24691        this.node.attributes.checked = checked;
24692        this.fireEvent('checkchange', this.node, checked);
24693    },
24694
24695    // private
24696    ecClick : function(e){
24697        if(!this.animating && this.node.isExpandable()){
24698            this.node.toggle();
24699        }
24700    },
24701
24702    // private
24703    startDrop : function(){
24704        this.dropping = true;
24705    },
24706    
24707    // delayed drop so the click event doesn't get fired on a drop
24708    endDrop : function(){ 
24709       setTimeout(function(){
24710           this.dropping = false;
24711       }.createDelegate(this), 50); 
24712    },
24713
24714    // private
24715    expand : function(){
24716        this.updateExpandIcon();
24717        this.ctNode.style.display = "";
24718    },
24719
24720    // private
24721    focus : function(){
24722        if(!this.node.preventHScroll){
24723            try{this.anchor.focus();
24724            }catch(e){}
24725        }else{
24726            try{
24727                var noscroll = this.node.getOwnerTree().getTreeEl().dom;
24728                var l = noscroll.scrollLeft;
24729                this.anchor.focus();
24730                noscroll.scrollLeft = l;
24731            }catch(e){}
24732        }
24733    },
24734
24735
24736    toggleCheck : function(value){
24737        var cb = this.checkbox;
24738        if(cb){
24739            cb.checked = (value === undefined ? !cb.checked : value);
24740            this.onCheckChange();
24741        }
24742    },
24743
24744    // private
24745    blur : function(){
24746        try{
24747            this.anchor.blur();
24748        }catch(e){} 
24749    },
24750
24751    // private
24752    animExpand : function(callback){
24753        var ct = Ext.get(this.ctNode);
24754        ct.stopFx();
24755        if(!this.node.isExpandable()){
24756            this.updateExpandIcon();
24757            this.ctNode.style.display = "";
24758            Ext.callback(callback);
24759            return;
24760        }
24761        this.animating = true;
24762        this.updateExpandIcon();
24763        
24764        ct.slideIn('t', {
24765           callback : function(){
24766               this.animating = false;
24767               Ext.callback(callback);
24768            },
24769            scope: this,
24770            duration: this.node.ownerTree.duration || .25
24771        });
24772    },
24773
24774    // private
24775    highlight : function(){
24776        var tree = this.node.getOwnerTree();
24777        Ext.fly(this.wrap).highlight(
24778            tree.hlColor || "C3DAF9",
24779            {endColor: tree.hlBaseColor}
24780        );
24781    },
24782
24783    // private
24784    collapse : function(){
24785        this.updateExpandIcon();
24786        this.ctNode.style.display = "none";
24787    },
24788
24789    // private
24790    animCollapse : function(callback){
24791        var ct = Ext.get(this.ctNode);
24792        ct.enableDisplayMode('block');
24793        ct.stopFx();
24794
24795        this.animating = true;
24796        this.updateExpandIcon();
24797
24798        ct.slideOut('t', {
24799            callback : function(){
24800               this.animating = false;
24801               Ext.callback(callback);
24802            },
24803            scope: this,
24804            duration: this.node.ownerTree.duration || .25
24805        });
24806    },
24807
24808    // private
24809    getContainer : function(){
24810        return this.ctNode;  
24811    },
24812
24813    // private
24814    getEl : function(){
24815        return this.wrap;  
24816    },
24817
24818    // private
24819    appendDDGhost : function(ghostNode){
24820        ghostNode.appendChild(this.elNode.cloneNode(true));
24821    },
24822
24823    // private
24824    getDDRepairXY : function(){
24825        return Ext.lib.Dom.getXY(this.iconNode);
24826    },
24827
24828    // private
24829    onRender : function(){
24830        this.render();    
24831    },
24832
24833    // private
24834    render : function(bulkRender){
24835        var n = this.node, a = n.attributes;
24836        var targetNode = n.parentNode ? 
24837              n.parentNode.ui.getContainer() : n.ownerTree.innerCt.dom;
24838        
24839        if(!this.rendered){
24840            this.rendered = true;
24841
24842            this.renderElements(n, a, targetNode, bulkRender);
24843
24844            if(a.qtip){
24845               if(this.textNode.setAttributeNS){
24846                   this.textNode.setAttributeNS("ext", "qtip", a.qtip);
24847                   if(a.qtipTitle){
24848                       this.textNode.setAttributeNS("ext", "qtitle", a.qtipTitle);
24849                   }
24850               }else{
24851                   this.textNode.setAttribute("ext:qtip", a.qtip);
24852                   if(a.qtipTitle){
24853                       this.textNode.setAttribute("ext:qtitle", a.qtipTitle);
24854                   }
24855               } 
24856            }else if(a.qtipCfg){
24857                a.qtipCfg.target = Ext.id(this.textNode);
24858                Ext.QuickTips.register(a.qtipCfg);
24859            }
24860            this.initEvents();
24861            if(!this.node.expanded){
24862                this.updateExpandIcon(true);
24863            }
24864        }else{
24865            if(bulkRender === true) {
24866                targetNode.appendChild(this.wrap);
24867            }
24868        }
24869    },
24870
24871    // private
24872    renderElements : function(n, a, targetNode, bulkRender){
24873        // add some indent caching, this helps performance when rendering a large tree
24874        this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';
24875
24876        var cb = typeof a.checked == 'boolean';
24877
24878        var href = a.href ? a.href : Ext.isGecko ? "" : "#";
24879        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">',
24880            '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",
24881            '<img src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow" />',
24882            '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on" />',
24883            cb ? ('<input class="x-tree-node-cb" type="checkbox" ' + (a.checked ? 'checked="checked" />' : '/>')) : '',
24884            '<a hidefocus="on" class="x-tree-node-anchor" href="',href,'" tabIndex="1" ',
24885             a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", '><span unselectable="on">',n.text,"</span></a></div>",
24886            '<ul class="x-tree-node-ct" style="display:none;"></ul>',
24887            "</li>"].join('');
24888
24889        var nel;
24890        if(bulkRender !== true && n.nextSibling && (nel = n.nextSibling.ui.getEl())){
24891            this.wrap = Ext.DomHelper.insertHtml("beforeBegin", nel, buf);
24892        }else{
24893            this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf);
24894        }
24895        
24896        this.elNode = this.wrap.childNodes[0];
24897        this.ctNode = this.wrap.childNodes[1];
24898        var cs = this.elNode.childNodes;
24899        this.indentNode = cs[0];
24900        this.ecNode = cs[1];
24901        this.iconNode = cs[2];
24902        var index = 3;
24903        if(cb){
24904            this.checkbox = cs[3];
24905			// fix for IE6
24906			this.checkbox.defaultChecked = this.checkbox.checked;			
24907            index++;
24908        }
24909        this.anchor = cs[index];
24910        this.textNode = cs[index].firstChild;
24911    },
24912
24913
24914    getAnchor : function(){
24915        return this.anchor;
24916    },
24917    
24918
24919    getTextEl : function(){
24920        return this.textNode;
24921    },
24922    
24923
24924    getIconEl : function(){
24925        return this.iconNode;
24926    },
24927
24928
24929    isChecked : function(){
24930        return this.checkbox ? this.checkbox.checked : false; 
24931    },
24932
24933    // private
24934    updateExpandIcon : function(){
24935        if(this.rendered){
24936            var n = this.node, c1, c2;
24937            var cls = n.isLast() ? "x-tree-elbow-end" : "x-tree-elbow";
24938            if(n.isExpandable()){
24939                if(n.expanded){
24940                    cls += "-minus";
24941                    c1 = "x-tree-node-collapsed";
24942                    c2 = "x-tree-node-expanded";
24943                }else{
24944                    cls += "-plus";
24945                    c1 = "x-tree-node-expanded";
24946                    c2 = "x-tree-node-collapsed";
24947                }
24948                if(this.wasLeaf){
24949                    this.removeClass("x-tree-node-leaf");
24950                    this.wasLeaf = false;
24951                }
24952                if(this.c1 != c1 || this.c2 != c2){
24953                    Ext.fly(this.elNode).replaceClass(c1, c2);
24954                    this.c1 = c1; this.c2 = c2;
24955                }
24956            }else{
24957                if(!this.wasLeaf){
24958                    Ext.fly(this.elNode).replaceClass("x-tree-node-expanded", "x-tree-node-leaf");
24959                    delete this.c1;
24960                    delete this.c2;
24961                    this.wasLeaf = true;
24962                }
24963            }
24964            var ecc = "x-tree-ec-icon "+cls;
24965            if(this.ecc != ecc){
24966                this.ecNode.className = ecc;
24967                this.ecc = ecc;
24968            }
24969        }
24970    },
24971
24972    // private
24973    getChildIndent : function(){
24974        if(!this.childIndent){
24975            var buf = [];
24976            var p = this.node;
24977            while(p){
24978                if(!p.isRoot || (p.isRoot && p.ownerTree.rootVisible)){
24979                    if(!p.isLast()) {
24980                        buf.unshift('<img src="'+this.emptyIcon+'" class="x-tree-elbow-line" />');
24981                    } else {
24982                        buf.unshift('<img src="'+this.emptyIcon+'" class="x-tree-icon" />');
24983                    }
24984                }
24985                p = p.parentNode;
24986            }
24987            this.childIndent = buf.join("");
24988        }
24989        return this.childIndent;
24990    },
24991
24992    // private
24993    renderIndent : function(){
24994        if(this.rendered){
24995            var indent = "";
24996            var p = this.node.parentNode;
24997            if(p){
24998                indent = p.ui.getChildIndent();
24999            }
25000            if(this.indentMarkup != indent){ // don't rerender if not required
25001                this.indentNode.innerHTML = indent;
25002                this.indentMarkup = indent;
25003            }
25004            this.updateExpandIcon();
25005        }
25006    },
25007
25008    destroy : function(){
25009        if(this.elNode){
25010            Ext.dd.Registry.unregister(this.elNode.id);
25011        }
25012        delete this.elNode;
25013        delete this.ctNode;
25014        delete this.indentNode;
25015        delete this.ecNode;
25016        delete this.iconNode;
25017        delete this.checkbox;
25018        delete this.anchor;
25019        delete this.textNode;
25020        
25021        if (this.holder){
25022             delete this.wrap;
25023             Ext.removeNode(this.holder);
25024             delete this.holder;
25025        }else{
25026            Ext.removeNode(this.wrap);
25027            delete this.wrap;
25028        }
25029    }
25030};
25031
25032
25033Ext.tree.RootTreeNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
25034    // private
25035    render : function(){
25036        if(!this.rendered){
25037            var targetNode = this.node.ownerTree.innerCt.dom;
25038            this.node.expanded = true;
25039            targetNode.innerHTML = '<div class="x-tree-root-node"></div>';
25040            this.wrap = this.ctNode = targetNode.firstChild;
25041        }
25042    },
25043    collapse : Ext.emptyFn,
25044    expand : Ext.emptyFn
25045});
25046
25047Ext.tree.TreeLoader = function(config){
25048    this.baseParams = {};
25049    Ext.apply(this, config);
25050
25051    this.addEvents(
25052        
25053        "beforeload",
25054        
25055        "load",
25056        
25057        "loadexception"
25058    );
25059
25060    Ext.tree.TreeLoader.superclass.constructor.call(this);
25061};
25062
25063Ext.extend(Ext.tree.TreeLoader, Ext.util.Observable, {
25064    
25065    
25066    
25067    
25068    
25069    
25070    
25071    uiProviders : {},
25072
25073    
25074    clearOnLoad : true,
25075
25076    
25077    load : function(node, callback){
25078        if(this.clearOnLoad){
25079            while(node.firstChild){
25080                node.removeChild(node.firstChild);
25081            }
25082        }
25083        if(this.doPreload(node)){ // preloaded json children
25084            if(typeof callback == "function"){
25085                callback();
25086            }
25087        }else if(this.dataUrl||this.url){
25088            this.requestData(node, callback);
25089        }
25090    },
25091
25092    doPreload : function(node){
25093        if(node.attributes.children){
25094            if(node.childNodes.length < 1){ // preloaded?
25095                var cs = node.attributes.children;
25096                node.beginUpdate();
25097                for(var i = 0, len = cs.length; i < len; i++){
25098                    var cn = node.appendChild(this.createNode(cs[i]));
25099                    if(this.preloadChildren){
25100                        this.doPreload(cn);
25101                    }
25102                }
25103                node.endUpdate();
25104            }
25105            return true;
25106        }else {
25107            return false;
25108        }
25109    },
25110
25111    getParams: function(node){
25112        var buf = [], bp = this.baseParams;
25113        for(var key in bp){
25114            if(typeof bp[key] != "function"){
25115                buf.push(encodeURIComponent(key), "=", encodeURIComponent(bp[key]), "&");
25116            }
25117        }
25118        buf.push("node=", encodeURIComponent(node.id));
25119        return buf.join("");
25120    },
25121
25122    requestData : function(node, callback){
25123        if(this.fireEvent("beforeload", this, node, callback) !== false){
25124            this.transId = Ext.Ajax.request({
25125                method:this.requestMethod,
25126                url: this.dataUrl||this.url,
25127                success: this.handleResponse,
25128                failure: this.handleFailure,
25129                scope: this,
25130                argument: {callback: callback, node: node},
25131                params: this.getParams(node)
25132            });
25133        }else{
25134            // if the load is cancelled, make sure we notify
25135            // the node that we are done
25136            if(typeof callback == "function"){
25137                callback();
25138            }
25139        }
25140    },
25141
25142    isLoading : function(){
25143        return !!this.transId;
25144    },
25145
25146    abort : function(){
25147        if(this.isLoading()){
25148            Ext.Ajax.abort(this.transId);
25149        }
25150    },
25151
25152    
25153    createNode : function(attr){
25154        // apply baseAttrs, nice idea Corey!
25155        if(this.baseAttrs){
25156            Ext.applyIf(attr, this.baseAttrs);
25157        }
25158        if(this.applyLoader !== false){
25159            attr.loader = this;
25160        }
25161        if(typeof attr.uiProvider == 'string'){
25162           attr.uiProvider = this.uiProviders[attr.uiProvider] || eval(attr.uiProvider);
25163        }
25164        if(attr.nodeType){
25165            return new Ext.tree.TreePanel.nodeTypes[attr.nodeType](attr);
25166        }else{
25167            return attr.leaf ?
25168                        new Ext.tree.TreeNode(attr) :
25169                        new Ext.tree.AsyncTreeNode(attr);
25170        }
25171    },
25172
25173    processResponse : function(response, node, callback){
25174        var json = response.responseText;
25175        try {
25176            var o = eval("("+json+")");
25177            node.beginUpdate();
25178            for(var i = 0, len = o.length; i < len; i++){
25179                var n = this.createNode(o[i]);
25180                if(n){
25181                    node.appendChild(n);
25182                }
25183            }
25184            node.endUpdate();
25185            if(typeof callback == "function"){
25186                callback(this, node);
25187            }
25188        }catch(e){
25189            this.handleFailure(response);
25190        }
25191    },
25192
25193    handleResponse : function(response){
25194        this.transId = false;
25195        var a = response.argument;
25196        this.processResponse(response, a.node, a.callback);
25197        this.fireEvent("load", this, a.node, response);
25198    },
25199
25200    handleFailure : function(response){
25201        this.transId = false;
25202        var a = response.argument;
25203        this.fireEvent("loadexception", this, a.node, response);
25204        if(typeof a.callback == "function"){
25205            a.callback(this, a.node);
25206        }
25207    }
25208});
25209
25210Ext.tree.TreeFilter = function(tree, config){
25211    this.tree = tree;
25212    this.filtered = {};
25213    Ext.apply(this, config);
25214};
25215
25216Ext.tree.TreeFilter.prototype = {
25217    clearBlank:false,
25218    reverse:false,
25219    autoClear:false,
25220    remove:false,
25221
25222     
25223    filter : function(value, attr, startNode){
25224        attr = attr || "text";
25225        var f;
25226        if(typeof value == "string"){
25227            var vlen = value.length;
25228            // auto clear empty filter
25229            if(vlen == 0 && this.clearBlank){
25230                this.clear();
25231                return;
25232            }
25233            value = value.toLowerCase();
25234            f = function(n){
25235                return n.attributes[attr].substr(0, vlen).toLowerCase() == value;
25236            };
25237        }else if(value.exec){ // regex?
25238            f = function(n){
25239                return value.test(n.attributes[attr]);
25240            };
25241        }else{
25242            throw 'Illegal filter type, must be string or regex';
25243        }
25244        this.filterBy(f, null, startNode);
25245	},
25246    
25247    
25248    filterBy : function(fn, scope, startNode){
25249        startNode = startNode || this.tree.root;
25250        if(this.autoClear){
25251            this.clear();
25252        }
25253        var af = this.filtered, rv = this.reverse;
25254        var f = function(n){
25255            if(n == startNode){
25256                return true;
25257            }
25258            if(af[n.id]){
25259                return false;
25260            }
25261            var m = fn.call(scope || n, n);
25262            if(!m || rv){
25263                af[n.id] = n;
25264                n.ui.hide();
25265                return false;
25266            }
25267            return true;
25268        };
25269        startNode.cascade(f);
25270        if(this.remove){
25271           for(var id in af){
25272               if(typeof id != "function"){
25273                   var n = af[id];
25274                   if(n && n.parentNode){
25275                       n.parentNode.removeChild(n);
25276                   }
25277               }
25278           } 
25279        }
25280    },
25281    
25282    
25283    clear : function(){
25284        var t = this.tree;
25285        var af = this.filtered;
25286        for(var id in af){
25287            if(typeof id != "function"){
25288                var n = af[id];
25289                if(n){
25290                    n.ui.show();
25291                }
25292            }
25293        }
25294        this.filtered = {}; 
25295    }
25296};
25297
25298
25299Ext.tree.TreeSorter = function(tree, config){
25300    
25301	
25302    
25303    
25304    
25305    
25306    
25307    Ext.apply(this, config);
25308    tree.on("beforechildrenrendered", this.doSort, this);
25309    tree.on("append", this.updateSort, this);
25310    tree.on("insert", this.updateSort, this);
25311    tree.on("textchange", this.updateSortParent, this);
25312    
25313    var dsc = this.dir && this.dir.toLowerCase() == "desc";
25314    var p = this.property || "text";
25315    var sortType = this.sortType;
25316    var fs = this.folderSort;
25317    var cs = this.caseSensitive === true;
25318    var leafAttr = this.leafAttr || 'leaf';
25319
25320    this.sortFn = function(n1, n2){
25321        if(fs){
25322            if(n1.attributes[leafAttr] && !n2.attributes[leafAttr]){
25323                return 1;
25324            }
25325            if(!n1.attributes[leafAttr] && n2.attributes[leafAttr]){
25326                return -1;
25327            }
25328        }
25329    	var v1 = sortType ? sortType(n1) : (cs ? n1.attributes[p] : n1.attributes[p].toUpperCase());
25330    	var v2 = sortType ? sortType(n2) : (cs ? n2.attributes[p] : n2.attributes[p].toUpperCase());
25331    	if(v1 < v2){
25332			return dsc ? +1 : -1;
25333		}else if(v1 > v2){
25334			return dsc ? -1 : +1;
25335        }else{
25336	    	return 0;
25337        }
25338    };
25339};
25340
25341Ext.tree.TreeSorter.prototype = {
25342    doSort : function(node){
25343        node.sort(this.sortFn);
25344    },
25345    
25346    compareNodes : function(n1, n2){
25347        return (n1.text.toUpperCase() > n2.text.toUpperCase() ? 1 : -1);
25348    },
25349    
25350    updateSort : function(tree, node){
25351        if(node.childrenRendered){
25352            this.doSort.defer(1, this, [node]);
25353        }
25354    },
25355    
25356    updateSortParent : function(node){
25357		var p = node.parentNode;
25358		if(p && p.childrenRendered){
25359            this.doSort.defer(1, this, [p]);
25360        }
25361    }
25362};
25363
25364if(Ext.dd.DropZone){
25365    
25366Ext.tree.TreeDropZone = function(tree, config){
25367    
25368    this.allowParentInsert = false;
25369    
25370    this.allowContainerDrop = false;
25371    
25372    this.appendOnly = false;
25373    Ext.tree.TreeDropZone.superclass.constructor.call(this, tree.innerCt, config);
25374    
25375    this.tree = tree;
25376    
25377    this.dragOverData = {};
25378    // private
25379    this.lastInsertClass = "x-tree-no-status";
25380};
25381
25382Ext.extend(Ext.tree.TreeDropZone, Ext.dd.DropZone, {
25383    
25384    ddGroup : "TreeDD",
25385
25386    
25387    expandDelay : 1000,
25388
25389    // private
25390    expandNode : function(node){
25391        if(node.hasChildNodes() && !node.isExpanded()){
25392            node.expand(false, null, this.triggerCacheRefresh.createDelegate(this));
25393        }
25394    },
25395
25396    // private
25397    queueExpand : function(node){
25398        this.expandProcId = this.expandNode.defer(this.expandDelay, this, [node]);
25399    },
25400
25401    // private
25402    cancelExpand : function(){
25403        if(this.expandProcId){
25404            clearTimeout(this.expandProcId);
25405            this.expandProcId = false;
25406        }
25407    },
25408
25409    // private
25410    isValidDropPoint : function(n, pt, dd, e, data){
25411        if(!n || !data){ return false; }
25412        var targetNode = n.node;
25413        var dropNode = data.node;
25414        // default drop rules
25415        if(!(targetNode && targetNode.isTarget && pt)){
25416            return false;
25417        }
25418        if(pt == "append" && targetNode.allowChildren === false){
25419            return false;
25420        }
25421        if((pt == "above" || pt == "below") && (targetNode.parentNode && targetNode.parentNode.allowChildren === false)){
25422            return false;
25423        }
25424        if(dropNode && (targetNode == dropNode || dropNode.contains(targetNode))){
25425            return false;
25426        }
25427        // reuse the object
25428        var overEvent = this.dragOverData;
25429        overEvent.tree = this.tree;
25430        overEvent.target = targetNode;
25431        overEvent.data = data;
25432        overEvent.point = pt;
25433        overEvent.source = dd;
25434        overEvent.rawEvent = e;
25435        overEvent.dropNode = dropNode;
25436        overEvent.cancel = false;  
25437        var result = this.tree.fireEvent("nodedragover", overEvent);
25438        return overEvent.cancel === false && result !== false;
25439    },
25440
25441    // private
25442    getDropPoint : function(e, n, dd){
25443        var tn = n.node;
25444        if(tn.isRoot){
25445            return tn.allowChildren !== false ? "append" : false; // always append for root
25446        }
25447        var dragEl = n.ddel;
25448        var t = Ext.lib.Dom.getY(dragEl), b = t + dragEl.offsetHeight;
25449        var y = Ext.lib.Event.getPageY(e);
25450        var noAppend = tn.allowChildren === false || tn.isLeaf();
25451        if(this.appendOnly || tn.parentNode.allowChildren === false){
25452            return noAppend ? false : "append";
25453        }
25454        var noBelow = false;
25455        if(!this.allowParentInsert){
25456            noBelow = tn.hasChildNodes() && tn.isExpanded();
25457        }
25458        var q = (b - t) / (noAppend ? 2 : 3);
25459        if(y >= t && y < (t + q)){
25460            return "above";
25461        }else if(!noBelow && (noAppend || y >= b-q && y <= b)){
25462            return "below";
25463        }else{
25464            return "append";
25465        }
25466    },
25467
25468    // private
25469    onNodeEnter : function(n, dd, e, data){
25470        this.cancelExpand();
25471    },
25472
25473    // private
25474    onNodeOver : function(n, dd, e, data){
25475        var pt = this.getDropPoint(e, n, dd);
25476        var node = n.node;
25477        
25478        // auto node expand check
25479        if(!this.expandProcId && pt == "append" && node.hasChildNodes() && !n.node.isExpanded()){
25480            this.queueExpand(node);
25481        }else if(pt != "append"){
25482            this.cancelExpand();
25483        }
25484        
25485        // set the insert point style on the target node
25486        var returnCls = this.dropNotAllowed;
25487        if(this.isValidDropPoint(n, pt, dd, e, data)){
25488           if(pt){
25489               var el = n.ddel;
25490               var cls;
25491               if(pt == "above"){
25492                   returnCls = n.node.isFirst() ? "x-tree-drop-ok-above" : "x-tree-drop-ok-between";
25493                   cls = "x-tree-drag-insert-above";
25494               }else if(pt == "below"){
25495                   returnCls = n.node.isLast() ? "x-tree-drop-ok-below" : "x-tree-drop-ok-between";
25496                   cls = "x-tree-drag-insert-below";
25497               }else{
25498                   returnCls = "x-tree-drop-ok-append";
25499                   cls = "x-tree-drag-append";
25500               }
25501               if(this.lastInsertClass != cls){
25502                   Ext.fly(el).replaceClass(this.lastInsertClass, cls);
25503                   this.lastInsertClass = cls;
25504               }
25505           }
25506       }
25507       return returnCls;
25508    },
25509
25510    // private
25511    onNodeOut : function(n, dd, e, data){
25512        this.cancelExpand();
25513        this.removeDropIndicators(n);
25514    },
25515
25516    // private
25517    onNodeDrop : function(n, dd, e, data){
25518        var point = this.getDropPoint(e, n, dd);
25519        var targetNode = n.node;
25520        targetNode.ui.startDrop();
25521        if(!this.isValidDropPoint(n, point, dd, e, data)){
25522            targetNode.ui.endDrop();
25523            return false;
25524        }
25525        // first try to find the drop node
25526        var dropNode = data.node || (dd.getTreeNode ? dd.getTreeNode(data, targetNode, point, e) : null);
25527        var dropEvent = {
25528            tree : this.tree,
25529            target: targetNode,
25530            data: data,
25531            point: point,
25532            source: dd,
25533            rawEvent: e,
25534            dropNode: dropNode,
25535            cancel: !dropNode,
25536            dropStatus: false
25537        };
25538        var retval = this.tree.fireEvent("beforenodedrop", dropEvent);
25539        if(retval === false || dropEvent.cancel === true || !dropEvent.dropNode){
25540            targetNode.ui.endDrop();
25541            return dropEvent.dropStatus;
25542        }
25543        // allow target changing
25544        targetNode = dropEvent.target;
25545        if(point == "append" && !targetNode.isExpanded()){
25546            targetNode.expand(false, null, function(){
25547                this.completeDrop(dropEvent);
25548            }.createDelegate(this));
25549        }else{
25550            this.completeDrop(dropEvent);
25551        }
25552        return true;
25553    },
25554
25555    // private
25556    completeDrop : function(de){
25557        var ns = de.dropNode, p = de.point, t = de.target;
25558        if(!Ext.isArray(ns)){
25559            ns = [ns];
25560        }
25561        var n;
25562        for(var i = 0, len = ns.length; i < len; i++){
25563            n = ns[i];
25564            if(p == "above"){
25565                t.parentNode.insertBefore(n, t);
25566            }else if(p == "below"){
25567                t.parentNode.insertBefore(n, t.nextSibling);
25568            }else{
25569                t.appendChild(n);
25570            }
25571        }
25572        n.ui.focus();
25573        if(Ext.enableFx && this.tree.hlDrop){
25574            n.ui.highlight();
25575        }
25576        t.ui.endDrop();
25577        this.tree.fireEvent("nodedrop", de);
25578    },
25579
25580    // private
25581    afterNodeMoved : function(dd, data, e, targetNode, dropNode){
25582        if(Ext.enableFx && this.tree.hlDrop){
25583            dropNode.ui.focus();
25584            dropNode.ui.highlight();
25585        }
25586        this.tree.fireEvent("nodedrop", this.tree, targetNode, data, dd, e);
25587    },
25588
25589    // private
25590    getTree : function(){
25591        return this.tree;
25592    },
25593
25594    // private
25595    removeDropIndicators : function(n){
25596        if(n && n.ddel){
25597            var el = n.ddel;
25598            Ext.fly(el).removeClass([
25599                    "x-tree-drag-insert-above",
25600                    "x-tree-drag-insert-below",
25601                    "x-tree-drag-append"]);
25602            this.lastInsertClass = "_noclass";
25603        }
25604    },
25605
25606    // private
25607    beforeDragDrop : function(target, e, id){
25608        this.cancelExpand();
25609        return true;
25610    },
25611
25612    // private
25613    afterRepair : function(data){
25614        if(data && Ext.enableFx){
25615            data.node.ui.highlight();
25616        }
25617        this.hideProxy();
25618    }    
25619});
25620
25621}
25622
25623if(Ext.dd.DragZone){
25624Ext.tree.TreeDragZone = function(tree, config){
25625    Ext.tree.TreeDragZone.superclass.constructor.call(this, tree.getTreeEl(), config);
25626    
25627    this.tree = tree;
25628};
25629
25630Ext.extend(Ext.tree.TreeDragZone, Ext.dd.DragZone, {
25631    
25632    ddGroup : "TreeDD",
25633
25634    // private
25635    onBeforeDrag : function(data, e){
25636        var n = data.node;
25637        return n && n.draggable && !n.disabled;
25638    },
25639
25640    // private
25641    onInitDrag : function(e){
25642        var data = this.dragData;
25643        this.tree.getSelectionModel().select(data.node);
25644        this.tree.eventModel.disable();
25645        this.proxy.update("");
25646        data.node.ui.appendDDGhost(this.proxy.ghost.dom);
25647        this.tree.fireEvent("startdrag", this.tree, data.node, e);
25648    },
25649
25650    // private
25651    getRepairXY : function(e, data){
25652        return data.node.ui.getDDRepairXY();
25653    },
25654
25655    // private
25656    onEndDrag : function(data, e){
25657        this.tree.eventModel.enable.defer(100, this.tree.eventModel);
25658        this.tree.fireEvent("enddrag", this.tree, data.node, e);
25659    },
25660
25661    // private
25662    onValidDrop : function(dd, e, id){
25663        this.tree.fireEvent("dragdrop", this.tree, this.dragData.node, dd, e);
25664        this.hideProxy();
25665    },
25666
25667    // private
25668    beforeInvalidDrop : function(e, id){
25669        // this scrolls the original position back into view
25670        var sm = this.tree.getSelectionModel();
25671        sm.clearSelections();
25672        sm.select(this.dragData.node);
25673    },
25674    
25675    // private
25676    afterRepair : function(){
25677        if (Ext.enableFx && this.tree.hlDrop) {
25678            Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
25679        }
25680        this.dragging = false;
25681    }
25682});
25683}
25684
25685Ext.tree.TreeEditor = function(tree, fc, config){
25686    fc = fc || {};
25687    var field = fc.events ? fc : new Ext.form.TextField(fc);
25688    Ext.tree.TreeEditor.superclass.constructor.call(this, field, config);
25689
25690    this.tree = tree;
25691
25692    if(!tree.rendered){
25693        tree.on('render', this.initEditor, this);
25694    }else{
25695        this.initEditor(tree);
25696    }
25697};
25698
25699Ext.extend(Ext.tree.TreeEditor, Ext.Editor, {
25700    
25701    alignment: "l-l",
25702    // inherit
25703    autoSize: false,
25704    
25705    hideEl : false,
25706    
25707    cls: "x-small-editor x-tree-editor",
25708    
25709    shim:false,
25710    // inherit
25711    shadow:"frame",
25712    
25713    maxWidth: 250,
25714    
25715    editDelay : 350,
25716
25717    initEditor : function(tree){
25718        tree.on('beforeclick', this.beforeNodeClick, this);
25719        tree.on('dblclick', this.onNodeDblClick, this);
25720        this.on('complete', this.updateNode, this);
25721        this.on('beforestartedit', this.fitToTree, this);
25722        this.on('startedit', this.bindScroll, this, {delay:10});
25723        this.on('specialkey', this.onSpecialKey, this);
25724    },
25725
25726    // private
25727    fitToTree : function(ed, el){
25728        var td = this.tree.getTreeEl().dom, nd = el.dom;
25729        if(td.scrollLeft >  nd.offsetLeft){ // ensure the node left point is visible
25730            td.scrollLeft = nd.offsetLeft;
25731        }
25732        var w = Math.min(
25733                this.maxWidth,
25734                (td.clientWidth > 20 ? td.clientWidth : td.offsetWidth) - Math.max(0, nd.offsetLeft-td.scrollLeft) - 5);
25735        this.setSize(w, '');
25736    },
25737
25738    // private
25739    triggerEdit : function(node, defer){
25740        this.completeEdit();
25741		if(node.attributes.editable !== false){
25742	       
25743			this.editNode = node;
25744            if(this.tree.autoScroll){
25745                node.ui.getEl().scrollIntoView(this.tree.body);
25746            }
25747            this.autoEditTimer = this.startEdit.defer(this.editDelay, this, [node.ui.textNode, node.text]);
25748            return false;
25749        }
25750    },
25751
25752    // private
25753    bindScroll : function(){
25754        this.tree.getTreeEl().on('scroll', this.cancelEdit, this);
25755    },
25756
25757    // private
25758    beforeNodeClick : function(node, e){
25759        clearTimeout(this.autoEditTimer);
25760        if(this.tree.getSelectionModel().isSelected(node)){
25761            e.stopEvent();
25762            return this.triggerEdit(node);
25763        }
25764    },
25765
25766    onNodeDblClick : function(node, e){
25767        clearTimeout(this.autoEditTimer);
25768    },
25769
25770    // private
25771    updateNode : function(ed, value){
25772        this.tree.getTreeEl().un('scroll', this.cancelEdit, this);
25773        this.editNode.setText(value);
25774    },
25775
25776    // private
25777    onHide : function(){
25778        Ext.tree.TreeEditor.superclass.onHide.call(this);
25779        if(this.editNode){
25780            this.editNode.ui.focus.defer(50, this.editNode.ui);
25781        }
25782    },
25783
25784    // private
25785    onSpecialKey : function(field, e){
25786        var k = e.getKey();
25787        if(k == e.ESC){
25788            e.stopEvent();
25789            this.cancelEdit();
25790        }else if(k == e.ENTER && !e.hasModifier()){
25791            e.stopEvent();
25792            this.completeEdit();
25793        }
25794    }
25795});
25796
25797Ext.menu.Menu = function(config){
25798    if(Ext.isArray(config)){
25799        config = {items:config};
25800    }
25801    Ext.apply(this, config);
25802    this.id = this.id || Ext.id();
25803    this.addEvents(
25804        
25805        'beforeshow',
25806        
25807        'beforehide',
25808        
25809        'show',
25810        
25811        'hide',
25812        
25813        'click',
25814        
25815        'mouseover',
25816        
25817        'mouseout',
25818        
25819        'itemclick'
25820    );
25821    Ext.menu.MenuMgr.register(this);
25822    Ext.menu.Menu.superclass.constructor.call(this);
25823    var mis = this.items;
25824    
25825
25826    this.items = new Ext.util.MixedCollection();
25827    if(mis){
25828        this.add.apply(this, mis);
25829    }
25830};
25831
25832Ext.extend(Ext.menu.Menu, Ext.util.Observable, {
25833    
25834    
25835    
25836    minWidth : 120,
25837    
25838    shadow : "sides",
25839    
25840    subMenuAlign : "tl-tr?",
25841    
25842    defaultAlign : "tl-bl?",
25843    
25844    allowOtherMenus : false,
25845    
25846    ignoreParentClicks : false,
25847
25848    // private
25849    hidden:true,
25850
25851    // private
25852    createEl : function(){
25853        return new Ext.Layer({
25854            cls: "x-menu",
25855            shadow:this.shadow,
25856            constrain: false,
25857            parentEl: this.parentEl || document.body,
25858            zindex:15000
25859        });
25860    },
25861
25862    // private
25863    render : function(){
25864        if(this.el){
25865            return;
25866        }
25867        var el = this.el = this.createEl();
25868
25869        if(!this.keyNav){
25870            this.keyNav = new Ext.menu.MenuNav(this);
25871        }
25872        if(this.plain){
25873            el.addClass("x-menu-plain");
25874        }
25875        if(this.cls){
25876            el.addClass(this.cls);
25877        }
25878        // generic focus element
25879        this.focusEl = el.createChild({
25880            tag: "a", cls: "x-menu-focus", href: "#", onclick: "return false;", tabIndex:"-1"
25881        });
25882        var ul = el.createChild({tag: "ul", cls: "x-menu-list"});
25883        ul.on("click", this.onClick, this);
25884        ul.on("mouseover", this.onMouseOver, this);
25885        ul.on("mouseout", this.onMouseOut, this);
25886        this.items.each(function(item){
25887            var li = document.createElement("li");
25888            li.className = "x-menu-list-item";
25889            ul.dom.appendChild(li);
25890            item.render(li, this);
25891        }, this);
25892        this.ul = ul;
25893        this.autoWidth();
25894    },
25895
25896    // private
25897    autoWidth : function(){
25898        var el = this.el, ul = this.ul;
25899        if(!el){
25900            return;
25901        }
25902        var w = this.width;
25903        if(w){
25904            el.setWidth(w);
25905        }else if(Ext.isIE){
25906            el.setWidth(this.minWidth);
25907            var t = el.dom.offsetWidth; // force recalc
25908            el.setWidth(ul.getWidth()+el.getFrameWidth("lr"));
25909        }
25910    },
25911
25912    // private
25913    delayAutoWidth : function(){
25914        if(this.el){
25915            if(!this.awTask){
25916                this.awTask = new Ext.util.DelayedTask(this.autoWidth, this);
25917            }
25918            this.awTask.delay(20);
25919        }
25920    },
25921
25922    // private
25923    findTargetItem : function(e){
25924        var t = e.getTarget(".x-menu-list-item", this.ul,  true);
25925        if(t && t.menuItemId){
25926            return this.items.get(t.menuItemId);
25927        }
25928    },
25929
25930    // private
25931    onClick : function(e){
25932        var t;
25933        if(t = this.findTargetItem(e)){
25934            if(t.menu && this.ignoreParentClicks){
25935                t.expandMenu();
25936            }else{
25937                t.onClick(e);
25938                this.fireEvent("click", this, t, e);
25939            }
25940        }
25941    },
25942
25943    // private
25944    setActiveItem : function(item, autoExpand){
25945        if(item != this.activeItem){
25946            if(this.activeItem){
25947                this.activeItem.deactivate();
25948            }
25949            this.activeItem = item;
25950            item.activate(autoExpand);
25951        }else if(autoExpand){
25952            item.expandMenu();
25953        }
25954    },
25955
25956    // private
25957    tryActivate : function(start, step){
25958        var items = this.items;
25959        for(var i = start, len = items.length; i >= 0 && i < len; i+= step){
25960            var item = items.get(i);
25961            if(!item.disabled && item.canActivate){
25962                this.setActiveItem(item, false);
25963                return item;
25964            }
25965        }
25966        return false;
25967    },
25968
25969    // private
25970    onMouseOver : function(e){
25971        var t;
25972        if(t = this.findTargetItem(e)){
25973            if(t.canActivate && !t.disabled){
25974                this.setActiveItem(t, true);
25975            }
25976        }
25977        this.over = true;
25978        this.fireEvent("mouseover", this, e, t);
25979    },
25980
25981    // private
25982    onMouseOut : function(e){
25983        var t;
25984        if(t = this.findTargetItem(e)){
25985            if(t == this.activeItem && t.shouldDeactivate(e)){
25986                this.activeItem.deactivate();
25987                delete this.activeItem;
25988            }
25989        }
25990        this.over = false;
25991        this.fireEvent("mouseout", this, e, t);
25992    },
25993
25994    
25995    isVisible : function(){
25996        return this.el && !this.hidden;
25997    },
25998
25999    
26000    show : function(el, pos, parentMenu){
26001        this.parentMenu = parentMenu;
26002        if(!this.el){
26003            this.render();
26004        }
26005        this.fireEvent("beforeshow", this);
26006        this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign), parentMenu, false);
26007    },
26008
26009    
26010    showAt : function(xy, parentMenu, _e){
26011        this.parentMenu = parentMenu;
26012        if(!this.el){
26013            this.render();
26014        }
26015        if(_e !== false){
26016            this.fireEvent("beforeshow", this);
26017            xy = this.el.adjustForConstraints(xy);
26018        }
26019        this.el.setXY(xy);
26020        this.el.show();
26021        this.hidden = false;
26022        this.focus();
26023        this.fireEvent("show", this);
26024    },
26025
26026
26027
26028    focus : function(){
26029        if(!this.hidden){
26030            this.doFocus.defer(50, this);
26031        }
26032    },
26033
26034    doFocus : function(){
26035        if(!this.hidden){
26036            this.focusEl.focus();
26037        }
26038    },
26039
26040    
26041    hide : function(deep){
26042        if(this.el && this.isVisible()){
26043            this.fireEvent("beforehide", this);
26044            if(this.activeItem){
26045                this.activeItem.deactivate();
26046                this.activeItem = null;
26047            }
26048            this.el.hide();
26049            this.hidden = true;
26050            this.fireEvent("hide", this);
26051        }
26052        if(deep === true && this.parentMenu){
26053            this.parentMenu.hide(true);
26054        }
26055    },
26056
26057    
26058    add : function(){
26059        var a = arguments, l = a.length, item;
26060        for(var i = 0; i < l; i++){
26061            var el = a[i];
26062            if(el.render){ // some kind of Item
26063                item = this.addItem(el);
26064            }else if(typeof el == "string"){ // string
26065                if(el == "separator" || el == "-"){
26066                    item = this.addSeparator();
26067                }else{
26068                    item = this.addText(el);
26069                }
26070            }else if(el.tagName || el.el){ // element
26071                item = this.addElement(el);
26072            }else if(typeof el == "object"){ // must be menu item config?
26073                Ext.applyIf(el, this.defaults);
26074                item = this.addMenuItem(el);
26075            }
26076        }
26077        return item;
26078    },
26079
26080    
26081    getEl : function(){
26082        if(!this.el){
26083            this.render();
26084        }
26085        return this.el;
26086    },
26087
26088    
26089    addSeparator : function(){
26090        return this.addItem(new Ext.menu.Separator());
26091    },
26092
26093    
26094    addElement : function(el){
26095        return this.addItem(new Ext.menu.BaseItem(el));
26096    },
26097
26098    
26099    addItem : function(item){
26100        this.items.add(item);
26101        if(this.ul){
26102            var li = document.createElement("li");
26103            li.className = "x-menu-list-item";
26104            this.ul.dom.appendChild(li);
26105            item.render(li, this);
26106            this.delayAutoWidth();
26107        }
26108        return item;
26109    },
26110
26111    
26112    addMenuItem : function(config){
26113        if(!(config instanceof Ext.menu.Item)){
26114            if(typeof config.checked == "boolean"){ // must be check menu item config?
26115                config = new Ext.menu.CheckItem(config);
26116            }else{
26117                config = new Ext.menu.Item(config);
26118            }
26119        }
26120        return this.addItem(config);
26121    },
26122
26123    
26124    addText : function(text){
26125        return this.addItem(new Ext.menu.TextItem(text));
26126    },
26127
26128    
26129    insert : function(index, item){
26130        this.items.insert(index, item);
26131        if(this.ul){
26132            var li = document.createElement("li");
26133            li.className = "x-menu-list-item";
26134            this.ul.dom.insertBefore(li, this.ul.dom.childNodes[index]);
26135            item.render(li, this);
26136            this.delayAutoWidth();
26137        }
26138        return item;
26139    },
26140
26141    
26142    remove : function(item){
26143        this.items.removeKey(item.id);
26144        item.destroy();
26145    },
26146
26147    
26148    removeAll : function(){
26149    	if(this.items){
26150	        var f;
26151	        while(f = this.items.first()){
26152	            this.remove(f);
26153	        }
26154    	}
26155    },
26156
26157    
26158    destroy : function(){
26159        this.beforeDestroy();
26160        Ext.menu.MenuMgr.unregister(this);
26161        if (this.keyNav) {
26162        	this.keyNav.disable();
26163        }
26164        this.removeAll();
26165        if (this.ul) {
26166        	this.ul.removeAllListeners();
26167        }
26168        if (this.el) {
26169        	this.el.destroy();
26170        }
26171    },
26172
26173	// private
26174    beforeDestroy : Ext.emptyFn
26175
26176});
26177
26178// MenuNav is a private utility class used internally by the Menu
26179Ext.menu.MenuNav = function(menu){
26180    Ext.menu.MenuNav.superclass.constructor.call(this, menu.el);
26181    this.scope = this.menu = menu;
26182};
26183
26184Ext.extend(Ext.menu.MenuNav, Ext.KeyNav, {
26185    doRelay : function(e, h){
26186        var k = e.getKey();
26187        if(!this.menu.activeItem && e.isNavKeyPress() && k != e.SPACE && k != e.RETURN){
26188            this.menu.tryActivate(0, 1);
26189            return false;
26190        }
26191        return h.call(this.scope || this, e, this.menu);
26192    },
26193
26194    up : function(e, m){
26195        if(!m.tryActivate(m.items.indexOf(m.activeItem)-1, -1)){
26196            m.tryActivate(m.items.length-1, -1);
26197        }
26198    },
26199
26200    down : function(e, m){
26201        if(!m.tryActivate(m.items.indexOf(m.activeItem)+1, 1)){
26202            m.tryActivate(0, 1);
26203        }
26204    },
26205
26206    right : function(e, m){
26207        if(m.activeItem){
26208            m.activeItem.expandMenu(true);
26209        }
26210    },
26211
26212    left : function(e, m){
26213        m.hide();
26214        if(m.parentMenu && m.parentMenu.activeItem){
26215            m.parentMenu.activeItem.activate();
26216        }
26217    },
26218
26219    enter : function(e, m){
26220        if(m.activeItem){
26221            e.stopPropagation();
26222            m.activeItem.onClick(e);
26223            m.fireEvent("click", this, m.activeItem);
26224            return true;
26225        }
26226    }
26227});
26228
26229Ext.menu.MenuMgr = function(){
26230   var menus, active, groups = {}, attached = false, lastShow = new Date();
26231
26232   // private - called when first menu is created
26233   function init(){
26234       menus = {};
26235       active = new Ext.util.MixedCollection();
26236       Ext.getDoc().addKeyListener(27, function(){
26237           if(active.length > 0){
26238               hideAll();
26239           }
26240       });
26241   }
26242
26243   // private
26244   function hideAll(){
26245       if(active && active.length > 0){
26246           var c = active.clone();
26247           c.each(function(m){
26248               m.hide();
26249           });
26250       }
26251   }
26252
26253   // private
26254   function onHide(m){
26255       active.remove(m);
26256       if(active.length < 1){
26257           Ext.getDoc().un("mousedown", onMouseDown);
26258           attached = false;
26259       }
26260   }
26261
26262   // private
26263   function onShow(m){
26264       var last = active.last();
26265       lastShow = new Date();
26266       active.add(m);
26267       if(!attached){
26268           Ext.getDoc().on("mousedown", onMouseDown);
26269           attached = true;
26270       }
26271       if(m.parentMenu){
26272          m.getEl().setZIndex(parseInt(m.parentMenu.getEl().getStyle("z-index"), 10) + 3);
26273          m.parentMenu.activeChild = m;
26274       }else if(last && last.isVisible()){
26275          m.getEl().setZIndex(parseInt(last.getEl().getStyle("z-index"), 10) + 3);
26276       }
26277   }
26278
26279   // private
26280   function onBeforeHide(m){
26281       if(m.activeChild){
26282           m.activeChild.hide();
26283       }
26284       if(m.autoHideTimer){
26285           clearTimeout(m.autoHideTimer);
26286           delete m.autoHideTimer;
26287       }
26288   }
26289
26290   // private
26291   function onBeforeShow(m){
26292       var pm = m.parentMenu;
26293       if(!pm && !m.allowOtherMenus){
26294           hideAll();
26295       }else if(pm && pm.activeChild){
26296           pm.activeChild.hide();
26297       }
26298   }
26299
26300   // private
26301   function onMouseDown(e){
26302       if(lastShow.getElapsed() > 50 && active.length > 0 && !e.getTarget(".x-menu")){
26303           hideAll();
26304       }
26305   }
26306
26307   // private
26308   function onBeforeCheck(mi, state){
26309       if(state){
26310           var g = groups[mi.group];
26311           for(var i = 0, l = g.length; i < l; i++){
26312               if(g[i] != mi){
26313                   g[i].setChecked(false);
26314               }
26315           }
26316       }
26317   }
26318
26319   return {
26320
26321       
26322       hideAll : function(){
26323            hideAll();  
26324       },
26325
26326       // private
26327       register : function(menu){
26328           if(!menus){
26329               init();
26330           }
26331           menus[menu.id] = menu;
26332           menu.on("beforehide", onBeforeHide);
26333           menu.on("hide", onHide);
26334           menu.on("beforeshow", onBeforeShow);
26335           menu.on("show", onShow);
26336           var g = menu.group;
26337           if(g && menu.events["checkchange"]){
26338               if(!groups[g]){
26339                   groups[g] = [];
26340               }
26341               groups[g].push(menu);
26342               menu.on("checkchange", onCheck);
26343           }
26344       },
26345
26346        
26347       get : function(menu){
26348           if(typeof menu == "string"){ // menu id
26349               if(!menus){  // not initialized, no menus to return
26350                   return null;
26351               }
26352               return menus[menu];
26353           }else if(menu.events){  // menu instance
26354               return menu;
26355           }else if(typeof menu.length == 'number'){ // array of menu items?
26356               return new Ext.menu.Menu({items:menu});
26357           }else{ // otherwise, must be a config
26358               return new Ext.menu.Menu(menu);
26359           }
26360       },
26361
26362       // private
26363       unregister : function(menu){
26364           delete menus[menu.id];
26365           menu.un("beforehide", onBeforeHide);
26366           menu.un("hide", onHide);
26367           menu.un("beforeshow", onBeforeShow);
26368           menu.un("show", onShow);
26369           var g = menu.group;
26370           if(g && menu.events["checkchange"]){
26371               groups[g].remove(menu);
26372               menu.un("checkchange", onCheck);
26373           }
26374       },
26375
26376       // private
26377       registerCheckable : function(menuItem){
26378           var g = menuItem.group;
26379           if(g){
26380               if(!groups[g]){
26381                   groups[g] = [];
26382               }
26383               groups[g].push(menuItem);
26384               menuItem.on("beforecheckchange", onBeforeCheck);
26385           }
26386       },
26387
26388       // private
26389       unregisterCheckable : function(menuItem){
26390           var g = menuItem.group;
26391           if(g){
26392               groups[g].remove(menuItem);
26393               menuItem.un("beforecheckchange", onBeforeCheck);
26394           }
26395       },
26396
26397       getCheckedItem : function(groupId){
26398           var g = groups[groupId];
26399           if(g){
26400               for(var i = 0, l = g.length; i < l; i++){
26401                   if(g[i].checked){
26402                       return g[i];
26403                   }
26404               }
26405           }
26406           return null;
26407       },
26408
26409       setCheckedItem : function(groupId, itemId){
26410           var g = groups[groupId];
26411           if(g){
26412               for(var i = 0, l = g.length; i < l; i++){
26413                   if(g[i].id == itemId){
26414                       g[i].setChecked(true);
26415                   }
26416               }
26417           }
26418           return null;
26419       }
26420   };
26421}();
26422
26423
26424Ext.menu.BaseItem = function(config){
26425    Ext.menu.BaseItem.superclass.constructor.call(this, config);
26426
26427    this.addEvents(
26428        
26429        'click',
26430        
26431        'activate',
26432        
26433        'deactivate'
26434    );
26435
26436    if(this.handler){
26437        this.on("click", this.handler, this.scope);
26438    }
26439};
26440
26441Ext.extend(Ext.menu.BaseItem, Ext.Component, {
26442    
26443    
26444    
26445    canActivate : false,
26446    
26447    activeClass : "x-menu-item-active",
26448    
26449    hideOnClick : true,
26450    
26451    hideDelay : 100,
26452
26453    // private
26454    ctype: "Ext.menu.BaseItem",
26455
26456    // private
26457    actionMode : "container",
26458
26459    // private
26460    render : function(container, parentMenu){
26461        
26462        this.parentMenu = parentMenu;
26463        Ext.menu.BaseItem.superclass.render.call(this, container);
26464        this.container.menuItemId = this.id;
26465    },
26466
26467    // private
26468    onRender : function(container, position){
26469        this.el = Ext.get(this.el);
26470        if(this.id){
26471            this.el.id = this.id;
26472        }
26473        container.dom.appendChild(this.el.dom);
26474    },
26475
26476    
26477    setHandler : function(handler, scope){
26478        if(this.handler){
26479            this.un("click", this.handler, this.scope);
26480        }
26481        this.on("click", this.handler = handler, this.scope = scope);
26482    },
26483
26484    // private
26485    onClick : function(e){
26486        if(!this.disabled && this.fireEvent("click", this, e) !== false
26487                && this.parentMenu.fireEvent("itemclick", this, e) !== false){
26488            this.handleClick(e);
26489        }else{
26490            e.stopEvent();
26491        }
26492    },
26493
26494    // private
26495    activate : function(){
26496        if(this.disabled){
26497            return false;
26498        }
26499        var li = this.container;
26500        li.addClass(this.activeClass);
26501        this.region = li.getRegion().adjust(2, 2, -2, -2);
26502        this.fireEvent("activate", this);
26503        return true;
26504    },
26505
26506    // private
26507    deactivate : function(){
26508        this.container.removeClass(this.activeClass);
26509        this.fireEvent("deactivate", this);
26510    },
26511
26512    // private
26513    shouldDeactivate : function(e){
26514        return !this.region || !this.region.contains(e.getPoint());
26515    },
26516
26517    // private
26518    handleClick : function(e){
26519        if(this.hideOnClick){
26520            this.parentMenu.hide.defer(this.hideDelay, this.parentMenu, [true]);
26521        }
26522    },
26523
26524    // private
26525    expandMenu : function(autoActivate){
26526        // do nothing
26527    },
26528
26529    // private
26530    hideMenu : function(){
26531        // do nothing
26532    }
26533});
26534
26535Ext.menu.TextItem = function(cfg){
26536    if(typeof cfg == 'string'){
26537        cfg = {text: cfg}
26538    }
26539    Ext.menu.TextItem.superclass.constructor.call(this, cfg);
26540};
26541
26542Ext.extend(Ext.menu.TextItem, Ext.menu.BaseItem, {
26543    
26544    
26545    hideOnClick : false,
26546    
26547    itemCls : "x-menu-text",
26548
26549    // private
26550    onRender : function(){
26551        var s = document.createElement("span");
26552        s.className = this.itemCls;
26553        s.innerHTML = this.text;
26554        this.el = s;
26555        Ext.menu.TextItem.superclass.onRender.apply(this, arguments);
26556    }
26557});
26558
26559Ext.menu.Separator = function(config){
26560    Ext.menu.Separator.superclass.constructor.call(this, config);
26561};
26562
26563Ext.extend(Ext.menu.Separator, Ext.menu.BaseItem, {
26564    
26565    itemCls : "x-menu-sep",
26566    
26567    hideOnClick : false,
26568
26569    // private
26570    onRender : function(li){
26571        var s = document.createElement("span");
26572        s.className = this.itemCls;
26573        s.innerHTML = "&#160;";
26574        this.el = s;
26575        li.addClass("x-menu-sep-li");
26576        Ext.menu.Separator.superclass.onRender.apply(this, arguments);
26577    }
26578});
26579
26580Ext.menu.Item = function(config){
26581    Ext.menu.Item.superclass.constructor.call(this, config);
26582    if(this.menu){
26583        this.menu = Ext.menu.MenuMgr.get(this.menu);
26584    }
26585};
26586Ext.extend(Ext.menu.Item, Ext.menu.BaseItem, {
26587    
26588    
26589    
26590    
26591    
26592    
26593    
26594    itemCls : "x-menu-item",
26595    
26596    canActivate : true,
26597    
26598    showDelay: 200,
26599    // doc'd in BaseItem
26600    hideDelay: 200,
26601
26602    // private
26603    ctype: "Ext.menu.Item",
26604
26605    // private
26606    onRender : function(container, position){
26607        var el = document.createElement("a");
26608        el.hideFocus = true;
26609        el.unselectable = "on";
26610        el.href = this.href || "#";
26611        if(this.hrefTarget){
26612            el.target = this.hrefTarget;
26613        }
26614        el.className = this.itemCls + (this.menu ?  " x-menu-item-arrow" : "") + (this.cls ?  " " + this.cls : "");
26615        el.innerHTML = String.format(
26616                '<img src="{0}" class="x-menu-item-icon {2}" />{1}',
26617                this.icon || Ext.BLANK_IMAGE_URL, this.itemText||this.text, this.iconCls || '');
26618        this.el = el;
26619        Ext.menu.Item.superclass.onRender.call(this, container, position);
26620    },
26621
26622    
26623    setText : function(text){
26624        this.text = text;
26625        if(this.rendered){
26626            this.el.update(String.format(
26627                '<img src="{0}" class="x-menu-item-icon {2}">{1}',
26628                this.icon || Ext.BLANK_IMAGE_URL, this.text, this.iconCls || ''));
26629            this.parentMenu.autoWidth();
26630        }
26631    },
26632
26633    
26634    setIconClass : function(cls){
26635        var oldCls = this.iconCls;
26636        this.iconCls = cls;
26637        if(this.rendered){
26638            this.el.child('img.x-menu-item-icon').replaceClass(oldCls, this.iconCls);
26639        }
26640    },
26641    
26642    //private
26643    beforeDestroy: function(){
26644        if (this.menu){
26645            this.menu.destroy();
26646        }
26647        Ext.menu.Item.superclass.beforeDestroy.call(this);
26648    },
26649
26650    // private
26651    handleClick : function(e){
26652        if(!this.href){ // if no link defined, stop the event automatically
26653            e.stopEvent();
26654        }
26655        Ext.menu.Item.superclass.handleClick.apply(this, arguments);
26656    },
26657
26658    // private
26659    activate : function(autoExpand){
26660        if(Ext.menu.Item.superclass.activate.apply(this, arguments)){
26661            this.focus();
26662            if(autoExpand){
26663                this.expandMenu();
26664            }
26665        }
26666        return true;
26667    },
26668
26669    // private
26670    shouldDeactivate : function(e){
26671        if(Ext.menu.Item.superclass.shouldDeactivate.call(this, e)){
26672            if(this.menu && this.menu.isVisible()){
26673                return !this.menu.getEl().getRegion().contains(e.getPoint());
26674            }
26675            return true;
26676        }
26677        return false;
26678    },
26679
26680    // private
26681    deactivate : function(){
26682        Ext.menu.Item.superclass.deactivate.apply(this, arguments);
26683        this.hideMenu();
26684    },
26685
26686    // private
26687    expandMenu : function(autoActivate){
26688        if(!this.disabled && this.menu){
26689            clearTimeout(this.hideTimer);
26690            delete this.hideTimer;
26691            if(!this.menu.isVisible() && !this.showTimer){
26692                this.showTimer = this.deferExpand.defer(this.showDelay, this, [autoActivate]);
26693            }else if (this.menu.isVisible() && autoActivate){
26694                this.menu.tryActivate(0, 1);
26695            }
26696        }
26697    },
26698
26699    // private
26700    deferExpand : function(autoActivate){
26701        delete this.showTimer;
26702        this.menu.show(this.container, this.parentMenu.subMenuAlign || "tl-tr?", this.parentMenu);
26703        if(autoActivate){
26704            this.menu.tryActivate(0, 1);
26705        }
26706    },
26707
26708    // private
26709    hideMenu : function(){
26710        clearTimeout(this.showTimer);
26711        delete this.showTimer;
26712        if(!this.hideTimer && this.menu && this.menu.isVisible()){
26713            this.hideTimer = this.deferHide.defer(this.hideDelay, this);
26714        }
26715    },
26716
26717    // private
26718    deferHide : function(){
26719        delete this.hideTimer;
26720        if(this.menu.over){
26721            this.parentMenu.setActiveItem(this, false);
26722        }else{
26723            this.menu.hide();
26724        }
26725    }
26726});
26727
26728Ext.menu.CheckItem = function(config){
26729    Ext.menu.CheckItem.superclass.constructor.call(this, config);
26730    this.addEvents(
26731        
26732        "beforecheckchange" ,
26733        
26734        "checkchange"
26735    );
26736    
26737    if(this.checkHandler){
26738        this.on('checkchange', this.checkHandler, this.scope);
26739    }
26740    Ext.menu.MenuMgr.registerCheckable(this);
26741};
26742Ext.extend(Ext.menu.CheckItem, Ext.menu.Item, {
26743    
26744    
26745    itemCls : "x-menu-item x-menu-check-item",
26746    
26747    groupClass : "x-menu-group-item",
26748
26749    
26750    checked: false,
26751
26752    // private
26753    ctype: "Ext.menu.CheckItem",
26754
26755    // private
26756    onRender : function(c){
26757        Ext.menu.CheckItem.superclass.onRender.apply(this, arguments);
26758        if(this.group){
26759            this.el.addClass(this.groupClass);
26760        }
26761        if(this.checked){
26762            this.checked = false;
26763            this.setChecked(true, true);
26764        }
26765    },
26766
26767    // private
26768    destroy : function(){
26769        Ext.menu.MenuMgr.unregisterCheckable(this);
26770        Ext.menu.CheckItem.superclass.destroy.apply(this, arguments);
26771    },
26772
26773    
26774    setChecked : function(state, suppressEvent){
26775        if(this.checked != state && this.fireEvent("beforecheckchange", this, state) !== false){
26776            if(this.container){
26777                this.container[state ? "addClass" : "removeClass"]("x-menu-item-checked");
26778            }
26779            this.checked = state;
26780            if(suppressEvent !== true){
26781                this.fireEvent("checkchange", this, state);
26782            }
26783        }
26784    },
26785
26786    // private
26787    handleClick : function(e){
26788       if(!this.disabled && !(this.checked && this.group)){// disable unselect on radio item
26789           this.setChecked(!this.checked);
26790       }
26791       Ext.menu.CheckItem.superclass.handleClick.apply(this, arguments);
26792    }
26793});
26794
26795Ext.menu.Adapter = function(component, config){
26796    Ext.menu.Adapter.superclass.constructor.call(this, config);
26797    this.component = component;
26798};
26799Ext.extend(Ext.menu.Adapter, Ext.menu.BaseItem, {
26800    // private
26801    canActivate : true,
26802
26803    // private
26804    onRender : function(container, position){
26805        this.component.render(container);
26806        this.el = this.component.getEl();
26807    },
26808
26809    // private
26810    activate : function(){
26811        if(this.disabled){
26812            return false;
26813        }
26814        this.component.focus();
26815        this.fireEvent("activate", this);
26816        return true;
26817    },
26818
26819    // private
26820    deactivate : function(){
26821        this.fireEvent("deactivate", this);
26822    },
26823
26824    // private
26825    disable : function(){
26826        this.component.disable();
26827        Ext.menu.Adapter.superclass.disable.call(this);
26828    },
26829
26830    // private
26831    enable : function(){
26832        this.component.enable();
26833        Ext.menu.Adapter.superclass.enable.call(this);
26834    }
26835});
26836
26837Ext.menu.DateItem = function(config){
26838    Ext.menu.DateItem.superclass.constructor.call(this, new Ext.DatePicker(config), config);
26839    
26840    this.picker = this.component;
26841    this.addEvents('select');
26842    
26843    this.picker.on("render", function(picker){
26844        picker.getEl().swallowEvent("click");
26845        picker.container.addClass("x-menu-date-item");
26846    });
26847
26848    this.picker.on("select", this.onSelect, this);
26849};
26850
26851Ext.extend(Ext.menu.DateItem, Ext.menu.Adapter, {
26852    // private
26853    onSelect : function(picker, date){
26854        this.fireEvent("select", this, date, picker);
26855        Ext.menu.DateItem.superclass.handleClick.call(this);
26856    }
26857});
26858
26859Ext.menu.ColorItem = function(config){
26860    Ext.menu.ColorItem.superclass.constructor.call(this, new Ext.ColorPalette(config), config);
26861    
26862    this.palette = this.component;
26863    this.relayEvents(this.palette, ["select"]);
26864    if(this.selectHandler){
26865        this.on('select', this.selectHandler, this.scope);
26866    }
26867};
26868Ext.extend(Ext.menu.ColorItem, Ext.menu.Adapter);
26869
26870Ext.menu.DateMenu = function(config){
26871    Ext.menu.DateMenu.superclass.constructor.call(this, config);
26872    this.plain = true;
26873    var di = new Ext.menu.DateItem(config);
26874    this.add(di);
26875    
26876    this.picker = di.picker;
26877    
26878    this.relayEvents(di, ["select"]);
26879
26880    this.on('beforeshow', function(){
26881        if(this.picker){
26882            this.picker.hideMonthPicker(true);
26883        }
26884    }, this);
26885};
26886Ext.extend(Ext.menu.DateMenu, Ext.menu.Menu, {
26887    cls:'x-date-menu',
26888
26889    // private
26890    beforeDestroy : function() {
26891        this.picker.destroy();
26892    }
26893});
26894
26895Ext.menu.ColorMenu = function(config){
26896    Ext.menu.ColorMenu.superclass.constructor.call(this, config);
26897    this.plain = true;
26898    var ci = new Ext.menu.ColorItem(config);
26899    this.add(ci);
26900    
26901    this.palette = ci.palette;
26902    
26903    this.relayEvents(ci, ["select"]);
26904};
26905Ext.extend(Ext.menu.ColorMenu, Ext.menu.Menu, {
26906    //private
26907    beforeDestroy: function(){
26908        this.palette.destroy();
26909    }
26910});
26911
26912Ext.form.Field = Ext.extend(Ext.BoxComponent,  {
26913    
26914    
26915    
26916    
26917    
26918    
26919    
26920    
26921    
26922    
26923    
26924
26925    
26926    invalidClass : "x-form-invalid",
26927    
26928    invalidText : "O valor neste campo é inválido",
26929    
26930    focusClass : "x-form-focus",
26931    
26932    validationEvent : "keyup",
26933    
26934    validateOnBlur : true,
26935    
26936    validationDelay : 250,
26937    
26938    defaultAutoCreate : {tag: "input", type: "text", size: "20", autocomplete: "off"},
26939    
26940    fieldClass : "x-form-field",
26941    
26942    msgTarget : 'qtip',
26943    
26944    msgFx : 'normal',
26945    
26946    readOnly : false,
26947    
26948    disabled : false,
26949
26950    // private
26951    isFormField : true,
26952
26953    // private
26954    hasFocus : false,
26955
26956	// private
26957	initComponent : function(){
26958        Ext.form.Field.superclass.initComponent.call(this);
26959        this.addEvents(
26960            
26961            'focus',
26962            
26963            'blur',
26964            
26965            'specialkey',
26966            
26967            'change',
26968            
26969            'invalid',
26970            
26971            'valid'
26972        );
26973    },
26974
26975    
26976    getName: function(){
26977         return this.rendered && this.el.dom.name ? this.el.dom.name : (this.hiddenName || '');
26978    },
26979
26980    // private
26981    onRender : function(ct, position){
26982        Ext.form.Field.superclass.onRender.call(this, ct, position);
26983        if(!this.el){
26984            var cfg = this.getAutoCreate();
26985            if(!cfg.name){
26986                cfg.name = this.name || this.id;
26987            }
26988            if(this.inputType){
26989                cfg.type = this.inputType;
26990            }
26991            this.el = ct.createChild(cfg, position);
26992        }
26993        var type = this.el.dom.type;
26994        if(type){
26995            if(type == 'password'){
26996                type = 'text';
26997            }
26998            this.el.addClass('x-form-'+type);
26999        }
27000        if(this.readOnly){
27001            this.el.dom.readOnly = true;
27002        }
27003        if(this.tabIndex !== undefined){
27004            this.el.dom.setAttribute('tabIndex', this.tabIndex);
27005        }
27006
27007        this.el.addClass([this.fieldClass, this.cls]);
27008    },
27009
27010    // private
27011    initValue : function(){
27012        if(this.value !== undefined){
27013            this.setValue(this.value);
27014        }else if(this.el.dom.value.length > 0 && this.el.dom.value != this.emptyText){
27015            this.setValue(this.el.dom.value);
27016        }
27017        // reference to original value for reset
27018        this.originalValue = this.getValue();
27019    },
27020
27021    
27022    isDirty : function() {
27023        if(this.disabled) {
27024            return false;
27025        }
27026        return String(this.getValue()) !== String(this.originalValue);
27027    },
27028
27029    // private
27030    afterRender : function(){
27031        Ext.form.Field.superclass.afterRender.call(this);
27032        this.initEvents();
27033        this.initValue();
27034    },
27035
27036    // private
27037    fireKey : function(e){
27038        if(e.isSpecialKey()){
27039            this.fireEvent("specialkey", this, e);
27040        }
27041    },
27042
27043    
27044    reset : function(){
27045        this.setValue(this.originalValue);
27046        this.clearInvalid();
27047    },
27048
27049    // private
27050    initEvents : function(){
27051        this.el.on(Ext.isIE || Ext.isSafari3 ? "keydown" : "keypress", this.fireKey,  this);
27052        this.el.on("focus", this.onFocus,  this);
27053
27054        // fix weird FF/Win editor issue when changing OS window focus
27055        var o = this.inEditor && Ext.isWindows && Ext.isGecko ? {buffer:10} : null;
27056        this.el.on("blur", this.onBlur,  this, o);
27057    },
27058
27059    // private
27060    onFocus : function(){
27061        if(this.focusClass){
27062            this.el.addClass(this.focusClass);
27063        }
27064        if(!this.hasFocus){
27065            this.hasFocus = true;
27066            this.startValue = this.getValue();
27067            this.fireEvent("focus", this);
27068        }
27069    },
27070
27071    // private
27072    beforeBlur : Ext.emptyFn,
27073
27074    // private
27075    onBlur : function(){
27076        this.beforeBlur();
27077        if(this.focusClass){
27078            this.el.removeClass(this.focusClass);
27079        }
27080        this.hasFocus = false;
27081        if(this.validationEvent !== false && this.validateOnBlur && this.validationEvent != "blur"){
27082            this.validate();
27083        }
27084        var v = this.getValue();
27085        if(String(v) !== String(this.startValue)){
27086            this.fireEvent('change', this, v, this.startValue);
27087        }
27088        this.fireEvent("blur", this);
27089    },
27090
27091    
27092    isValid : function(preventMark){
27093        if(this.disabled){
27094            return true;
27095        }
27096        var restore = this.preventMark;
27097        this.preventMark = preventMark === true;
27098        var v = this.validateValue(this.processValue(this.getRawValue()));
27099        this.preventMark = restore;
27100        return v;
27101    },
27102
27103    
27104    validate : function(){
27105        if(this.disabled || this.validateValue(this.processValue(this.getRawValue()))){
27106            this.clearInvalid();
27107            return true;
27108        }
27109        return false;
27110    },
27111
27112    // protected - should be overridden by subclasses if necessary to prepare raw values for validation
27113    processValue : function(value){
27114        return value;
27115    },
27116
27117    // private
27118    // Subclasses should provide the validation implementation by overriding this
27119    validateValue : function(value){
27120        return true;
27121    },
27122
27123    
27124    markInvalid : function(msg){
27125        if(!this.rendered || this.preventMark){ // not rendered
27126            return;
27127        }
27128        this.el.addClass(this.invalidClass);
27129        msg = msg || this.invalidText;
27130
27131        switch(this.msgTarget){
27132            case 'qtip':
27133                this.el.dom.qtip = msg;
27134                this.el.dom.qclass = 'x-form-invalid-tip';
27135                if(Ext.QuickTips){ // fix for floating editors interacting with DND
27136                    Ext.QuickTips.enable();
27137                }
27138                break;
27139            case 'title':
27140                this.el.dom.title = msg;
27141                break;
27142            case 'under':
27143                if(!this.errorEl){
27144                    var elp = this.getErrorCt();
27145                    if(!elp){ // field has no container el
27146                        this.el.dom.title = msg;
27147                        break;
27148                    }
27149                    this.errorEl = elp.createChild({cls:'x-form-invalid-msg'});
27150                    this.errorEl.setWidth(elp.getWidth(true)-20);
27151                }
27152                this.errorEl.update(msg);
27153                Ext.form.Field.msgFx[this.msgFx].show(this.errorEl, this);
27154                break;
27155            case 'side':
27156                if(!this.errorIcon){
27157                    var elp = this.getErrorCt();
27158                    if(!elp){ // field has no container el
27159                        this.el.dom.title = msg;
27160                        break;
27161                    }
27162                    this.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});
27163                }
27164                this.alignErrorIcon();
27165                this.errorIcon.dom.qtip = msg;
27166                this.errorIcon.dom.qclass = 'x-form-invalid-tip';
27167                this.errorIcon.show();
27168                this.on('resize', this.alignErrorIcon, this);
27169                break;
27170            default:
27171                var t = Ext.getDom(this.msgTarget);
27172                t.innerHTML = msg;
27173                t.style.display = this.msgDisplay;
27174                break;
27175        }
27176        this.fireEvent('invalid', this, msg);
27177    },
27178
27179    // private
27180    getErrorCt : function(){
27181        return this.el.findParent('.x-form-element', 5, true) || // use form element wrap if available
27182            this.el.findParent('.x-form-field-wrap', 5, true);   // else direct field wrap
27183    },
27184
27185    // private
27186    alignErrorIcon : function(){
27187        this.errorIcon.alignTo(this.el, 'tl-tr', [2, 0]);
27188    },
27189
27190    
27191    clearInvalid : function(){
27192        if(!this.rendered || this.preventMark){ // not rendered
27193            return;
27194        }
27195        this.el.removeClass(this.invalidClass);
27196        switch(this.msgTarget){
27197            case 'qtip':
27198                this.el.dom.qtip = '';
27199                break;
27200            case 'title':
27201                this.el.dom.title = '';
27202                break;
27203            case 'under':
27204                if(this.errorEl){
27205                    Ext.form.Field.msgFx[this.msgFx].hide(this.errorEl, this);
27206                }
27207                break;
27208            case 'side':
27209                if(this.errorIcon){
27210                    this.errorIcon.dom.qtip = '';
27211                    this.errorIcon.hide();
27212                    this.un('resize', this.alignErrorIcon, this);
27213                }
27214                break;
27215            default:
27216                var t = Ext.getDom(this.msgTarget);
27217                t.innerHTML = '';
27218                t.style.display = 'none';
27219                break;
27220        }
27221        this.fireEvent('valid', this);
27222    },
27223
27224    
27225    getRawValue : function(){
27226        var v = this.rendered ? this.el.getValue() : Ext.value(this.value, '');
27227        if(v === this.emptyText){
27228            v = '';
27229        }
27230        return v;
27231    },
27232
27233    
27234    getValue : function(){
27235        if(!this.rendered) {
27236            return this.value;
27237        }
27238        var v = this.el.getValue();
27239        if(v === this.emptyText || v === undefined){
27240            v = '';
27241        }
27242        return v;
27243    },
27244
27245    
27246    setRawValue : function(v){
27247        return this.el.dom.value = (v === null || v === undefined ? '' : v);
27248    },
27249
27250    
27251    setValue : function(v){
27252        this.value = v;
27253        if(this.rendered){
27254            this.el.dom.value = (v === null || v === undefined ? '' : v);
27255            this.validate();
27256        }
27257    },
27258
27259    // private
27260    adjustSize : function(w, h){
27261        var s = Ext.form.Field.superclass.adjustSize.call(this, w, h);
27262        s.width = this.adjustWidth(this.el.dom.tagName, s.width);
27263        return s;
27264    },
27265
27266    // private
27267    adjustWidth : function(tag, w){
27268        tag = tag.toLowerCase();
27269        if(typeof w == 'number' && !Ext.isSafari){
27270            if(Ext.isIE && (tag == 'input' || tag == 'textarea')){
27271                if(tag == 'input' && !Ext.isStrict){
27272                    return this.inEditor ? w : w - 3;
27273                }
27274                if(tag == 'input' && Ext.isStrict){
27275                    return w - (Ext.isIE6 ? 4 : 1);
27276                }
27277                if(tag == 'textarea' && Ext.isStrict){
27278                    return w-2;
27279                }
27280            }else if(Ext.isOpera && Ext.isStrict){
27281                if(tag == 'input'){
27282                    return w + 2;
27283                }
27284                if(tag == 'textarea'){
27285                    return w-2;
27286                }
27287            }
27288        }
27289        return w;
27290    }
27291
27292    
27293    
27294
27295    
27296});
27297
27298Ext.form.MessageTargets = {
27299    'qtip' : {
27300        mark: function(f){
27301            this.el.dom.qtip = msg;
27302            this.el.dom.qclass = 'x-form-invalid-tip';
27303            if(Ext.QuickTips){ // fix for floating editors interacting with DND
27304                Ext.QuickTips.enable();
27305            }
27306        },
27307        clear: function(f){
27308            this.el.dom.qtip = '';
27309        }
27310    },
27311    'title' : {
27312        mark: function(f){
27313            this.el.dom.title = msg;
27314        },
27315        clear: function(f){
27316            this.el.dom.title = '';
27317        }
27318    },
27319    'under' : {
27320        mark: function(f){
27321            if(!this.errorEl){
27322                var elp = this.getErrorCt();
27323                if(!elp){ // field has no container el
27324                    this.el.dom.title = msg;
27325                    return;
27326                }
27327                this.errorEl = elp.createChild({cls:'x-form-invalid-msg'});
27328                this.errorEl.setWidth(elp.getWidth(true)-20);
27329            }
27330            this.errorEl.update(msg);
27331            Ext.form.Field.msgFx[this.msgFx].show(this.errorEl, this);
27332        },
27333        clear: function(f){
27334            if(this.errorEl){
27335                Ext.form.Field.msgFx[this.msgFx].hide(this.errorEl, this);
27336            }else{
27337                this.el.dom.title = '';
27338            }
27339        }
27340    },
27341    'side' : {
27342        mark: function(f){
27343            if(!this.errorIcon){
27344                var elp = this.getErrorCt();
27345                if(!elp){ // field has no container el
27346                    this.el.dom.title = msg;
27347                    return;
27348                }
27349                this.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});
27350            }
27351            this.alignErrorIcon();
27352            this.errorIcon.dom.qtip = msg;
27353            this.errorIcon.dom.qclass = 'x-form-invalid-tip';
27354            this.errorIcon.show();
27355            this.on('resize', this.alignErrorIcon, this);
27356        },
27357        clear: function(f){
27358            if(this.errorIcon){
27359                this.errorIcon.dom.qtip = '';
27360                this.errorIcon.hide();
27361                this.un('resize', this.alignErrorIcon, this);
27362            }else{
27363                this.el.dom.title = '';
27364            }
27365        }
27366    },
27367    'around' : {
27368        mark: function(f){
27369
27370        },
27371        clear: function(f){
27372
27373        }
27374    }
27375};
27376
27377
27378// anything other than normal should be considered experimental
27379Ext.form.Field.msgFx = {
27380    normal : {
27381        show: function(msgEl, f){
27382            msgEl.setDisplayed('block');
27383        },
27384
27385        hide : function(msgEl, f){
27386            msgEl.setDisplayed(false).update('');
27387        }
27388    },
27389
27390    slide : {
27391        show: function(msgEl, f){
27392            msgEl.slideIn('t', {stopFx:true});
27393        },
27394
27395        hide : function(msgEl, f){
27396            msgEl.slideOut('t', {stopFx:true,useDisplay:true});
27397        }
27398    },
27399
27400    slideRight : {
27401        show: function(msgEl, f){
27402            msgEl.fixDisplay();
27403            msgEl.alignTo(f.el, 'tl-tr');
27404            msgEl.slideIn('l', {stopFx:true});
27405        },
27406
27407        hide : function(msgEl, f){
27408            msgEl.slideOut('l', {stopFx:true,useDisplay:true});
27409        }
27410    }
27411};
27412Ext.reg('field', Ext.form.Field);
27413
27414
27415Ext.form.TextField = Ext.extend(Ext.form.Field,  {
27416    
27417    
27418    
27419    grow : false,
27420    
27421    growMin : 30,
27422    
27423    growMax : 800,
27424    
27425    vtype : null,
27426    
27427    maskRe : null,
27428    
27429    disableKeyFilter : false,
27430    
27431    allowBlank : true,
27432    
27433    minLength : 0,
27434    
27435    maxLength : Number.MAX_VALUE,
27436    
27437    minLengthText : "O tamanho mínimo pra este campo é {0}",
27438    
27439    maxLengthText : "O tamanho máximo para este campo é {0}",
27440    
27441    selectOnFocus : false,
27442    
27443    blankText : "Este campo é obrigatório",
27444    
27445    validator : null,
27446    
27447    regex : null,
27448    
27449    regexText : "",
27450    
27451    emptyText : null,
27452    
27453    emptyClass : 'x-form-empty-field',
27454
27455    
27456
27457    initComponent : function(){
27458        Ext.form.TextField.superclass.initComponent.call(this);
27459        this.addEvents(
27460            
27461            'autosize',
27462
27463            
27464            'keydown',
27465            
27466            'keyup',
27467            
27468            'keypress'
27469        );
27470    },
27471
27472    // private
27473    initEvents : function(){
27474        Ext.form.TextField.superclass.initEvents.call(this);
27475        if(this.validationEvent == 'keyup'){
27476            this.validationTask = new Ext.util.DelayedTask(this.validate, this);
27477            this.el.on('keyup', this.filterValidation, this);
27478        }
27479        else if(this.validationEvent !== false){
27480            this.el.on(this.validationEvent, this.validate, this, {buffer: this.validationDelay});
27481        }
27482        if(this.selectOnFocus || this.emptyText){
27483            this.on("focus", this.preFocus, this);
27484            this.el.on('mousedown', function(){
27485                if(!this.hasFocus){
27486                    this.el.on('mouseup', function(e){
27487                        e.preventDefault();
27488                    }, this, {single:true});
27489                }
27490            }, this);
27491            if(this.emptyText){
27492                this.on('blur', this.postBlur, this);
27493                this.applyEmptyText();
27494            }
27495        }
27496        if(this.maskRe || (this.vtype && this.disableKeyFilter !== true && (this.maskRe = Ext.form.VTypes[this.vtype+'Mask']))){
27497            this.el.on("keypress", this.filterKeys, this);
27498        }
27499        if(this.grow){
27500            this.el.on("keyup", this.onKeyUpBuffered,  this, {buffer:50});
27501            this.el.on("click", this.autoSize,  this);
27502        }
27503
27504        if(this.enableKeyEvents){
27505            this.el.on("keyup", this.onKeyUp, this);
27506            this.el.on("keydown", this.onKeyDown, this);
27507            this.el.on("keypress", this.onKeyPress, this);
27508        }
27509    },
27510
27511    processValue : function(value){
27512        if(this.stripCharsRe){
27513            var newValue = value.replace(this.stripCharsRe, '');
27514            if(newValue !== value){
27515                this.setRawValue(newValue);
27516                return newValue;
27517            }
27518        }
27519        return value;
27520    },
27521
27522    filterValidation : function(e){
27523        if(!e.isNavKeyPress()){
27524            this.validationTask.delay(this.validationDelay);
27525        }
27526    },
27527    
27528    //private
27529    onDisable: function(){
27530        Ext.form.TextField.superclass.onDisable.call(this);
27531        if(Ext.isIE){
27532            this.el.dom.unselectable = 'on';
27533        }
27534    },
27535    
27536    //private
27537    onEnable: function(){
27538        Ext.form.TextField.superclass.onEnable.call(this);
27539        if(Ext.isIE){
27540            this.el.dom.unselectable = '';
27541        }
27542    },
27543
27544    // private
27545    onKeyUpBuffered : function(e){
27546        if(!e.isNavKeyPress()){
27547            this.autoSize();
27548        }
27549    },
27550
27551    // private
27552    onKeyUp : function(e){
27553        this.fireEvent('keyup', this, e);
27554    },
27555
27556    // private
27557    onKeyDown : function(e){
27558        this.fireEvent('keydown', this, e);
27559    },
27560
27561    // private
27562    onKeyPress : function(e){
27563        this.fireEvent('keypress', this, e);
27564    },
27565
27566    
27567    reset : function(){
27568        Ext.form.TextField.superclass.reset.call(this);
27569        this.applyEmptyText();
27570    },
27571
27572    applyEmptyText : function(){
27573        if(this.rendered && this.emptyText && this.getRawValue().length < 1 && !this.hasFocus){
27574            this.setRawValue(this.emptyText);
27575            this.el.addClass(this.emptyClass);
27576        }
27577    },
27578
27579    // private
27580    preFocus : function(){
27581        if(this.emptyText){
27582            if(this.el.dom.value == this.emptyText){
27583                this.setRawValue('');
27584            }
27585            this.el.removeClass(this.emptyClass);
27586        }
27587        if(this.selectOnFocus){
27588            this.el.dom.select();
27589        }
27590    },
27591
27592    // private
27593    postBlur : function(){
27594        this.applyEmptyText();
27595    },
27596
27597    // private
27598    filterKeys : function(e){
27599        if(e.ctrlKey){
27600            return;
27601        }
27602        var k = e.getKey();
27603        if(Ext.isGecko && (e.isNavKeyPress() || k == e.BACKSPACE || (k == e.DELETE && e.button == -1))){
27604            return;
27605        }
27606        var c = e.getCharCode(), cc = String.fromCharCode(c);
27607        if(!Ext.isGecko && e.isSpecialKey() && !cc){
27608            return;
27609        }
27610        if(!this.maskRe.test(cc)){
27611            e.stopEvent();
27612        }
27613    },
27614
27615    setValue : function(v){
27616        if(this.emptyText && this.el && v !== undefined && v !== null && v !== ''){
27617            this.el.removeClass(this.emptyClass);
27618        }
27619        Ext.form.TextField.superclass.setValue.apply(this, arguments);
27620        this.applyEmptyText();
27621        this.autoSize();
27622    },
27623
27624    
27625    validateValue : function(value){
27626        if(value.length < 1 || value === this.emptyText){ // if it's blank
27627             if(this.allowBlank){
27628                 this.clearInvalid();
27629                 return true;
27630             }else{
27631                 this.markInvalid(this.blankText);
27632                 return false;
27633             }
27634        }
27635        if(value.length < this.minLength){
27636            this.markInvalid(String.format(this.minLengthText, this.minLength));
27637            return false;
27638        }
27639        if(value.length > this.maxLength){
27640            this.markInvalid(String.format(this.maxLengthText, this.maxLength));
27641            return false;
27642        }
27643        if(this.vtype){
27644            var vt = Ext.form.VTypes;
27645            if(!vt[this.vtype](value, this)){
27646                this.markInvalid(this.vtypeText || vt[this.vtype +'Text']);
27647                return false;
27648            }
27649        }
27650        if(typeof this.validator == "function"){
27651            var msg = this.validator(value);
27652            if(msg !== true){
27653                this.markInvalid(msg);
27654                return false;
27655            }
27656        }
27657        if(this.regex && !this.regex.test(value)){
27658            this.markInvalid(this.regexText);
27659            return false;
27660        }
27661        return true;
27662    },
27663
27664    
27665    selectText : function(start, end){
27666        var v = this.getRawValue();
27667        var doFocus = false;
27668        if(v.length > 0){
27669            start = start === undefined ? 0 : start;
27670            end = end === undefined ? v.length : end;
27671            var d = this.el.dom;
27672            if(d.setSelectionRange){
27673                d.setSelectionRange(start, end);
27674            }else if(d.createTextRange){
27675                var range = d.createTextRange();
27676                range.moveStart("character", start);
27677                range.moveEnd("character", end-v.length);
27678                range.select();
27679            }
27680            doFocus = Ext.isGecko || Ext.isOpera;
27681        }else{
27682            doFocus = true;
27683        }
27684        if(doFocus){
27685            this.focus();
27686        }
27687    },
27688
27689    
27690    autoSize : function(){
27691        if(!this.grow || !this.rendered){
27692            return;
27693        }
27694        if(!this.metrics){
27695            this.metrics = Ext.util.TextMetrics.createInstance(this.el);
27696        }
27697        var el = this.el;
27698        var v = el.dom.value;
27699        var d = document.createElement('div');
27700        d.appendChild(document.createTextNode(v));
27701        v = d.innerHTML;
27702        Ext.removeNode(d);
27703        d = null;
27704        v += "&#160;";
27705        var w = Math.min(this.growMax, Math.max(this.metrics.getWidth(v) +  10, this.growMin));
27706        this.el.setWidth(w);
27707        this.fireEvent("autosize", this, w);
27708    }
27709});
27710Ext.reg('textfield', Ext.form.TextField);
27711
27712
27713Ext.form.TriggerField = Ext.extend(Ext.form.TextField,  {
27714    
27715    
27716    defaultAutoCreate : {tag: "input", type: "text", size: "16", autocomplete: "off"},
27717    
27718    hideTrigger:false,
27719
27720    
27721    autoSize: Ext.emptyFn,
27722    // private
27723    monitorTab : true,
27724    // private
27725    deferHeight : true,
27726    // private
27727    mimicing : false,
27728
27729    // private
27730    onResize : function(w, h){
27731        Ext.form.TriggerField.superclass.onResize.call(this, w, h);
27732        if(typeof w == 'number'){
27733            this.el.setWidth(this.adjustWidth('input', w - this.trigger.getWidth()));
27734        }
27735        this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth());
27736    },
27737
27738    // private
27739    adjustSize : Ext.BoxComponent.prototype.adjustSize,
27740
27741    // private
27742    getResizeEl : function(){
27743        return this.wrap;
27744    },
27745
27746    // private
27747    getPositionEl : function(){
27748        return this.wrap;
27749    },
27750
27751    // private
27752    alignErrorIcon : function(){
27753        if(this.wrap){
27754            this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);
27755        }
27756    },
27757
27758    // private
27759    onRender : function(ct, position){
27760        Ext.form.TriggerField.superclass.onRender.call(this, ct, position);
27761        this.wrap = this.el.wrap({cls: "x-form-field-wrap"});
27762        this.trigger = this.wrap.createChild(this.triggerConfig ||
27763                {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.triggerClass});
27764        if(this.hideTrigger){
27765            this.trigger.setDisplayed(false);
27766        }
27767        this.initTrigger();
27768        if(!this.width){
27769            this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth());
27770        }
27771    },
27772
27773    afterRender : function(){
27774        Ext.form.TriggerField.superclass.afterRender.call(this);
27775        var y;
27776        if(Ext.isIE && !this.hideTrigger && this.el.getY() != (y = this.trigger.getY())){
27777            this.el.position();
27778            this.el.setY(y);
27779        }
27780    },
27781
27782    // private
27783    initTrigger : function(){
27784        this.trigger.on("click", this.onTriggerClick, this, {preventDefault:true});
27785        this.trigger.addClassOnOver('x-form-trigger-over');
27786        this.trigger.addClassOnClick('x-form-trigger-click');
27787    },
27788
27789    // private
27790    onDestroy : function(){
27791        if(this.trigger){
27792            this.trigger.removeAllListeners();
27793            this.trigger.remove();
27794        }
27795        if(this.wrap){
27796            this.wrap.remove();
27797        }
27798        Ext.form.TriggerField.superclass.onDestroy.call(this);
27799    },
27800
27801    // private
27802    onFocus : function(){
27803        Ext.form.TriggerField.superclass.onFocus.call(this);
27804        if(!this.mimicing){
27805            this.wrap.addClass('x-trigger-wrap-focus');
27806            this.mimicing = true;
27807            Ext.get(Ext.isIE ? document.body : document).on("mousedown", this.mimicBlur, this, {delay: 10});
27808            if(this.monitorTab){
27809                this.el.on("keydown", this.checkTab, this);
27810            }
27811        }
27812    },
27813
27814    // private
27815    checkTab : function(e){
27816        if(e.getKey() == e.TAB){
27817            this.triggerBlur();
27818        }
27819    },
27820
27821    // private
27822    onBlur : function(){
27823        // do nothing
27824    },
27825
27826    // private
27827    mimicBlur : function(e){
27828        if(!this.wrap.contains(e.target) && this.validateBlur(e)){
27829            this.triggerBlur();
27830        }
27831    },
27832
27833    // private
27834    triggerBlur : function(){
27835        this.mimicing = false;
27836        Ext.get(Ext.isIE ? document.body : document).un("mousedown", this.mimicBlur, this);
27837        if(this.monitorTab && this.el){
27838            this.el.un("keydown", this.checkTab, this);
27839        }
27840        this.beforeBlur();
27841        if(this.wrap){
27842            this.wrap.removeClass('x-trigger-wrap-focus');
27843        }
27844        Ext.form.TriggerField.superclass.onBlur.call(this);
27845    },
27846
27847    beforeBlur : Ext.emptyFn, 
27848
27849    // private
27850    // This should be overriden by any subclass that needs to check whether or not the field can be blurred.
27851    validateBlur : function(e){
27852        return true;
27853    },
27854
27855    // private
27856    onDisable : function(){
27857        Ext.form.TriggerField.superclass.onDisable.call(this);
27858        if(this.wrap){
27859            this.wrap.addClass(this.disabledClass);
27860            this.el.removeClass(this.disabledClass);
27861        }
27862    },
27863
27864    // private
27865    onEnable : function(){
27866        Ext.form.TriggerField.superclass.onEnable.call(this);
27867        if(this.wrap){
27868            this.wrap.removeClass(this.disabledClass);
27869        }
27870    },
27871
27872    // private
27873    onShow : function(){
27874        if(this.wrap){
27875            this.wrap.dom.style.display = '';
27876            this.wrap.dom.style.visibility = 'visible';
27877        }
27878    },
27879
27880    // private
27881    onHide : function(){
27882        this.wrap.dom.style.display = 'none';
27883    },
27884
27885    
27886    onTriggerClick : Ext.emptyFn
27887
27888    
27889    
27890    
27891});
27892
27893// TwinTriggerField is not a public class to be used directly.  It is meant as an abstract base class
27894// to be extended by an implementing class.  For an example of implementing this class, see the custom
27895// SearchField implementation here: http://extjs.com/deploy/ext/examples/form/custom.html
27896Ext.form.TwinTriggerField = Ext.extend(Ext.form.TriggerField, {
27897    initComponent : function(){
27898        Ext.form.TwinTriggerField.superclass.initComponent.call(this);
27899
27900        this.triggerConfig = {
27901            tag:'span', cls:'x-form-twin-triggers', cn:[
27902            {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger1Class},
27903            {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger2Class}
27904        ]};
27905    },
27906
27907    getTrigger : function(index){
27908        return this.triggers[index];
27909    },
27910
27911    initTrigger : function(){
27912        var ts = this.trigger.select('.x-form-trigger', true);
27913        this.wrap.setStyle('overflow', 'hidden');
27914        var triggerField = this;
27915        ts.each(function(t, all, index){
27916            t.hide = function(){
27917                var w = triggerField.wrap.getWidth();
27918                this.dom.style.display = 'none';
27919                triggerField.el.setWidth(w-triggerField.trigger.getWidth());
27920            };
27921            t.show = function(){
27922                var w = triggerField.wrap.getWidth();
27923                this.dom.style.display = '';
27924                triggerField.el.setWidth(w-triggerField.trigger.getWidth());
27925            };
27926            var triggerIndex = 'Trigger'+(index+1);
27927
27928            if(this['hide'+triggerIndex]){
27929                t.dom.style.display = 'none';
27930            }
27931            t.on("click", this['on'+triggerIndex+'Click'], this, {preventDefault:true});
27932            t.addClassOnOver('x-form-trigger-over');
27933            t.addClassOnClick('x-form-trigger-click');
27934        }, this);
27935        this.triggers = ts.elements;
27936    },
27937
27938    onTrigger1Click : Ext.emptyFn,
27939    onTrigger2Click : Ext.emptyFn
27940});
27941Ext.reg('trigger', Ext.form.TriggerField);
27942
27943Ext.form.TextArea = Ext.extend(Ext.form.TextField,  {
27944    
27945    growMin : 60,
27946    
27947    growMax: 1000,
27948    growAppend : '&#160;\n&#160;',
27949    growPad : 0,
27950
27951    enterIsSpecial : false,
27952
27953    
27954    preventScrollbars: false,
27955    
27956
27957    // private
27958    onRender : function(ct, position){
27959        if(!this.el){
27960            this.defaultAutoCreate = {
27961                tag: "textarea",
27962                style:"width:100px;height:60px;",
27963                autocomplete: "off"
27964            };
27965        }
27966        Ext.form.TextArea.superclass.onRender.call(this, ct, position);
27967        if(this.grow){
27968            this.textSizeEl = Ext.DomHelper.append(document.body, {
27969                tag: "pre", cls: "x-form-grow-sizer"
27970            });
27971            if(this.preventScrollbars){
27972                this.el.setStyle("overflow", "hidden");
27973            }
27974            this.el.setHeight(this.growMin);
27975        }
27976    },
27977
27978    onDestroy : function(){
27979        if(this.textSizeEl){
27980            Ext.removeNode(this.textSizeEl);
27981        }
27982        Ext.form.TextArea.superclass.onDestroy.call(this);
27983    },
27984
27985    fireKey : function(e){
27986        if(e.isSpecialKey() && (this.enterIsSpecial || (e.getKey() != e.ENTER || e.hasModifier()))){
27987            this.fireEvent("specialkey", this, e);
27988        }
27989    },
27990
27991    // private
27992    onKeyUp : function(e){
27993        if(!e.isNavKeyPress() || e.getKey() == e.ENTER){
27994            this.autoSize();
27995        }
27996        Ext.form.TextArea.superclass.onKeyUp.call(this, e);
27997    },
27998
27999    
28000    autoSize : function(){
28001        if(!this.grow || !this.textSizeEl){
28002            return;
28003        }
28004        var el = this.el;
28005        var v = el.dom.value;
28006        var ts = this.textSizeEl;
28007        ts.innerHTML = '';
28008        ts.appendChild(document.createTextNode(v));
28009        v = ts.innerHTML;
28010
28011        Ext.fly(ts).setWidth(this.el.getWidth());
28012        if(v.length < 1){
28013            v = "&#160;&#160;";
28014        }else{
28015            if(Ext.isIE){
28016                v = v.replace(/\n/g, '<p>&#160;</p>');
28017            }
28018            v += this.growAppend;
28019        }
28020        ts.innerHTML = v;
28021        var h = Math.min(this.growMax, Math.max(ts.offsetHeight, this.growMin)+this.growPad);
28022        if(h != this.lastHeight){
28023            this.lastHeight = h;
28024            this.el.setHeight(h);
28025            this.fireEvent("autosize", this, h);
28026        }
28027    }
28028});
28029Ext.reg('textarea', Ext.form.TextArea);
28030
28031Ext.form.NumberField = Ext.extend(Ext.form.TextField,  {
28032    
28033    
28034    fieldClass: "x-form-field x-form-num-field",
28035    
28036    allowDecimals : true,
28037    
28038    decimalSeparator : ".",
28039    
28040    decimalPrecision : 2,
28041    
28042    allowNegative : true,
28043    
28044    minValue : Number.NEGATIVE_INFINITY,
28045    
28046    maxValue : Number.MAX_VALUE,
28047    
28048    minText : "O valor mínimo para este campo é {0}",
28049    
28050    maxText : "O valor máximo para este campo é {0}",
28051    
28052    nanText : "{0} não é um número válido",
28053    
28054    baseChars : "0123456789",
28055
28056    // private
28057    initEvents : function(){
28058        Ext.form.NumberField.superclass.initEvents.call(this);
28059        var allowed = this.baseChars+'';
28060        if(this.allowDecimals){
28061            allowed += this.decimalSeparator;
28062        }
28063        if(this.allowNegative){
28064            allowed += "-";
28065        }
28066        this.stripCharsRe = new RegExp('[^'+allowed+']', 'gi');
28067        var keyPress = function(e){
28068            var k = e.getKey();
28069            if(!Ext.isIE && (e.isSpecialKey() || k == e.BACKSPACE || k == e.DELETE)){
28070                return;
28071            }
28072            var c = e.getCharCode();
28073            if(allowed.indexOf(String.fromCharCode(c)) === -1){
28074                e.stopEvent();
28075            }
28076        };
28077        this.el.on("keypress", keyPress, this);
28078    },
28079
28080    // private
28081    validateValue : function(value){
28082        if(!Ext.form.NumberField.superclass.validateValue.call(this, value)){
28083            return false;
28084        }
28085        if(value.length < 1){ // if it's blank and textfield didn't flag it then it's valid
28086             return true;
28087        }
28088        value = String(value).replace(this.decimalSeparator, ".");
28089        if(isNaN(value)){
28090            this.markInvalid(String.format(this.nanText, value));
28091            return false;
28092        }
28093        var num = this.parseValue(value);
28094        if(num < this.minValue){
28095            this.markInvalid(String.format(this.minText, this.minValue));
28096            return false;
28097        }
28098        if(num > this.maxValue){
28099            this.markInvalid(String.format(this.maxText, this.maxValue));
28100            return false;
28101        }
28102        return true;
28103    },
28104
28105    getValue : function(){
28106        return this.fixPrecision(this.parseValue(Ext.form.NumberField.superclass.getValue.call(this)));
28107    },
28108
28109    setValue : function(v){
28110    	v = typeof v == 'number' ? v : parseFloat(String(v).replace(this.decimalSeparator, "."));
28111        v = isNaN(v) ? '' : String(v).replace(".", this.decimalSeparator);
28112        Ext.form.NumberField.superclass.setValue.call(this, v);
28113    },
28114
28115    // private
28116    parseValue : function(value){
28117        value = parseFloat(String(value).replace(this.decimalSeparator, "."));
28118        return isNaN(value) ? '' : value;
28119    },
28120
28121    // private
28122    fixPrecision : function(value){
28123        var nan = isNaN(value);
28124        if(!this.allowDecimals || this.decimalPrecision == -1 || nan || !value){
28125           return nan ? '' : value;
28126        }
28127        return parseFloat(parseFloat(value).toFixed(this.decimalPrecision));
28128    },
28129
28130    beforeBlur : function(){
28131        var v = this.parseValue(this.getRawValue());
28132        if(v || v === 0){
28133            this.setValue(this.fixPrecision(v));
28134        }
28135    }
28136});
28137Ext.reg('numberfield', Ext.form.NumberField);
28138
28139Ext.form.DateField = Ext.extend(Ext.form.TriggerField,  {
28140    
28141    format : "m/d/Y",
28142    
28143    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",
28144    
28145    disabledDaysText : "Inactivo",
28146    
28147    disabledDatesText : "Inactivo",
28148    
28149    minText : "A data neste campo tem que ser igual ou posterior a {0}",
28150    
28151    maxText : "A data neste campo tem que ser igual ou anterior a {0}",
28152    
28153    invalidText : "{0} não é uma data válida - tem que estar no formato {1}",
28154    
28155    triggerClass : 'x-form-date-trigger',
28156    
28157    showToday : true,
28158    
28159    
28160    
28161    
28162    
28163
28164    // private
28165    defaultAutoCreate : {tag: "input", type: "text", size: "10", autocomplete: "off"},
28166
28167    initComponent : function(){
28168        Ext.form.DateField.superclass.initComponent.call(this);
28169        
28170        this.addEvents(
28171            
28172            'select'
28173        );
28174        
28175        if(typeof this.minValue == "string"){
28176            this.minValue = this.parseDate(this.minValue);
28177        }
28178        if(typeof this.maxValue == "string"){
28179            this.maxValue = this.parseDate(this.maxValue);
28180        }
28181        this.disabledDatesRE = null;
28182        this.initDisabledDays();
28183    },
28184
28185    // private
28186    initDisabledDays : function(){
28187        if(this.disabledDates){
28188            var dd = this.disabledDates;
28189            var re = "(?:";
28190            for(var i = 0; i < dd.length; i++){
28191                re += dd[i];
28192                if(i != dd.length-1) re += "|";
28193            }
28194            this.disabledDatesRE = new RegExp(re + ")");
28195        }
28196    },
28197
28198    
28199    setDisabledDates : function(dd){
28200        this.disabledDates = dd;
28201        this.initDisabledDays();
28202        if(this.menu){
28203            this.menu.picker.setDisabledDates(this.disabledDatesRE);
28204        }
28205    },
28206
28207    
28208    setDisabledDays : function(dd){
28209        this.disabledDays = dd;
28210        if(this.menu){
28211            this.menu.picker.setDisabledDays(dd);
28212        }
28213    },
28214
28215    
28216    setMinValue : function(dt){
28217        this.minValue = (typeof dt == "string" ? this.parseDate(dt) : dt);
28218        if(this.menu){
28219            this.menu.picker.setMinDate(this.minValue);
28220        }
28221    },
28222
28223    
28224    setMaxValue : function(dt){
28225        this.maxValue = (typeof dt == "string" ? this.parseDate(dt) : dt);
28226        if(this.menu){
28227            this.menu.picker.setMaxDate(this.maxValue);
28228        }
28229    },
28230
28231    // private
28232    validateValue : function(value){
28233        value = this.formatDate(value);
28234        if(!Ext.form.DateField.superclass.validateValue.call(this, value)){
28235            return false;
28236        }
28237        if(value.length < 1){ // if it's blank and textfield didn't flag it then it's valid
28238             return true;
28239        }
28240        var svalue = value;
28241        value = this.parseDate(value);
28242        if(!value){
28243            this.markInvalid(String.format(this.invalidText, svalue, this.format));
28244            return false;
28245        }
28246        var time = value.getTime();
28247        if(this.minValue && time < this.minValue.getTime()){
28248            this.markInvalid(String.format(this.minText, this.formatDate(this.minValue)));
28249            return false;
28250        }
28251        if(this.maxValue && time > this.maxValue.getTime()){
28252            this.markInvalid(String.format(this.maxText, this.formatDate(this.maxValue)));
28253            return false;
28254        }
28255        if(this.disabledDays){
28256            var day = value.getDay();
28257            for(var i = 0; i < this.disabledDays.length; i++) {
28258            	if(day === this.disabledDays[i]){
28259            	    this.markInvalid(this.disabledDaysText);
28260                    return false;
28261            	}
28262            }
28263        }
28264        var fvalue = this.formatDate(value);
28265        if(this.disabledDatesRE && this.disabledDatesRE.test(fvalue)){
28266            this.markInvalid(String.format(this.disabledDatesText, fvalue));
28267            return false;
28268        }
28269        return true;
28270    },
28271
28272    // private
28273    // Provides logic to override the default TriggerField.validateBlur which just returns true
28274    validateBlur : function(){
28275        return !this.menu || !this.menu.isVisible();
28276    },
28277
28278    
28279    getValue : function(){
28280        return this.parseDate(Ext.form.DateField.superclass.getValue.call(this)) || "";
28281    },
28282
28283    
28284    setValue : function(date){
28285        Ext.form.DateField.superclass.setValue.call(this, this.formatDate(this.parseDate(date)));
28286    },
28287
28288    // private
28289    parseDate : function(value){
28290        if(!value || Ext.isDate(value)){
28291            return value;
28292        }
28293        var v = Date.parseDate(value, this.format);
28294        if(!v && this.altFormats){
28295            if(!this.altFormatsArray){
28296                this.altFormatsArray = this.altFormats.split("|");
28297            }
28298            for(var i = 0, len = this.altFormatsArray.length; i < len && !v; i++){
28299                v = Date.parseDate(value, this.altFormatsArray[i]);
28300            }
28301        }
28302        return v;
28303    },
28304
28305    // private
28306    onDestroy : function(){
28307        if(this.menu) {
28308            this.menu.destroy();
28309        }
28310        if(this.wrap){
28311            this.wrap.remove();
28312        }
28313        Ext.form.DateField.superclass.onDestroy.call(this);
28314    },
28315
28316    // private
28317    formatDate : function(date){
28318        return Ext.isDate(date) ? date.dateFormat(this.format) : date;
28319    },
28320
28321    // private
28322    menuListeners : {
28323        select: function(m, d){
28324            this.setValue(d);
28325            this.fireEvent('select', this, d);
28326        },
28327        show : function(){ // retain focus styling
28328            this.onFocus();
28329        },
28330        hide : function(){
28331            this.focus.defer(10, this);
28332            var ml = this.menuListeners;
28333            this.menu.un("select", ml.select,  this);
28334            this.menu.un("show", ml.show,  this);
28335            this.menu.un("hide", ml.hide,  this);
28336        }
28337    },
28338
28339    
28340    // private
28341    // Implements the default empty TriggerField.onTriggerClick function to display the DatePicker
28342    onTriggerClick : function(){
28343        if(this.disabled){
28344            return;
28345        }
28346        if(this.menu == null){
28347            this.menu = new Ext.menu.DateMenu();
28348        }
28349        Ext.apply(this.menu.picker,  {
28350            minDate : this.minValue,
28351            maxDate : this.maxValue,
28352            disabledDatesRE : this.disabledDatesRE,
28353            disabledDatesText : this.disabledDatesText,
28354            disabledDays : this.disabledDays,
28355            disabledDaysText : this.disabledDaysText,
28356            format : this.format,
28357            showToday : this.showToday,
28358            minText : String.format(this.minText, this.formatDate(this.minValue)),
28359            maxText : String.format(this.maxText, this.formatDate(this.maxValue))
28360        });
28361        this.menu.on(Ext.apply({}, this.menuListeners, {
28362            scope:this
28363        }));
28364        this.menu.picker.setValue(this.getValue() || new Date());
28365        this.menu.show(this.el, "tl-bl?");
28366    },
28367
28368    // private
28369    beforeBlur : function(){
28370        var v = this.parseDate(this.getRawValue());
28371        if(v){
28372            this.setValue(v);
28373        }
28374    }
28375
28376    
28377    
28378    
28379    
28380});
28381Ext.reg('datefield', Ext.form.DateField);
28382
28383Ext.form.ComboBox = Ext.extend(Ext.form.TriggerField, {
28384    
28385    
28386    
28387    
28388    
28389
28390    // private
28391    defaultAutoCreate : {tag: "input", type: "text", size: "24", autocomplete: "off"},
28392    
28393    
28394    
28395    
28396    
28397    
28398    listClass: '',
28399    
28400    selectedClass: 'x-combo-selected',
28401    
28402    triggerClass : 'x-form-arrow-trigger',
28403    
28404    shadow:'sides',
28405    
28406    listAlign: 'tl-bl?',
28407    
28408    maxHeight: 300,
28409    
28410    minHeight: 90,
28411    
28412    triggerAction: 'query',
28413    
28414    minChars : 4,
28415    
28416    typeAhead: false,
28417    
28418    queryDelay: 500,
28419    
28420    pageSize: 0,
28421    
28422    selectOnFocus:false,
28423    
28424    queryParam: 'query',
28425    
28426    loadingText: 'A carregar...',
28427    
28428    resizable: false,
28429    
28430    handleHeight : 8,
28431    
28432    editable: true,
28433    
28434    allQuery: '',
28435    
28436    mode: 'remote',
28437    
28438    minListWidth : 70,
28439    
28440    forceSelection:false,
28441    
28442    typeAheadDelay : 250,
28443    
28444
28445    
28446    lazyInit : true,
28447
28448    
28449
28450    // private
28451    initComponent : function(){
28452        Ext.form.ComboBox.superclass.initComponent.call(this);
28453        this.addEvents(
28454            
28455            'expand',
28456            
28457            'collapse',
28458            
28459            'beforeselect',
28460            
28461            'select',
28462            
28463            'beforequery'
28464        );
28465        if(this.transform){
28466            this.allowDomMove = false;
28467            var s = Ext.getDom(this.transform);
28468            if(!this.hiddenName){
28469                this.hiddenName = s.name;
28470            }
28471            if(!this.store){
28472                this.mode = 'local';
28473                var d = [], opts = s.options;
28474                for(var i = 0, len = opts.length;i < len; i++){
28475                    var o = opts[i];
28476                    var value = (Ext.isIE ? o.getAttributeNode('value').specified : o.hasAttribute('value')) ? o.value : o.text;
28477                    if(o.selected) {
28478                        this.value = value;
28479                    }
28480                    d.push([value, o.text]);
28481                }
28482                this.store = new Ext.data.SimpleStore({
28483                    'id': 0,
28484                    fields: ['value', 'text'],
28485                    data : d
28486                });
28487                this.valueField = 'value';
28488                this.displayField = 'text';
28489            }
28490            s.name = Ext.id(); // wipe out the name in case somewhere else they have a reference
28491            if(!this.lazyRender){
28492                this.target = true;
28493                this.el = Ext.DomHelper.insertBefore(s, this.autoCreate || this.defaultAutoCreate);
28494                Ext.removeNode(s); // remove it
28495                this.render(this.el.parentNode);
28496            }else{
28497                Ext.removeNode(s); // remove it
28498            }
28499        }
28500        //auto-configure store from local array data
28501        else if(Ext.isArray(this.store)){
28502            if (Ext.isArray(this.store[0])){
28503                this.store = new Ext.data.SimpleStore({
28504                    fields: ['value','text'],
28505                    data: this.store
28506                });
28507                this.valueField = 'value';
28508            }else{
28509                this.store = new Ext.data.SimpleStore({
28510                    fields: ['text'],
28511                    data: this.store,
28512                    expandData: true
28513                });
28514                this.valueField = 'text';
28515            }
28516            this.displayField = 'text';
28517            this.mode = 'local';
28518        }
28519
28520        this.selectedIndex = -1;
28521        if(this.mode == 'local'){
28522            if(this.initialConfig.queryDelay === undefined){
28523                this.queryDelay = 10;
28524            }
28525            if(this.initialConfig.minChars === undefined){
28526                this.minChars = 0;
28527            }
28528        }
28529    },
28530
28531    // private
28532    onRender : function(ct, position){
28533        Ext.form.ComboBox.superclass.onRender.call(this, ct, position);
28534        if(this.hiddenName){
28535            this.hiddenField = this.el.insertSibling({tag:'input', type:'hidden', name: this.hiddenName,
28536                    id: (this.hiddenId||this.hiddenName)}, 'before', true);
28537
28538            // prevent input submission
28539            this.el.dom.removeAttribute('name');
28540        }
28541        if(Ext.isGecko){
28542            this.el.dom.setAttribute('autocomplete', 'off');
28543        }
28544
28545        if(!this.lazyInit){
28546            this.initList();
28547        }else{
28548            this.on('focus', this.initList, this, {single: true});
28549        }
28550
28551        if(!this.editable){
28552            this.editable = true;
28553            this.setEditable(false);
28554        }
28555    },
28556
28557    // private
28558    initValue : function(){
28559        Ext.form.ComboBox.superclass.initValue.call(this);
28560        if(this.hiddenField){
28561            this.hiddenField.value =
28562                this.hiddenValue !== undefined ? this.hiddenValue :
28563                this.value !== undefined ? this.value : '';
28564        }
28565    },
28566
28567    // private
28568    initList : function(){
28569        if(!this.list){
28570            var cls = 'x-combo-list';
28571
28572            this.list = new Ext.Layer({
28573                shadow: this.shadow, cls: [cls, this.listClass].join(' '), constrain:false
28574            });
28575
28576            var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);
28577            this.list.setWidth(lw);
28578            this.list.swallowEvent('mousewheel');
28579            this.assetHeight = 0;
28580
28581            if(this.title){
28582                this.header = this.list.createChild({cls:cls+'-hd', html: this.title});
28583                this.assetHeight += this.header.getHeight();
28584            }
28585
28586            this.innerList = this.list.createChild({cls:cls+'-inner'});
28587            this.innerList.on('mouseover', this.onViewOver, this);
28588            this.innerList.on('mousemove', this.onViewMove, this);
28589            this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
28590
28591            if(this.pageSize){
28592                this.footer = this.list.createChild({cls:cls+'-ft'});
28593                this.pageTb = new Ext.PagingToolbar({
28594                    store:this.store,
28595                    pageSize: this.pageSize,
28596                    renderTo:this.footer
28597                });
28598                this.assetHeight += this.footer.getHeight();
28599            }
28600
28601            if(!this.tpl){
28602                
28603                this.tpl = '<tpl for="."><div class="'+cls+'-item">{' + this.displayField + '}</div></tpl>';
28604                
28605            }
28606
28607            
28608            this.view = new Ext.DataView({
28609                applyTo: this.innerList,
28610                tpl: this.tpl,
28611                singleSelect: true,
28612                selectedClass: this.selectedClass,
28613                itemSelector: this.itemSelector || '.' + cls + '-item'
28614            });
28615
28616            this.view.on('click', this.onViewClick, this);
28617
28618            this.bindStore(this.store, true);
28619
28620            if(this.resizable){
28621                this.resizer = new Ext.Resizable(this.list,  {
28622                   pinned:true, handles:'se'
28623                });
28624                this.resizer.on('resize', function(r, w, h){
28625                    this.maxHeight = h-this.handleHeight-this.list.getFrameWidth('tb')-this.assetHeight;
28626                    this.listWidth = w;
28627                    this.innerList.setWidth(w - this.list.getFrameWidth('lr'));
28628                    this.restrictHeight();
28629                }, this);
28630                this[this.pageSize?'footer':'innerList'].setStyle('margin-bottom', this.handleHeight+'px');
28631            }
28632        }
28633    },
28634    
28635    
28636    getStore : function(){
28637        return this.store;
28638    },
28639
28640    // private
28641    bindStore : function(store, initial){
28642        if(this.store && !initial){
28643            this.store.un('beforeload', this.onBeforeLoad, this);
28644            this.store.un('load', this.onLoad, this);
28645            this.store.un('loadexception', this.collapse, this);
28646            if(!store){
28647                this.store = null;
28648                if(this.view){
28649                    this.view.setStore(null);
28650                }
28651            }
28652        }
28653        if(store){
28654            this.store = Ext.StoreMgr.lookup(store);
28655
28656            this.store.on('beforeload', this.onBeforeLoad, this);
28657            this.store.on('load', this.onLoad, this);
28658            this.store.on('loadexception', this.collapse, this);
28659
28660            if(this.view){
28661                this.view.setStore(store);
28662            }
28663        }
28664    },
28665
28666    // private
28667    initEvents : function(){
28668        Ext.form.ComboBox.superclass.initEvents.call(this);
28669
28670        this.keyNav = new Ext.KeyNav(this.el, {
28671            "up" : function(e){
28672                this.inKeyMode = true;
28673                this.selectPrev();
28674            },
28675
28676            "down" : function(e){
28677                if(!this.isExpanded()){
28678                    this.onTriggerClick();
28679                }else{
28680                    this.inKeyMode = true;
28681                    this.selectNext();
28682                }
28683            },
28684
28685            "enter" : function(e){
28686                this.onViewClick();
28687                this.delayedCheck = true;
28688                this.unsetDelayCheck.defer(10, this);
28689            },
28690
28691            "esc" : function(e){
28692                this.collapse();
28693            },
28694
28695            "tab" : function(e){
28696                this.onViewClick(false);
28697                return true;
28698            },
28699
28700            scope : this,
28701
28702            doRelay : function(foo, bar, hname){
28703                if(hname == 'down' || this.scope.isExpanded()){
28704                   return Ext.KeyNav.prototype.doRelay.apply(this, arguments);
28705                }
28706                return true;
28707            },
28708
28709            forceKeyDown : true
28710        });
28711        this.queryDelay = Math.max(this.queryDelay || 10,
28712                this.mode == 'local' ? 10 : 250);
28713        this.dqTask = new Ext.util.DelayedTask(this.initQuery, this);
28714        if(this.typeAhead){
28715            this.taTask = new Ext.util.DelayedTask(this.onTypeAhead, this);
28716        }
28717        if(this.editable !== false){
28718            this.el.on("keyup", this.onKeyUp, this);
28719        }
28720        if(this.forceSelection){
28721            this.on('blur', this.doForce, this);
28722        }
28723    },
28724
28725    // private
28726    onDestroy : function(){
28727        if(this.view){
28728            Ext.destroy(this.view);
28729        }
28730        if(this.list){
28731            if(this.innerList){
28732                this.innerList.un('mouseover', this.onViewOver, this);
28733                this.innerList.un('mousemove', this.onViewMove, this);
28734            }
28735            this.list.destroy();
28736        }
28737        if (this.dqTask){
28738            this.dqTask.cancel();
28739            this.dqTask = null;
28740        }
28741        this.bindStore(null);
28742        Ext.form.ComboBox.superclass.onDestroy.call(this);
28743    },
28744
28745    // private
28746    unsetDelayCheck : function(){
28747        delete this.delayedCheck;
28748    },
28749
28750    // private
28751    fireKey : function(e){
28752        if(e.isNavKeyPress() && !this.isExpanded() && !this.delayedCheck){
28753            this.fireEvent("specialkey", this, e);
28754        }
28755    },
28756
28757    // private
28758    onResize: function(w, h){
28759        Ext.form.ComboBox.superclass.onResize.apply(this, arguments);
28760        if(this.list && this.listWidth === undefined){
28761            var lw = Math.max(w, this.minListWidth);
28762            this.list.setWidth(lw);
28763            this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
28764        }
28765    },
28766
28767    // private
28768    onEnable: function(){
28769        Ext.form.ComboBox.superclass.onEnable.apply(this, arguments);
28770        if(this.hiddenField){
28771            this.hiddenField.disabled = false;
28772        }
28773    },
28774
28775    // private
28776    onDisable: function(){
28777        Ext.form.ComboBox.superclass.onDisable.apply(this, arguments);
28778        if(this.hiddenField){
28779            this.hiddenField.disabled = true;
28780        }
28781    },
28782
28783    
28784    setEditable : function(value){
28785        if(value == this.editable){
28786            return;
28787        }
28788        this.editable = value;
28789        if(!value){
28790            this.el.dom.setAttribute('readOnly', true);
28791            this.el.on('mousedown', this.onTriggerClick,  this);
28792            this.el.addClass('x-combo-noedit');
28793        }else{
28794            this.el.dom.removeAttribute('readOnly');
28795            this.el.un('mousedown', this.onTriggerClick,  this);
28796            this.el.removeClass('x-combo-noedit');
28797        }
28798    },
28799
28800    // private
28801    onBeforeLoad : function(){
28802        if(!this.hasFocus){
28803            return;
28804        }
28805        this.innerList.update(this.loadingText ?
28806               '<div class="loading-indicator">'+this.loadingText+'</div>' : '');
28807        this.restrictHeight();
28808        this.selectedIndex = -1;
28809    },
28810
28811    // private
28812    onLoad : function(){
28813        if(!this.hasFocus){
28814            return;
28815        }
28816        if(this.store.getCount() > 0){
28817            this.expand();
28818            this.restrictHeight();
28819            if(this.lastQuery == this.allQuery){
28820                if(this.editable){
28821                    this.el.dom.select();
28822                }
28823                if(!this.selectByValue(this.value, true)){
28824                    this.select(0, true);
28825                }
28826            }else{
28827                this.selectNext();
28828                if(this.typeAhead && this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE){
28829                    this.taTask.delay(this.typeAheadDelay);
28830                }
28831            }
28832        }else{
28833            this.onEmptyResults();
28834        }
28835        //this.el.focus();
28836    },
28837
28838    // private
28839    onTypeAhead : function(){
28840        if(this.store.getCount() > 0){
28841            var r = this.store.getAt(0);
28842            var newValue = r.data[this.displayField];
28843            var len = newValue.length;
28844            var selStart = this.getRawValue().length;
28845            if(selStart != len){
28846                this.setRawValue(newValue);
28847                this.selectText(selStart, newValue.length);
28848            }
28849        }
28850    },
28851
28852    // private
28853    onSelect : function(record, index){
28854        if(this.fireEvent('beforeselect', this, record, index) !== false){
28855            this.setValue(record.data[this.valueField || this.displayField]);
28856            this.collapse();
28857            this.fireEvent('select', this, record, index);
28858        }
28859    },
28860
28861    
28862    getValue : function(){
28863        if(this.valueField){
28864            return typeof this.value != 'undefined' ? this.value : '';
28865        }else{
28866            return Ext.form.ComboBox.superclass.getValue.call(this);
28867        }
28868    },
28869
28870    
28871    clearValue : function(){
28872        if(this.hiddenField){
28873            this.hiddenField.value = '';
28874        }
28875        this.setRawValue('');
28876        this.lastSelectionText = '';
28877        this.applyEmptyText();
28878        this.value = '';
28879    },
28880
28881    
28882    setValue : function(v){
28883        var text = v;
28884        if(this.valueField){
28885            var r = this.findRecord(this.valueField, v);
28886            if(r){
28887                text = r.data[this.displayField];
28888            }else if(this.valueNotFoundText !== undefined){
28889                text = this.valueNotFoundText;
28890            }
28891        }
28892        this.lastSelectionText = text;
28893        if(this.hiddenField){
28894            this.hiddenField.value = v;
28895        }
28896        Ext.form.ComboBox.superclass.setValue.call(this, text);
28897        this.value = v;
28898    },
28899
28900    // private
28901    findRecord : function(prop, value){
28902        var record;
28903        if(this.store.getCount() > 0){
28904            this.store.each(function(r){
28905                if(r.data[prop] == value){
28906                    record = r;
28907                    return false;
28908                }
28909            });
28910        }
28911        return record;
28912    },
28913
28914    // private
28915    onViewMove : function(e, t){
28916        this.inKeyMode = false;
28917    },
28918
28919    // private
28920    onViewOver : function(e, t){
28921        if(this.inKeyMode){ // prevent key nav and mouse over conflicts
28922            return;
28923        }
28924        var item = this.view.findItemFromChild(t);
28925        if(item){
28926            var index = this.view.indexOf(item);
28927            this.select(index, false);
28928        }
28929    },
28930
28931    // private
28932    onViewClick : function(doFocus){
28933        var index = this.view.getSelectedIndexes()[0];
28934        var r = this.store.getAt(index);
28935        if(r){
28936            this.onSelect(r, index);
28937        }
28938        if(doFocus !== false){
28939            this.el.focus();
28940        }
28941    },
28942
28943    // private
28944    restrictHeight : function(){
28945        this.innerList.dom.style.height = '';
28946        var inner = this.innerList.dom;
28947        var pad = this.list.getFrameWidth('tb')+(this.resizable?this.handleHeight:0)+this.assetHeight;
28948        var h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight);
28949        var ha = this.getPosition()[1]-Ext.getBody().getScroll().top;
28950        var hb = Ext.lib.Dom.getViewHeight()-ha-this.getSize().height;
28951        var space = Math.max(ha, hb, this.minHeight || 0)-this.list.shadowOffset-pad-5;
28952        h = Math.min(h, space, this.maxHeight);
28953
28954        this.innerList.setHeight(h);
28955        this.list.beginUpdate();
28956        this.list.setHeight(h+pad);
28957        this.list.alignTo(this.wrap, this.listAlign);
28958        this.list.endUpdate();
28959    },
28960
28961    // private
28962    onEmptyResults : function(){
28963        this.collapse();
28964    },
28965
28966    
28967    isExpanded : function(){
28968        return this.list && this.list.isVisible();
28969    },
28970
28971    
28972    selectByValue : function(v, scrollIntoView){
28973        if(v !== undefined && v !== null){
28974            var r = this.findRecord(this.valueField || this.displayField, v);
28975            if(r){
28976                this.select(this.store.indexOf(r), scrollIntoView);
28977                return true;
28978            }
28979        }
28980        return false;
28981    },
28982
28983    
28984    select : function(index, scrollIntoView){
28985        this.selectedIndex = index;
28986        this.view.select(index);
28987        if(scrollIntoView !== false){
28988            var el = this.view.getNode(index);
28989            if(el){
28990                this.innerList.scrollChildIntoView(el, false);
28991            }
28992        }
28993    },
28994
28995    // private
28996    selectNext : function(){
28997        var ct = this.store.getCount();
28998        if(ct > 0){
28999            if(this.selectedIndex == -1){
29000                this.select(0);
29001            }else if(this.selectedIndex < ct-1){
29002                this.select(this.selectedIndex+1);
29003            }
29004        }
29005    },
29006
29007    // private
29008    selectPrev : function(){
29009        var ct = this.store.getCount();
29010        if(ct > 0){
29011            if(this.selectedIndex == -1){
29012                this.select(0);
29013            }else if(this.selectedIndex != 0){
29014                this.select(this.selectedIndex-1);
29015            }
29016        }
29017    },
29018
29019    // private
29020    onKeyUp : function(e){
29021        if(this.editable !== false && !e.isSpecialKey()){
29022            this.lastKey = e.getKey();
29023            this.dqTask.delay(this.queryDelay);
29024        }
29025    },
29026
29027    // private
29028    validateBlur : function(){
29029        return !this.list || !this.list.isVisible();
29030    },
29031
29032    // private
29033    initQuery : function(){
29034        this.doQuery(this.getRawValue());
29035    },
29036
29037    // private
29038    doForce : function(){
29039        if(this.el.dom.value.length > 0){
29040            this.el.dom.value =
29041                this.lastSelectionText === undefined ? '' : this.lastSelectionText;
29042            this.applyEmptyText();
29043        }
29044    },
29045
29046    
29047    doQuery : function(q, forceAll){
29048        if(q === undefined || q === null){
29049            q = '';
29050        }
29051        var qe = {
29052            query: q,
29053            forceAll: forceAll,
29054            combo: this,
29055            cancel:false
29056        };
29057        if(this.fireEvent('beforequery', qe)===false || qe.cancel){
29058            return false;
29059        }
29060        q = qe.query;
29061        forceAll = qe.forceAll;
29062        if(forceAll === true || (q.length >= this.minChars)){
29063            if(this.lastQuery !== q){
29064                this.lastQuery = q;
29065                if(this.mode == 'local'){
29066                    this.selectedIndex = -1;
29067                    if(forceAll){
29068                        this.store.clearFilter();
29069                    }else{
29070                        this.store.filter(this.displayField, q);
29071                    }
29072                    this.onLoad();
29073                }else{
29074                    this.store.baseParams[this.queryParam] = q;
29075                    this.store.load({
29076                        params: this.getParams(q)
29077                    });
29078                    this.expand();
29079                }
29080            }else{
29081                this.selectedIndex = -1;
29082                this.onLoad();
29083            }
29084        }
29085    },
29086
29087    // private
29088    getParams : function(q){
29089        var p = {};
29090        //p[this.queryParam] = q;
29091        if(this.pageSize){
29092            p.start = 0;
29093            p.limit = this.pageSize;
29094        }
29095        return p;
29096    },
29097
29098    
29099    collapse : function(){
29100        if(!this.isExpanded()){
29101            return;
29102        }
29103        this.list.hide();
29104        Ext.getDoc().un('mousewheel', this.collapseIf, this);
29105        Ext.getDoc().un('mousedown', this.collapseIf, this);
29106        this.fireEvent('collapse', this);
29107    },
29108
29109    // private
29110    collapseIf : function(e){
29111        if(!e.within(this.wrap) && !e.within(this.list)){
29112            this.collapse();
29113        }
29114    },
29115
29116    
29117    expand : function(){
29118        if(this.isExpanded() || !this.hasFocus){
29119            return;
29120        }
29121        this.list.alignTo(this.wrap, this.listAlign);
29122        this.list.show();
29123        this.innerList.setOverflow('auto'); // necessary for FF 2.0/Mac
29124        Ext.getDoc().on('mousewheel', this.collapseIf, this);
29125        Ext.getDoc().on('mousedown', this.collapseIf, this);
29126        this.fireEvent('expand', this);
29127    },
29128
29129    
29130    // private
29131    // Implements the default empty TriggerField.onTriggerClick function
29132    onTriggerClick : function(){
29133        if(this.disabled){
29134            return;
29135        }
29136        if(this.isExpanded()){
29137            this.collapse();
29138            this.el.focus();
29139        }else {
29140            this.onFocus({});
29141            if(this.triggerAction == 'all') {
29142                this.doQuery(this.allQuery, true);
29143            } else {
29144                this.doQuery(this.getRawValue());
29145            }
29146            this.el.focus();
29147        }
29148    }
29149
29150    
29151    
29152    
29153    
29154
29155});
29156Ext.reg('combo', Ext.form.ComboBox);
29157
29158Ext.form.Checkbox = Ext.extend(Ext.form.Field,  {
29159    
29160    checkedCls: 'x-form-check-checked',
29161    
29162    focusCls: 'x-form-check-focus',
29163    
29164    overCls: 'x-form-check-over',
29165    
29166    mouseDownCls: 'x-form-check-down',
29167    
29168    tabIndex: 0,
29169    
29170    checked: false,
29171    
29172    defaultAutoCreate: {tag: 'input', type: 'checkbox', autocomplete: 'off'},
29173    
29174    
29175    
29176    
29177
29178
29179    // private
29180    baseCls: 'x-form-check',
29181
29182    // private
29183    initComponent : function(){
29184        Ext.form.Checkbox.superclass.initComponent.call(this);
29185        this.addEvents(
29186            
29187            'check'
29188        );
29189    },
29190
29191    // private
29192    initEvents : function(){
29193        Ext.form.Checkbox.superclass.initEvents.call(this);
29194        this.initCheckEvents();
29195    },
29196
29197    // private
29198    initCheckEvents : function(){
29199        this.innerWrap.removeAllListeners();
29200        this.innerWrap.addClassOnOver(this.overCls);
29201        this.innerWrap.addClassOnClick(this.mouseDownCls);
29202        this.innerWrap.on('click', this.onClick, this);
29203        this.innerWrap.on('keyup', this.onKeyUp, this);
29204    },
29205
29206    // private
29207    onRender : function(ct, position){
29208        Ext.form.Checkbox.superclass.onRender.call(this, ct, position);
29209        if(this.inputValue !== undefined){
29210            this.el.dom.value = this.inputValue;
29211        }
29212        this.el.addClass('x-hidden');
29213
29214        this.innerWrap = this.el.wrap({
29215            tabIndex: this.tabIndex,
29216            cls: this.baseCls+'-wrap-inner'
29217        });
29218        this.wrap = this.innerWrap.wrap({cls: this.baseCls+'-wrap'});
29219
29220        if(this.boxLabel){
29221            this.labelEl = this.innerWrap.createChild({
29222                tag: 'label',
29223                htmlFor: this.el.id,
29224                cls: 'x-form-cb-label',
29225                html: this.boxLabel
29226            });
29227        }
29228
29229        this.imageEl = this.innerWrap.createChild({
29230            tag: 'img',
29231            src: Ext.BLANK_IMAGE_URL,
29232            cls: this.baseCls
29233        }, this.el);
29234
29235        if(this.checked){
29236            this.setValue(true);
29237        }else{
29238            this.checked = this.el.dom.checked;
29239        }
29240        this.originalValue = this.checked;
29241    },
29242    
29243    // private
29244    afterRender : function(){
29245        Ext.form.Checkbox.superclass.afterRender.call(this);
29246        this.wrap[this.checked? 'addClass' : 'removeClass'](this.checkedCls);
29247    },
29248
29249    // private
29250    onDestroy : function(){
29251        if(this.rendered){
29252            Ext.destroy(this.imageEl, this.labelEl, this.innerWrap, this.wrap);
29253        }
29254        Ext.form.Checkbox.superclass.onDestroy.call(this);
29255    },
29256
29257    // private
29258    onFocus: function(e) {
29259        Ext.form.Checkbox.superclass.onFocus.call(this, e);
29260        this.el.addClass(this.focusCls);
29261    },
29262
29263    // private
29264    onBlur: function(e) {
29265        Ext.form.Checkbox.superclass.onBlur.call(this, e);
29266        this.el.removeClass(this.focusCls);
29267    },
29268
29269    // private
29270    onResize : function(){
29271        Ext.form.Checkbox.superclass.onResize.apply(this, arguments);
29272        if(!this.boxLabel && !this.fieldLabel){
29273            this.el.alignTo(this.wrap, 'c-c');
29274        }
29275    },
29276
29277    // private
29278    onKeyUp : function(e){
29279        if(e.getKey() == Ext.EventObject.SPACE){
29280            this.onClick(e);
29281        }
29282    },
29283
29284    // private
29285    onClick : function(e){
29286        if (!this.disabled && !this.readOnly) {
29287            this.toggleValue();
29288        }
29289        e.stopEvent();
29290    },
29291
29292    // private
29293    onEnable : function(){
29294        Ext.form.Checkbox.superclass.onEnable.call(this);
29295        this.initCheckEvents();
29296    },
29297
29298    // private
29299    onDisable : function(){
29300        Ext.form.Checkbox.superclass.onDisable.call(this);
29301        this.innerWrap.removeAllListeners();
29302    },
29303
29304    toggleValue : function(){
29305        this.setValue(!this.checked);
29306    },
29307
29308    // private
29309    getResizeEl : function(){
29310        if(!this.resizeEl){
29311            this.resizeEl = Ext.isSafari ? this.wrap : (this.wrap.up('.x-form-element', 5) || this.wrap);
29312        }
29313        return this.resizeEl;
29314    },
29315
29316    // private
29317    getPositionEl : function(){
29318        return this.wrap;
29319    },
29320
29321    // private
29322    getActionEl : function(){
29323        return this.wrap;
29324    },
29325
29326    
29327    markInvalid : Ext.emptyFn,
29328    
29329    clearInvalid : Ext.emptyFn,
29330
29331    // private
29332    initValue : Ext.emptyFn,
29333
29334    
29335    getValue : function(){
29336        if(this.rendered){
29337            return this.el.dom.checked;
29338        }
29339        return this.checked;
29340    },
29341
29342    
29343    setValue : function(v) {
29344        var checked = this.checked;
29345        this.checked = (v === true || v === 'true' || v == '1' || String(v).toLowerCase() == 'on');
29346        
29347        if(this.rendered){
29348            this.el.dom.checked = this.checked;
29349            this.el.dom.defaultChecked = this.checked;
29350            this.wrap[this.checked? 'addClass' : 'removeClass'](this.checkedCls);
29351        }
29352
29353        if(checked != this.checked){
29354            this.fireEvent("check", this, this.checked);
29355            if(this.handler){
29356                this.handler.call(this.scope || this, this, this.checked);
29357            }
29358        }
29359    }
29360
29361    
29362    
29363    
29364});
29365Ext.reg('checkbox', Ext.form.Checkbox);
29366
29367
29368Ext.form.CheckboxGroup = Ext.extend(Ext.form.Field, {
29369    
29370    
29371    columns : 'auto',
29372    
29373    vertical : false,
29374    
29375    allowBlank : true,
29376    
29377    blankText : "Tem que seleccionar pelo menos um item neste grupo",
29378    
29379    // private
29380    defaultType : 'checkbox',
29381    
29382    // private
29383    groupCls: 'x-form-check-group',
29384    
29385    // private
29386    onRender : function(ct, position){
29387        if(!this.el){
29388            var panelCfg = {
29389                cls: this.groupCls,
29390                layout: 'column',
29391                border: false,
29392                renderTo: ct
29393            };
29394            var colCfg = {
29395                defaultType: this.defaultType,
29396                layout: 'form',
29397                border: false,
29398                defaults: {
29399                    hideLabel: true,
29400                    anchor: '100%'
29401                }
29402            }
29403            
29404            if(this.items[0].items){
29405                
29406                // The container has standard ColumnLayout configs, so pass them in directly
29407                
29408                Ext.apply(panelCfg, {
29409                    layoutConfig: {columns: this.items.length},
29410                    defaults: this.defaults,
29411                    items: this.items
29412                })
29413                for(var i=0, len=this.items.length; i<len; i++){
29414                    Ext.applyIf(this.items[i], colCfg);
29415                };
29416                
29417            }else{
29418                
29419                // The container has field item configs, so we have to generate the column
29420                // panels first then move the items into the columns as needed.
29421                
29422                var numCols, cols = [];
29423                
29424                if(typeof this.columns == 'string'){ // 'auto' so create a col per item
29425                    this.columns = this.items.length;
29426                }
29427                if(!Ext.isArray(this.columns)){
29428                    var cs = [];
29429                    for(var i=0; i<this.columns; i++){
29430                        cs.push((100/this.columns)*.01); // distribute by even %
29431                    }
29432                    this.columns = cs;
29433                }
29434                
29435                numCols = this.columns.length;
29436                
29437                // Generate the column configs with the correct width setting
29438                for(var i=0; i<numCols; i++){
29439                    var cc = Ext.apply({items:[]}, colCfg);
29440                    cc[this.columns[i] <= 1 ? 'columnWidth' : 'width'] = this.columns[i];
29441                    if(this.defaults){
29442                        cc.defaults = Ext.apply(cc.defaults || {}, this.defaults)
29443                    }
29444                    cols.push(cc);
29445                };
29446                
29447                // Distribute the original items into the columns
29448                if(this.vertical){
29449                    var rows = Math.ceil(this.items.length / numCols), ri = 0;
29450                    for(var i=0, len=this.items.length; i<len; i++){
29451                        if(i>0 && i%rows==0){
29452                            ri++;
29453                        }
29454                        if(this.items[i].fieldLabel){
29455                            this.items[i].hideLabel = false;
29456                        }
29457                        cols[ri].items.push(this.items[i]);
29458                    };
29459                }else{
29460                    for(var i=0, len=this.items.length; i<len; i++){
29461                        var ci = i % numCols;
29462                        if(this.items[i].fieldLabel){
29463                            this.items[i].hideLabel = false;
29464                        }
29465                        cols[ci].items.push(this.items[i]);
29466                    };
29467                }
29468                
29469                Ext.apply(panelCfg, {
29470                    layoutConfig: {columns: numCols},
29471                    items: cols
29472                });
29473            }
29474            
29475            this.panel = new Ext.Panel(panelCfg);
29476            this.el = this.panel.getEl();
29477            
29478            if(this.forId && this.itemCls){
29479                var l = this.el.up(this.itemCls).child('label', true);
29480                if(l){
29481                    l.setAttribute('htmlFor', this.forId);
29482                }
29483            }
29484            
29485            var fields = this.panel.findBy(function(c){
29486                return c.isFormField;
29487            }, this);
29488            
29489            this.items = new Ext.util.MixedCollection();
29490            this.items.addAll(fields);
29491        }
29492        Ext.form.CheckboxGroup.superclass.onRender.call(this, ct, position);
29493    },
29494    
29495    // private
29496    validateValue : function(value){
29497        if(!this.allowBlank){
29498            var blank = true;
29499            this.items.each(function(f){
29500                if(f.checked){
29501                    return blank = false;
29502                }
29503            }, this);
29504            if(blank){
29505                this.markInvalid(this.blankText);
29506                return false;
29507            }
29508        }
29509        return true;
29510    },
29511    
29512    // private
29513    onDisable : function(){
29514        this.items.each(function(item){
29515            item.disable();
29516        })
29517    },
29518
29519    // private
29520    onEnable : function(){
29521        this.items.each(function(item){
29522            item.enable();
29523        })
29524    },
29525    
29526    // private
29527    onResize : function(w, h){
29528        this.panel.setSize(w, h);
29529        this.panel.doLayout();
29530    },
29531    
29532    // inherit docs from Field
29533    reset : function(){
29534        Ext.form.CheckboxGroup.superclass.reset.call(this);
29535        this.items.each(function(c){
29536            if(c.reset){
29537                c.reset();
29538            }
29539        }, this);
29540    },
29541    
29542    
29543    
29544    initValue : Ext.emptyFn,
29545    
29546    getValue : Ext.emptyFn,
29547    
29548    getRawValue : Ext.emptyFn,
29549    
29550    setValue : Ext.emptyFn,
29551    
29552    setRawValue : Ext.emptyFn
29553    
29554});
29555
29556Ext.reg('checkboxgroup', Ext.form.CheckboxGroup);
29557
29558
29559Ext.form.Radio = Ext.extend(Ext.form.Checkbox, {
29560    // private
29561    inputType: 'radio',
29562    // private
29563    baseCls: 'x-form-radio',
29564    
29565    
29566    getGroupValue : function(){
29567        var c = this.getParent().child('input[name='+this.el.dom.name+']:checked', true);
29568        return c ? c.value : null;
29569    },
29570    
29571    // private
29572    getParent : function(){
29573        return this.el.up('form') || Ext.getBody();
29574    },
29575
29576    // private
29577    toggleValue : function() {
29578        if(!this.checked){
29579            var els = this.getParent().select('input[name='+this.el.dom.name+']');
29580            els.each(function(el){
29581                if(el.dom.id == this.id){
29582                    this.setValue(true);
29583                }else{
29584                    Ext.getCmp(el.dom.id).setValue(false);
29585                }
29586            }, this);
29587        }
29588    },
29589    
29590    
29591    setValue : function(v){
29592        if(typeof v=='boolean') {
29593            Ext.form.Radio.superclass.setValue.call(this, v);
29594        }else{
29595            var r = this.getParent().child('input[name='+this.el.dom.name+'][value='+v+']', true);
29596            if(r && !r.checked){
29597                Ext.getCmp(r.id).toggleValue();
29598            };
29599        }
29600    },
29601    
29602    
29603    markInvalid : Ext.emptyFn,
29604    
29605    clearInvalid : Ext.emptyFn
29606    
29607});
29608Ext.reg('radio', Ext.form.Radio);
29609
29610
29611Ext.form.RadioGroup = Ext.extend(Ext.form.CheckboxGroup, {
29612    
29613    allowBlank : true,
29614    
29615    blankText : "Tem que seleccionar um item neste grupo",
29616    
29617    // private
29618    defaultType : 'radio',
29619    
29620    // private
29621    groupCls: 'x-form-radio-group'
29622});
29623
29624Ext.reg('radiogroup', Ext.form.RadioGroup);
29625
29626
29627Ext.form.Hidden = Ext.extend(Ext.form.Field, {
29628    // private
29629    inputType : 'hidden',
29630
29631    // private
29632    onRender : function(){
29633        Ext.form.Hidden.superclass.onRender.apply(this, arguments);
29634    },
29635
29636    // private
29637    initEvents : function(){
29638        this.originalValue = this.getValue();
29639    },
29640
29641    // These are all private overrides
29642    setSize : Ext.emptyFn,
29643    setWidth : Ext.emptyFn,
29644    setHeight : Ext.emptyFn,
29645    setPosition : Ext.emptyFn,
29646    setPagePosition : Ext.emptyFn,
29647    markInvalid : Ext.emptyFn,
29648    clearInvalid : Ext.emptyFn
29649});
29650Ext.reg('hidden', Ext.form.Hidden);
29651
29652Ext.form.BasicForm = function(el, config){
29653    Ext.apply(this, config);
29654    
29655    this.items = new Ext.util.MixedCollection(false, function(o){
29656        return o.id || (o.id = Ext.id());
29657    });
29658    this.addEvents(
29659        
29660        'beforeaction',
29661        
29662        'actionfailed',
29663        
29664        'actioncomplete'
29665    );
29666
29667    if(el){
29668        this.initEl(el);
29669    }
29670    Ext.form.BasicForm.superclass.constructor.call(this);
29671};
29672
29673Ext.extend(Ext.form.BasicForm, Ext.util.Observable, {
29674    
29675    
29676    
29677    
29678    
29679    
29680    
29681    timeout: 30,
29682
29683    // private
29684    activeAction : null,
29685
29686    
29687    trackResetOnLoad : false,
29688
29689    
29690    
29691
29692    // private
29693    initEl : function(el){
29694        this.el = Ext.get(el);
29695        this.id = this.el.id || Ext.id();
29696        if(!this.standardSubmit){
29697            this.el.on('submit', this.onSubmit, this);
29698        }
29699        this.el.addClass('x-form');
29700    },
29701
29702    
29703    getEl: function(){
29704        return this.el;
29705    },
29706
29707    // private
29708    onSubmit : function(e){
29709        e.stopEvent();
29710    },
29711
29712    // private
29713    destroy: function() {
29714        this.items.each(function(f){
29715            Ext.destroy(f);
29716        });
29717        if(this.el){
29718            this.el.removeAllListeners();
29719            this.el.remove();
29720        }
29721        this.purgeListeners();
29722    },
29723
29724    
29725    isValid : function(){
29726        var valid = true;
29727        this.items.each(function(f){
29728           if(!f.validate()){
29729               valid = false;
29730           }
29731        });
29732        return valid;
29733    },
29734
29735    
29736    isDirty : function(){
29737        var dirty = false;
29738        this.items.each(function(f){
29739           if(f.isDirty()){
29740               dirty = true;
29741               return false;
29742           }
29743        });
29744        return dirty;
29745    },
29746
29747    
29748    doAction : function(action, options){
29749        if(typeof action == 'string'){
29750            action = new Ext.form.Action.ACTION_TYPES[action](this, options);
29751        }
29752        if(this.fireEvent('beforeaction', this, action) !== false){
29753            this.beforeAction(action);
29754            action.run.defer(100, action);
29755        }
29756        return this;
29757    },
29758
29759    
29760    submit : function(options){
29761        if(this.standardSubmit){
29762            var v = this.isValid();
29763            if(v){
29764                this.el.dom.submit();
29765            }
29766            return v;
29767        }
29768        this.doAction('submit', options);
29769        return this;
29770    },
29771
29772    
29773    load : function(options){
29774        this.doAction('load', options);
29775        return this;
29776    },
29777
29778    
29779    updateRecord : function(record){
29780        record.beginEdit();
29781        var fs = record.fields;
29782        fs.each(function(f){
29783            var field = this.findField(f.name);
29784            if(field){
29785                record.set(f.name, field.getValue());
29786            }
29787        }, this);
29788        record.endEdit();
29789        return this;
29790    },
29791
29792    
29793    loadRecord : function(record){
29794        this.setValues(record.data);
29795        return this;
29796    },
29797
29798    // private
29799    beforeAction : function(action){
29800        var o = action.options;
29801        if(o.waitMsg){
29802            if(this.waitMsgTarget === true){
29803                this.el.mask(o.waitMsg, 'x-mask-loading');
29804            }else if(this.waitMsgTarget){
29805                this.waitMsgTarget = Ext.get(this.waitMsgTarget);
29806                this.waitMsgTarget.mask(o.waitMsg, 'x-mask-loading');
29807            }else{
29808                Ext.MessageBox.wait(o.waitMsg, o.waitTitle || this.waitTitle || 'Please Wait...');
29809            }
29810        }
29811    },
29812
29813    // private
29814    afterAction : function(action, success){
29815        this.activeAction = null;
29816        var o = action.options;
29817        if(o.waitMsg){
29818            if(this.waitMsgTarget === true){
29819                this.el.unmask();
29820            }else if(this.waitMsgTarget){
29821                this.waitMsgTarget.unmask();
29822            }else{
29823                Ext.MessageBox.updateProgress(1);
29824                Ext.MessageBox.hide();
29825            }
29826        }
29827        if(success){
29828            if(o.reset){
29829                this.reset();
29830            }
29831            Ext.callback(o.success, o.scope, [this, action]);
29832            this.fireEvent('actioncomplete', this, action);
29833        }else{
29834            Ext.callback(o.failure, o.scope, [this, action]);
29835            this.fireEvent('actionfailed', this, action);
29836        }
29837    },
29838
29839    
29840    findField : function(id){
29841        var field = this.items.get(id);
29842        if(!field){
29843            this.items.each(function(f){
29844                if(f.isFormField && (f.dataIndex == id || f.id == id || f.getName() == id)){
29845                    field = f;
29846                    return false;
29847                }
29848            });
29849        }
29850        return field || null;
29851    },
29852
29853
29854    
29855    markInvalid : function(errors){
29856        if(Ext.isArray(errors)){
29857            for(var i = 0, len = errors.length; i < len; i++){
29858                var fieldError = errors[i];
29859                var f = this.findField(fieldError.id);
29860                if(f){
29861                    f.markInvalid(fieldError.msg);
29862                }
29863            }
29864        }else{
29865            var field, id;
29866            for(id in errors){
29867                if(typeof errors[id] != 'function' && (field = this.findField(id))){
29868                    field.markInvalid(errors[id]);
29869                }
29870            }
29871        }
29872        return this;
29873    },
29874
29875    
29876    setValues : function(values){
29877        if(Ext.isArray(values)){ // array of objects
29878            for(var i = 0, len = values.length; i < len; i++){
29879                var v = values[i];
29880                var f = this.findField(v.id);
29881                if(f){
29882                    f.setValue(v.value);
29883                    if(this.trackResetOnLoad){
29884                        f.originalValue = f.getValue();
29885                    }
29886                }
29887            }
29888        }else{ // object hash
29889            var field, id;
29890            for(id in values){
29891                if(typeof values[id] != 'function' && (field = this.findField(id))){
29892                    field.setValue(values[id]);
29893                    if(this.trackResetOnLoad){
29894                        field.originalValue = field.getValue();
29895                    }
29896                }
29897            }
29898        }
29899        return this;
29900    },
29901
29902    
29903    getValues : function(asString){
29904        var fs = Ext.lib.Ajax.serializeForm(this.el.dom);
29905        if(asString === true){
29906            return fs;
29907        }
29908        return Ext.urlDecode(fs);
29909    },
29910
29911    
29912    clearInvalid : function(){
29913        this.items.each(function(f){
29914           f.clearInvalid();
29915        });
29916        return this;
29917    },
29918
29919    
29920    reset : function(){
29921        this.items.each(function(f){
29922            f.reset();
29923        });
29924        return this;
29925    },
29926
29927    
29928    add : function(){
29929        this.items.addAll(Array.prototype.slice.call(arguments, 0));
29930        return this;
29931    },
29932
29933
29934    
29935    remove : function(field){
29936        this.items.remove(field);
29937        return this;
29938    },
29939
29940    
29941    render : function(){
29942        this.items.each(function(f){
29943            if(f.isFormField && !f.rendered && document.getElementById(f.id)){ // if the element exists
29944                f.applyToMarkup(f.id);
29945            }
29946        });
29947        return this;
29948    },
29949
29950    
29951    applyToFields : function(o){
29952        this.items.each(function(f){
29953           Ext.apply(f, o);
29954        });
29955        return this;
29956    },
29957
29958    
29959    applyIfToFields : function(o){
29960        this.items.each(function(f){
29961           Ext.applyIf(f, o);
29962        });
29963        return this;
29964    }
29965});
29966
29967// back compat
29968Ext.BasicForm = Ext.form.BasicForm;
29969
29970Ext.FormPanel = Ext.extend(Ext.Panel, {
29971	
29972    
29973    
29974    
29975    
29976    buttonAlign:'center',
29977
29978    
29979    minButtonWidth:75,
29980
29981    
29982    labelAlign:'left',
29983
29984    
29985    monitorValid : false,
29986
29987    
29988    monitorPoll : 200,
29989
29990    
29991    layout: 'form',
29992
29993    // private
29994    initComponent :function(){
29995        this.form = this.createForm();
29996
29997        this.bodyCfg = {
29998            tag: 'form',
29999            cls: this.baseCls + '-body',
30000            method : this.method || 'POST',
30001            id : this.formId || Ext.id()
30002        };
30003        if(this.fileUpload) {
30004            this.bodyCfg.enctype = 'multipart/form-data';
30005        }
30006
30007        Ext.FormPanel.superclass.initComponent.call(this);
30008
30009        this.initItems();
30010
30011        this.addEvents(
30012            
30013            'clientvalidation'
30014        );
30015
30016        this.relayEvents(this.form, ['beforeaction', 'actionfailed', 'actioncomplete']);
30017    },
30018
30019    // private
30020    createForm: function(){
30021        delete this.initialConfig.listeners;
30022        return new Ext.form.BasicForm(null, this.initialConfig);
30023    },
30024
30025    // private
30026    initFields : function(){
30027        var f = this.form;
30028        var formPanel = this;
30029        var fn = function(c){
30030            if(c.isFormField){
30031                f.add(c);
30032            }else if(c.doLayout && c != formPanel){
30033                Ext.applyIf(c, {
30034                    labelAlign: c.ownerCt.labelAlign,
30035                    labelWidth: c.ownerCt.labelWidth,
30036                    itemCls: c.ownerCt.itemCls
30037                });
30038                if(c.items){
30039                    c.items.each(fn);
30040                }
30041            }
30042        }
30043        this.items.each(fn);
30044    },
30045
30046    // private
30047    getLayoutTarget : function(){
30048        return this.form.el;
30049    },
30050
30051    
30052    getForm : function(){
30053        return this.form;
30054    },
30055
30056    // private
30057    onRender : function(ct, position){
30058        this.initFields();
30059
30060        Ext.FormPanel.superclass.onRender.call(this, ct, position);
30061        this.form.initEl(this.body);
30062    },
30063    
30064    // private
30065    beforeDestroy: function(){
30066        Ext.FormPanel.superclass.beforeDestroy.call(this);
30067        this.stopMonitoring();
30068        Ext.destroy(this.form);
30069    },
30070
30071    // private
30072    initEvents : function(){
30073        Ext.FormPanel.superclass.initEvents.call(this);
30074        this.items.on('remove', this.onRemove, this);
30075		this.items.on('add', this.onAdd, this);
30076        if(this.monitorValid){ // initialize after render
30077            this.startMonitoring();
30078        }
30079    },
30080    
30081    // private
30082	onAdd : function(ct, c) {
30083		if (c.isFormField) {
30084			this.form.add(c);
30085		}
30086	},
30087	
30088	// private
30089	onRemove : function(c) {
30090		if (c.isFormField) {
30091			Ext.destroy(c.container.up('.x-form-item'));
30092			this.form.remove(c);
30093		}
30094	},
30095
30096    
30097    startMonitoring : function(){
30098        if(!this.bound){
30099            this.bound = true;
30100            Ext.TaskMgr.start({
30101                run : this.bindHandler,
30102                interval : this.monitorPoll || 200,
30103                scope: this
30104            });
30105        }
30106    },
30107
30108    
30109    stopMonitoring : function(){
30110        this.bound = false;
30111    },
30112
30113    
30114    load : function(){
30115        this.form.load.apply(this.form, arguments);  
30116    },
30117
30118    // private
30119    onDisable : function(){
30120        Ext.FormPanel.superclass.onDisable.call(this);
30121        if(this.form){
30122            this.form.items.each(function(){
30123                 this.disable();
30124            });
30125        }
30126    },
30127
30128    // private
30129    onEnable : function(){
30130        Ext.FormPanel.superclass.onEnable.call(this);
30131        if(this.form){
30132            this.form.items.each(function(){
30133                 this.enable();
30134            });
30135        }
30136    },
30137
30138    // private
30139    bindHandler : function(){
30140        if(!this.bound){
30141            return false; // stops binding
30142        }
30143        var valid = true;
30144        this.form.items.each(function(f){
30145            if(!f.isValid(true)){
30146                valid = false;
30147                return false;
30148            }
30149        });
30150        if(this.buttons){
30151            for(var i = 0, len = this.buttons.length; i < len; i++){
30152                var btn = this.buttons[i];
30153                if(btn.formBind === true && btn.disabled === valid){
30154                    btn.setDisabled(!valid);
30155                }
30156            }
30157        }
30158        this.fireEvent('clientvalidation', this, valid);
30159    }
30160});
30161Ext.reg('form', Ext.FormPanel);
30162
30163Ext.form.FormPanel = Ext.FormPanel;
30164
30165
30166
30167Ext.form.FieldSet = Ext.extend(Ext.Panel, {
30168    
30169    
30170    
30171    
30172    
30173    baseCls:'x-fieldset',
30174    
30175    layout: 'form',
30176    
30177    animCollapse: false,
30178
30179    // private
30180    onRender : function(ct, position){
30181        if(!this.el){
30182            this.el = document.createElement('fieldset');
30183            this.el.id = this.id;
30184            if (this.title || this.header || this.checkboxToggle) {
30185                this.el.appendChild(document.createElement('legend')).className = 'x-fieldset-header';
30186            }
30187        }
30188
30189        Ext.form.FieldSet.superclass.onRender.call(this, ct, position);
30190
30191        if(this.checkboxToggle){
30192            var o = typeof this.checkboxToggle == 'object' ?
30193                    this.checkboxToggle :
30194                    {tag: 'input', type: 'checkbox', name: this.checkboxName || this.id+'-checkbox'};
30195            this.checkbox = this.header.insertFirst(o);
30196            this.checkbox.dom.checked = !this.collapsed;
30197            this.checkbox.on('click', this.onCheckClick, this);
30198        }
30199    },
30200
30201    // private
30202    onCollapse : function(doAnim, animArg){
30203        if(this.checkbox){
30204            this.checkbox.dom.checked = false;
30205        }
30206        Ext.form.FieldSet.superclass.onCollapse.call(this, doAnim, animArg);
30207
30208    },
30209
30210    // private
30211    onExpand : function(doAnim, animArg){
30212        if(this.checkbox){
30213            this.checkbox.dom.checked = true;
30214        }
30215        Ext.form.FieldSet.superclass.onExpand.call(this, doAnim, animArg);
30216    },
30217
30218    
30219    onCheckClick : function(){
30220        this[this.checkbox.dom.checked ? 'expand' : 'collapse']();
30221    },
30222    
30223    // private
30224    beforeDestroy : function(){
30225        if(this.checkbox){
30226            this.checkbox.un('click', this.onCheckClick, this);
30227        }
30228        Ext.form.FieldSet.superclass.beforeDestroy.call(this);
30229    }
30230
30231    
30232    
30233    
30234    
30235    
30236    
30237    
30238    
30239    
30240    
30241    
30242    
30243    
30244    
30245    
30246    
30247    
30248    
30249    
30250    
30251    
30252    
30253    
30254    
30255    
30256    
30257    
30258    
30259    
30260    
30261    
30262    
30263    
30264    
30265    
30266    
30267    
30268});
30269Ext.reg('fieldset', Ext.form.FieldSet);
30270
30271
30272
30273
30274Ext.form.HtmlEditor = Ext.extend(Ext.form.Field, {
30275    
30276    enableFormat : true,
30277    
30278    enableFontSize : true,
30279    
30280    enableColors : true,
30281    
30282    enableAlignments : true,
30283    
30284    enableLists : true,
30285    
30286    enableSourceEdit : true,
30287    
30288    enableLinks : true,
30289    
30290    enableFont : true,
30291    
30292    createLinkText : 'Por favor introduza o URL para o link:',
30293    
30294    defaultLinkValue : 'http:/'+'/',
30295    
30296    fontFamilies : [
30297        'Arial',
30298        'Courier New',
30299        'Tahoma',
30300        'Times New Roman',
30301        'Verdana'
30302    ],
30303    defaultFont: 'tahoma',
30304
30305    // private properties
30306    validationEvent : false,
30307    deferHeight: true,
30308    initialized : false,
30309    activated : false,
30310    sourceEditMode : false,
30311    onFocus : Ext.emptyFn,
30312    iframePad:3,
30313    hideMode:'offsets',
30314    defaultAutoCreate : {
30315        tag: "textarea",
30316        style:"width:500px;height:300px;",
30317        autocomplete: "off"
30318    },
30319
30320    // private
30321    initComponent : function(){
30322        this.addEvents(
30323            
30324            'initialize',
30325            
30326            'activate',
30327             
30328            'beforesync',
30329             
30330            'beforepush',
30331             
30332            'sync',
30333             
30334            'push',
30335             
30336            'editmodechange'
30337        )
30338    },
30339
30340    // private
30341    createFontOptions : function(){
30342        var buf = [], fs = this.fontFamilies, ff, lc;
30343        for(var i = 0, len = fs.length; i< len; i++){
30344            ff = fs[i];
30345            lc = ff.toLowerCase();
30346            buf.push(
30347                '<option value="',lc,'" style="font-family:',ff,';"',
30348                    (this.defaultFont == lc ? ' selected="true">' : '>'),
30349                    ff,
30350                '</option>'
30351            );
30352        }
30353        return buf.join('');
30354    },
30355    
30356    
30357    createToolbar : function(editor){
30358        
30359        var tipsEnabled = Ext.QuickTips && Ext.QuickTips.isEnabled();
30360        
30361        function btn(id, toggle, handler){
30362            return {
30363                itemId : id,
30364                cls : 'x-btn-icon x-edit-'+id,
30365                enableToggle:toggle !== false,
30366                scope: editor,
30367                handler:handler||editor.relayBtnCmd,
30368                clickEvent:'mousedown',
30369                tooltip: tipsEnabled ? editor.buttonTips[id] || undefined : undefined,
30370                tabIndex:-1
30371            };
30372        }
30373
30374        // build the toolbar
30375        var tb = new Ext.Toolbar({
30376            renderTo:this.wrap.dom.firstChild
30377        });
30378
30379        // stop form submits
30380        tb.el.on('click', function(e){
30381            e.preventDefault();
30382        });
30383
30384        if(this.enableFont && !Ext.isSafari2){
30385            this.fontSelect = tb.el.createChild({
30386                tag:'select',
30387                cls:'x-font-select',
30388                html: this.createFontOptions()
30389            });
30390            this.fontSelect.on('change', function(){
30391                var font = this.fontSelect.dom.value;
30392                this.relayCmd('fontname', font);
30393                this.deferFocus();
30394            }, this);
30395            tb.add(
30396                this.fontSelect.dom,
30397                '-'
30398            );
30399        };
30400
30401        if(this.enableFormat){
30402            tb.add(
30403                btn('bold'),
30404                btn('italic'),
30405                btn('underline')
30406            );
30407        };
30408
30409        if(this.enableFontSize){
30410            tb.add(
30411                '-',
30412                btn('increasefontsize', false, this.adjustFont),
30413                btn('decreasefontsize', false, this.adjustFont)
30414            );
30415        };
30416
30417        if(this.enableColors){
30418            tb.add(
30419                '-', {
30420                    itemId:'forecolor',
30421                    cls:'x-btn-icon x-edit-forecolor',
30422                    clickEvent:'mousedown',
30423                    tooltip: tipsEnabled ? editor.buttonTips['forecolor'] || undefined : undefined,
30424                    tabIndex:-1,
30425                    menu : new Ext.menu.ColorMenu({
30426                        allowReselect: true,
30427                        focus: Ext.emptyFn,
30428                        value:'000000',
30429                        plain:true,
30430                        selectHandler: function(cp, color){
30431                            this.execCmd('forecolor', Ext.isSafari || Ext.isIE ? '#'+color : color);
30432                            this.deferFocus();
30433                        },
30434                        scope: this,
30435                        clickEvent:'mousedown'
30436                    })
30437                }, {
30438                    itemId:'backcolor',
30439                    cls:'x-btn-icon x-edit-backcolor',
30440                    clickEvent:'mousedown',
30441                    tooltip: tipsEnabled ? editor.buttonTips['backcolor'] || undefined : undefined,
30442                    tabIndex:-1,
30443                    menu : new Ext.menu.ColorMenu({
30444                        focus: Ext.emptyFn,
30445                        value:'FFFFFF',
30446                        plain:true,
30447                        allowReselect: true,
30448                        selectHandler: function(cp, color){
30449                            if(Ext.isGecko){
30450                                this.execCmd('useCSS', false);
30451                                this.execCmd('hilitecolor', color);
30452                                this.execCmd('useCSS', true);
30453                                this.deferFocus();
30454                            }else{
30455                                this.execCmd(Ext.isOpera ? 'hilitecolor' : 'backcolor', Ext.isSafari || Ext.isIE ? '#'+color : color);
30456                                this.deferFocus();
30457                            }
30458                        },
30459                        scope:this,
30460                        clickEvent:'mousedown'
30461                    })
30462                }
30463            );
30464        };
30465
30466        if(this.enableAlignments){
30467            tb.add(
30468                '-',
30469                btn('justifyleft'),
30470                btn('justifycenter'),
30471                btn('justifyright')
30472            );
30473        };
30474
30475        if(!Ext.isSafari2){
30476            if(this.enableLinks){
30477                tb.add(
30478                    '-',
30479                    btn('createlink', false, this.createLink)
30480                );
30481            };
30482
30483            if(this.enableLists){
30484                tb.add(
30485                    '-',
30486                    btn('insertorderedlist'),
30487                    btn('insertunorderedlist')
30488                );
30489            }
30490            if(this.enableSourceEdit){
30491                tb.add(
30492                    '-',
30493                    btn('sourceedit', true, function(btn){
30494                        this.toggleSourceEdit(btn.pressed);
30495                    })
30496                );
30497            }
30498        }
30499
30500        this.tb = tb;
30501    },
30502
30503    
30504    getDocMarkup : function(){
30505        return '<html><head><style type="text/css">body{border:0;margin:0;padding:3px;height:98%;cursor:text;}</style></head><body></body></html>';
30506    },
30507
30508    // private
30509    getEditorBody : function(){
30510        return this.doc.body || this.doc.documentElement;
30511    },
30512
30513    // private
30514    getDoc : function(){
30515        return Ext.isIE ? this.getWin().document : (this.iframe.contentDocument || this.getWin().document);
30516    },
30517
30518    // private
30519    getWin : function(){
30520        return Ext.isIE ? this.iframe.contentWindow : window.frames[this.iframe.name];
30521    },
30522
30523    // private
30524    onRender : function(ct, position){
30525        Ext.form.HtmlEditor.superclass.onRender.call(this, ct, position);
30526        this.el.dom.style.border = '0 none';
30527        this.el.dom.setAttribute('tabIndex', -1);
30528        this.el.addClass('x-hidden');
30529        if(Ext.isIE){ // fix IE 1px bogus margin
30530            this.el.applyStyles('margin-top:-1px;margin-bottom:-1px;')
30531        }
30532        this.wrap = this.el.wrap({
30533            cls:'x-html-editor-wrap', cn:{cls:'x-html-editor-tb'}
30534        });
30535
30536        this.createToolbar(this);
30537
30538        this.tb.items.each(function(item){
30539           if(item.itemId != 'sourceedit'){
30540                item.disable();
30541            }
30542        });
30543
30544        var iframe = document.createElement('iframe');
30545        iframe.name = Ext.id();
30546        iframe.frameBorder = '0';
30547
30548        iframe.src = Ext.isIE ? Ext.SSL_SECURE_URL : "javascript:;";
30549
30550        this.wrap.dom.appendChild(iframe);
30551
30552        this.iframe = iframe;
30553
30554        this.initFrame();
30555
30556        if(this.autoMonitorDesignMode !== false){
30557            this.monitorTask = Ext.TaskMgr.start({
30558                run: this.checkDesignMode,
30559                scope: this,
30560                interval:100
30561            });
30562        }
30563
30564        if(!this.width){
30565            var sz = this.el.getSize();
30566            this.setSize(sz.width, this.height || sz.height);
30567        }
30568    },
30569
30570    initFrame : function(){
30571        this.doc = this.getDoc();
30572        this.win = this.getWin();
30573
30574        this.doc.open();
30575        this.doc.write(this.getDocMarkup());
30576        this.doc.close();
30577
30578        var task = { // must defer to wait for browser to be ready
30579            run : function(){
30580                if(this.doc.body || this.doc.readyState == 'complete'){
30581                    Ext.TaskMgr.stop(task);
30582                    this.doc.designMode="on";
30583                    this.initEditor.defer(10, this);
30584                }
30585            },
30586            interval : 10,
30587            duration:10000,
30588            scope: this
30589        };
30590        Ext.TaskMgr.start(task);
30591    },
30592
30593
30594    checkDesignMode : function(){
30595        if(this.wrap && this.wrap.dom.offsetWidth){
30596            var doc = this.getDoc();
30597            if(!doc){
30598                return;
30599            }
30600            if(!doc.editorInitialized || String(doc.designMode).toLowerCase() != 'on'){
30601                this.initFrame();
30602            }
30603        }
30604    },
30605
30606    // private
30607    onResize : function(w, h){
30608        Ext.form.HtmlEditor.superclass.onResize.apply(this, arguments);
30609        if(this.el && this.iframe){
30610            if(typeof w == 'number'){
30611                var aw = w - this.wrap.getFrameWidth('lr');
30612                this.el.setWidth(this.adjustWidth('textarea', aw));
30613                this.iframe.style.width = Math.max(aw, 0) + 'px';
30614            }
30615            if(typeof h == 'number'){
30616                var ah = h - this.wrap.getFrameWidth('tb') - this.tb.el.getHeight();
30617                this.el.setHeight(this.adjustWidth('textarea', ah));
30618                this.iframe.style.height = Math.max(ah, 0) + 'px';
30619                if(this.doc){
30620                    this.getEditorBody().style.height = Math.max((ah - (this.iframePad*2)), 0) + 'px';
30621                }
30622            }
30623        }
30624    },
30625
30626    
30627    toggleSourceEdit : function(sourceEditMode){
30628        if(sourceEditMode === undefined){
30629            sourceEditMode = !this.sourceEditMode;
30630        }
30631        this.sourceEditMode = sourceEditMode === true;
30632        var btn = this.tb.items.get('sourceedit');
30633        if(btn.pressed !== this.sourceEditMode){
30634            btn.toggle(this.sourceEditMode);
30635            return;
30636        }
30637        if(this.sourceEditMode){
30638            this.tb.items.each(function(item){
30639                if(item.itemId != 'sourceedit'){
30640                    item.disable();
30641                }
30642            });
30643            this.syncValue();
30644            this.iframe.className = 'x-hidden';
30645            this.el.removeClass('x-hidden');
30646            this.el.dom.removeAttribute('tabIndex');
30647            this.el.focus();
30648        }else{
30649            if(this.initialized){
30650                this.tb.items.each(function(item){
30651                    item.enable();
30652                });
30653            }
30654            this.pushValue();
30655            this.iframe.className = '';
30656            this.el.addClass('x-hidden');
30657            this.el.dom.setAttribute('tabIndex', -1);
30658            this.deferFocus();
30659        }
30660        var lastSize = this.lastSize;
30661        if(lastSize){
30662            delete this.lastSize;
30663            this.setSize(lastSize);
30664        }
30665        this.fireEvent('editmodechange', this, this.sourceEditMode);
30666    },
30667
30668    // private used internally
30669    createLink : function(){
30670        var url = prompt(this.createLinkText, this.defaultLinkValue);
30671        if(url && url != 'http:/'+'/'){
30672            this.relayCmd('createlink', url);
30673        }
30674    },
30675
30676    // private (for BoxComponent)
30677    adjustSize : Ext.BoxComponent.prototype.adjustSize,
30678
30679    // private (for BoxComponent)
30680    getResizeEl : function(){
30681        return this.wrap;
30682    },
30683
30684    // private (for BoxComponent)
30685    getPositionEl : function(){
30686        return this.wrap;
30687    },
30688
30689    // private
30690    initEvents : function(){
30691        this.originalValue = this.getValue();
30692    },
30693
30694    
30695    markInvalid : Ext.emptyFn,
30696    
30697    
30698    clearInvalid : Ext.emptyFn,
30699
30700    // docs inherit from Field
30701    setValue : function(v){
30702        Ext.form.HtmlEditor.superclass.setValue.call(this, v);
30703        this.pushValue();
30704    },
30705
30706    
30707    cleanHtml : function(html){
30708        html = String(html);
30709        if(html.length > 5){
30710            if(Ext.isSafari){ // strip safari nonsense
30711                html = html.replace(/\sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi, '');
30712            }
30713        }
30714        if(html == '&nbsp;'){
30715            html = '';
30716        }
30717        return html;
30718    },
30719
30720    
30721    syncValue : function(){
30722        if(this.initialized){
30723            var bd = this.getEditorBody();
30724            var html = bd.innerHTML;
30725            if(Ext.isSafari){
30726                var bs = bd.getAttribute('style'); // Safari puts text-align styles on the body element!
30727                var m = bs.match(/text-align:(.*?);/i);
30728                if(m && m[1]){
30729                    html = '<div style="'+m[0]+'">' + html + '</div>';
30730                }
30731            }
30732            html = this.cleanHtml(html);
30733            if(this.fireEvent('beforesync', this, html) !== false){
30734                this.el.dom.value = html;
30735                this.fireEvent('sync', this, html);
30736            }
30737        }
30738    },
30739    
30740    //docs inherit from Field
30741    getValue : function() {
30742        this.syncValue();
30743        return Ext.form.HtmlEditor.superclass.getValue.call(this);
30744    },
30745
30746
30747    
30748    pushValue : function(){
30749        if(this.initialized){
30750            var v = this.el.dom.value;
30751            if(!this.activated && v.length < 1){
30752                v = '&nbsp;';
30753            }
30754            if(this.fireEvent('beforepush', this, v) !== false){
30755                this.getEditorBody().innerHTML = v;
30756                this.fireEvent('push', this, v);
30757            }
30758        }
30759    },
30760
30761    // private
30762    deferFocus : function(){
30763        this.focus.defer(10, this);
30764    },
30765
30766    // docs inherit from Field
30767    focus : function(){
30768        if(this.win && !this.sourceEditMode){
30769            this.win.focus();
30770        }else{
30771            this.el.focus();
30772        }
30773    },
30774
30775    // private
30776    initEditor : function(){
30777        var dbody = this.getEditorBody();
30778        var ss = this.el.getStyles('font-size', 'font-family', 'background-image', 'background-repeat');
30779        ss['background-attachment'] = 'fixed'; // w3c
30780        dbody.bgProperties = 'fixed'; // ie
30781
30782        Ext.DomHelper.applyStyles(dbody, ss);
30783
30784        if(this.doc){
30785            try{
30786                Ext.EventManager.removeAll(this.doc);
30787            }catch(e){}
30788        }
30789
30790        this.doc = this.getDoc();
30791
30792        Ext.EventManager.on(this.doc, {
30793            'mousedown': this.onEditorEvent,
30794            'dblclick': this.onEditorEvent,
30795            'click': this.onEditorEvent,
30796            'keyup': this.onEditorEvent,
30797            buffer:100,
30798            scope: this
30799        });
30800
30801        if(Ext.isGecko){
30802            Ext.EventManager.on(this.doc, 'keypress', this.applyCommand, this);
30803        }
30804        if(Ext.isIE || Ext.isSafari || Ext.isOpera){
30805            Ext.EventManager.on(this.doc, 'keydown', this.fixKeys, this);
30806        }
30807        this.initialized = true;
30808
30809        this.fireEvent('initialize', this);
30810
30811        this.doc.editorInitialized = true;
30812
30813        this.pushValue();
30814    },
30815
30816    // private
30817    onDestroy : function(){
30818        if(this.monitorTask){
30819            Ext.TaskMgr.stop(this.monitorTask);
30820        }
30821        if(this.rendered){
30822            this.tb.items.each(function(item){
30823                if(item.menu){
30824                    item.menu.removeAll();
30825                    if(item.menu.el){
30826                        item.menu.el.destroy();
30827                    }
30828                }
30829                item.destroy();
30830            });
30831            this.wrap.dom.innerHTML = '';
30832            this.wrap.remove();
30833        }
30834    },
30835
30836    // private
30837    onFirstFocus : function(){
30838        this.activated = true;
30839        this.tb.items.each(function(item){
30840           item.enable();
30841        });
30842        if(Ext.isGecko){ // prevent silly gecko errors
30843            this.win.focus();
30844            var s = this.win.getSelection();
30845            if(!s.focusNode || s.focusNode.nodeType != 3){
30846                var r = s.getRangeAt(0);
30847                r.selectNodeContents(this.getEditorBody());
30848                r.collapse(true);
30849                this.deferFocus();
30850            }
30851            try{
30852                this.execCmd('useCSS', true);
30853                this.execCmd('styleWithCSS', false);
30854            }catch(e){}
30855        }
30856        this.fireEvent('activate', this);
30857    },
30858
30859    // private
30860    adjustFont: function(btn){
30861        var adjust = btn.itemId == 'increasefontsize' ? 1 : -1;
30862
30863        var v = parseInt(this.doc.queryCommandValue('FontSize') || 2, 10);
30864        if(Ext.isSafari3 || Ext.isAir){
30865            // Safari 3 values
30866            // 1 = 10px, 2 = 13px, 3 = 16px, 4 = 18px, 5 = 24px, 6 = 32px
30867            if(v <= 10){
30868                v = 1 + adjust;
30869            }else if(v <= 13){
30870                v = 2 + adjust;
30871            }else if(v <= 16){
30872                v = 3 + adjust;
30873            }else if(v <= 18){
30874                v = 4 + adjust;
30875            }else if(v <= 24){
30876                v = 5 + adjust;
30877            }else {
30878                v = 6 + adjust;
30879            }
30880            v = v.constrain(1, 6);
30881        }else{
30882            if(Ext.isSafari){ // safari
30883                adjust *= 2;
30884            }
30885            v = Math.max(1, v+adjust) + (Ext.isSafari ? 'px' : 0);
30886        }
30887        this.execCmd('FontSize', v);
30888    },
30889
30890    // private
30891    onEditorEvent : function(e){
30892        this.updateToolbar();
30893    },
30894
30895
30896    
30897    updateToolbar: function(){
30898
30899        if(!this.activated){
30900            this.onFirstFocus();
30901            return;
30902        }
30903
30904        var btns = this.tb.items.map, doc = this.doc;
30905
30906        if(this.enableFont && !Ext.isSafari2){
30907            var name = (this.doc.queryCommandValue('FontName')||this.defaultFont).toLowerCase();
30908            if(name != this.fontSelect.dom.value){
30909                this.fontSelect.dom.value = name;
30910            }
30911        }
30912        if(this.enableFormat){
30913            btns.bold.toggle(doc.queryCommandState('bold'));
30914            btns.italic.toggle(doc.queryCommandState('italic'));
30915            btns.underline.toggle(doc.queryCommandState('underline'));
30916        }
30917        if(this.enableAlignments){
30918            btns.justifyleft.toggle(doc.queryCommandState('justifyleft'));
30919            btns.justifycenter.toggle(doc.queryCommandState('justifycenter'));
30920            btns.justifyright.toggle(doc.queryCommandState('justifyright'));
30921        }
30922        if(!Ext.isSafari2 && this.enableLists){
30923            btns.insertorderedlist.toggle(doc.queryCommandState('insertorderedlist'));
30924            btns.insertunorderedlist.toggle(doc.queryCommandState('insertunorderedlist'));
30925        }
30926        
30927        Ext.menu.MenuMgr.hideAll();
30928
30929        this.syncValue();
30930    },
30931
30932    // private
30933    relayBtnCmd : function(btn){
30934        this.relayCmd(btn.itemId);
30935    },
30936
30937    
30938    relayCmd : function(cmd, value){
30939        (function(){
30940            this.focus();
30941            this.execCmd(cmd, value);
30942            this.updateToolbar();
30943        }).defer(10, this);
30944    },
30945
30946    
30947    execCmd : function(cmd, value){
30948        this.doc.execCommand(cmd, false, value === undefined ? null : value);
30949        this.syncValue();
30950    },
30951
30952    // private
30953    applyCommand : function(e){
30954        if(e.ctrlKey){
30955            var c = e.getCharCode(), cmd;
30956            if(c > 0){
30957                c = String.fromCharCode(c);
30958                switch(c){
30959                    case 'b':
30960                        cmd = 'bold';
30961                    break;
30962                    case 'i':
30963                        cmd = 'italic';
30964                    break;
30965                    case 'u':
30966                        cmd = 'underline';
30967                    break;
30968                }
30969                if(cmd){
30970                    this.win.focus();
30971                    this.execCmd(cmd);
30972                    this.deferFocus();
30973                    e.preventDefault();
30974                }
30975            }
30976        }
30977    },
30978
30979    
30980    insertAtCursor : function(text){
30981        if(!this.activated){
30982            return;
30983        }
30984        if(Ext.isIE){
30985            this.win.focus();
30986            var r = this.doc.selection.createRange();
30987            if(r){
30988                r.collapse(true);
30989                r.pasteHTML(text);
30990                this.syncValue();
30991                this.deferFocus();
30992            }
30993        }else if(Ext.isGecko || Ext.isOpera){
30994            this.win.focus();
30995            this.execCmd('InsertHTML', text);
30996            this.deferFocus();
30997        }else if(Ext.isSafari){
30998            this.execCmd('InsertText', text);
30999            this.deferFocus();
31000        }
31001    },
31002
31003    // private
31004    fixKeys : function(){ // load time branching for fastest keydown performance
31005        if(Ext.isIE){
31006            return function(e){
31007                var k = e.getKey(), r;
31008                if(k == e.TAB){
31009                    e.stopEvent();
31010                    r = this.doc.selection.createRange();
31011                    if(r){
31012                        r.collapse(true);
31013                        r.pasteHTML('&nbsp;&nbsp;&nbsp;&nbsp;');
31014                        this.deferFocus();
31015                    }
31016                }else if(k == e.ENTER){
31017                    r = this.doc.selection.createRange();
31018                    if(r){
31019                        var target = r.parentElement();
31020                        if(!target || target.tagName.toLowerCase() != 'li'){
31021                            e.stopEvent();
31022                            r.pasteHTML('<br />');
31023                            r.collapse(false);
31024                            r.select();
31025                        }
31026                    }
31027                }
31028            };
31029        }else if(Ext.isOpera){
31030            return function(e){
31031                var k = e.getKey();
31032                if(k == e.TAB){
31033                    e.stopEvent();
31034                    this.win.focus();
31035                    this.execCmd('InsertHTML','&nbsp;&nbsp;&nbsp;&nbsp;');
31036                    this.deferFocus();
31037                }
31038            };
31039        }else if(Ext.isSafari){
31040            return function(e){
31041                var k = e.getKey();
31042                if(k == e.TAB){
31043                    e.stopEvent();
31044                    this.execCmd('InsertText','\t');
31045                    this.deferFocus();
31046                }
31047             };
31048        }
31049    }(),
31050
31051    
31052    getToolbar : function(){
31053        return this.tb;
31054    },
31055
31056    
31057    buttonTips : {
31058        bold : {
31059            title: 'Bold (Ctrl+B)',
31060            text: 'Make the selected text bold.',
31061            cls: 'x-html-editor-tip'
31062        },
31063        italic : {
31064            title: 'Italic (Ctrl+I)',
31065            text: 'Make the selected text italic.',
31066            cls: 'x-html-editor-tip'
31067        },
31068        underline : {
31069            title: 'Underline (Ctrl+U)',
31070            text: 'Underline the selected text.',
31071            cls: 'x-html-editor-tip'
31072        },
31073        increasefontsize : {
31074            title: 'Grow Text',
31075            text: 'Increase the font size.',
31076            cls: 'x-html-editor-tip'
31077        },
31078        decreasefontsize : {
31079            title: 'Shrink Text',
31080            text: 'Decrease the font size.',
31081            cls: 'x-html-editor-tip'
31082        },
31083        backcolor : {
31084            title: 'Text Highlight Color',
31085            text: 'Change the background color of the selected text.',
31086            cls: 'x-html-editor-tip'
31087        },
31088        forecolor : {
31089            title: 'Font Color',
31090            text: 'Change the color of the selected text.',
31091            cls: 'x-html-editor-tip'
31092        },
31093        justifyleft : {
31094            title: 'Align Text Left',
31095            text: 'Align text to the left.',
31096            cls: 'x-html-editor-tip'
31097        },
31098        justifycenter : {
31099            title: 'Center Text',
31100            text: 'Center text in the editor.',
31101            cls: 'x-html-editor-tip'
31102        },
31103        justifyright : {
31104            title: 'Align Text Right',
31105            text: 'Align text to the right.',
31106            cls: 'x-html-editor-tip'
31107        },
31108        insertunorderedlist : {
31109            title: 'Bullet List',
31110            text: 'Start a bulleted list.',
31111            cls: 'x-html-editor-tip'
31112        },
31113        insertorderedlist : {
31114            title: 'Numbered List',
31115            text: 'Start a numbered list.',
31116            cls: 'x-html-editor-tip'
31117        },
31118        createlink : {
31119            title: 'Hyperlink',
31120            text: 'Make the selected text a hyperlink.',
31121            cls: 'x-html-editor-tip'
31122        },
31123        sourceedit : {
31124            title: 'Source Edit',
31125            text: 'Switch to source editing mode.',
31126            cls: 'x-html-editor-tip'
31127        }
31128    }
31129
31130    // hide stuff that is not compatible
31131    
31132    
31133    
31134    
31135    
31136    
31137    
31138    
31139    
31140    
31141    
31142    
31143    
31144    
31145    
31146    
31147    
31148    
31149    
31150    
31151    
31152    
31153    
31154    
31155    
31156    
31157    
31158    
31159    
31160    
31161    
31162    
31163    
31164});
31165Ext.reg('htmleditor', Ext.form.HtmlEditor);
31166
31167Ext.form.TimeField = Ext.extend(Ext.form.ComboBox, {
31168    
31169    minValue : null,
31170    
31171    maxValue : null,
31172    
31173    minText : "The time in this field must be equal to or after {0}",
31174    
31175    maxText : "The time in this field must be equal to or before {0}",
31176    
31177    invalidText : "{0} is not a valid time",
31178    
31179    format : "g:i A",
31180    
31181    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",
31182    
31183    increment: 15,
31184
31185    // private override
31186    mode: 'local',
31187    // private override
31188    triggerAction: 'all',
31189    // private override
31190    typeAhead: false,
31191    
31192    // private - This is the date to use when generating time values in the absence of either minValue
31193    // or maxValue.  Using the current date causes DST issues on DST boundary dates, so this is an 
31194    // arbitrary "safe" date that can be any date aside from DST boundary dates.
31195    initDate: '1/1/2008',
31196
31197    // private
31198    initComponent : function(){
31199        Ext.form.TimeField.superclass.initComponent.call(this);
31200
31201        if(typeof this.minValue == "string"){
31202            this.minValue = this.parseDate(this.minValue);
31203        }
31204        if(typeof this.maxValue == "string"){
31205            this.maxValue = this.parseDate(this.maxValue);
31206        }
31207
31208        if(!this.store){
31209            var min = this.parseDate(this.minValue);
31210            if(!min){
31211                min = new Date(this.initDate).clearTime();
31212            }
31213            var max = this.parseDate(this.maxValue);
31214            if(!max){
31215                max = new Date(this.initDate).clearTime().add('mi', (24 * 60) - 1);
31216            }
31217            var times = [];
31218            while(min <= max){
31219                times.push([min.dateFormat(this.format)]);
31220                min = min.add('mi', this.increment);
31221            }
31222            this.store = new Ext.data.SimpleStore({
31223                fields: ['text'],
31224                data : times
31225            });
31226            this.displayField = 'text';
31227        }
31228    },
31229
31230    // inherited docs
31231    getValue : function(){
31232        var v = Ext.form.TimeField.superclass.getValue.call(this);
31233        return this.formatDate(this.parseDate(v)) || '';
31234    },
31235
31236    // inherited docs
31237    setValue : function(value){
31238        Ext.form.TimeField.superclass.setValue.call(this, this.formatDate(this.parseDate(value)));
31239    },
31240
31241    // private overrides
31242    validateValue : Ext.form.DateField.prototype.validateValue,
31243    parseDate : Ext.form.DateField.prototype.parseDate,
31244    formatDate : Ext.form.DateField.prototype.formatDate,
31245
31246    // private
31247    beforeBlur : function(){
31248        var v = this.parseDate(this.getRawValue());
31249        if(v){
31250            this.setValue(v.dateFormat(this.format));
31251        }
31252    }
31253
31254    
31255    
31256    
31257    
31258});
31259Ext.reg('timefield', Ext.form.TimeField);
31260
31261Ext.form.Label = Ext.extend(Ext.BoxComponent, {
31262    
31263    
31264    
31265
31266    // private
31267    onRender : function(ct, position){
31268        if(!this.el){
31269            this.el = document.createElement('label');
31270            this.el.id = this.getId();
31271            this.el.innerHTML = this.text ? Ext.util.Format.htmlEncode(this.text) : (this.html || '');
31272            if(this.forId){
31273                this.el.setAttribute('for', this.forId);
31274            }
31275        }
31276        Ext.form.Label.superclass.onRender.call(this, ct, position);
31277    },
31278    
31279    
31280    setText: function(t, encode){
31281        this.text = t;
31282        if(this.rendered){
31283            this.el.dom.innerHTML = encode !== false ? Ext.util.Format.htmlEncode(t) : t;
31284        }
31285        return this;
31286    }
31287});
31288
31289Ext.reg('label', Ext.form.Label);
31290
31291Ext.form.Action = function(form, options){
31292    this.form = form;
31293    this.options = options || {};
31294};
31295
31296
31297Ext.form.Action.CLIENT_INVALID = 'client';
31298
31299Ext.form.Action.SERVER_INVALID = 'server';
31300
31301Ext.form.Action.CONNECT_FAILURE = 'connect';
31302
31303Ext.form.Action.LOAD_FAILURE = 'load';
31304
31305Ext.form.Action.prototype = {
31306
31307
31308
31309
31310
31311
31312
31313
31314
31315
31316
31317
31318    type : 'default',
31319
31320
31321    // interface method
31322    run : function(options){
31323
31324    },
31325
31326    // interface method
31327    success : function(response){
31328
31329    },
31330
31331    // interface method
31332    handleResponse : function(response){
31333
31334    },
31335
31336    // default connection failure
31337    failure : function(response){
31338        this.response = response;
31339        this.failureType = Ext.form.Action.CONNECT_FAILURE;
31340        this.form.afterAction(this, false);
31341    },
31342
31343    // private
31344    processResponse : function(response){
31345        this.response = response;
31346        if(!response.responseText){
31347            return true;
31348        }
31349        this.result = this.handleResponse(response);
31350        return this.result;
31351    },
31352
31353    // utility functions used internally
31354    getUrl : function(appendParams){
31355        var url = this.options.url || this.form.url || this.form.el.dom.action;
31356        if(appendParams){
31357            var p = this.getParams();
31358            if(p){
31359                url += (url.indexOf('?') != -1 ? '&' : '?') + p;
31360            }
31361        }
31362        return url;
31363    },
31364
31365    // private
31366    getMethod : function(){
31367        return (this.options.method || this.form.method || this.form.el.dom.method || 'POST').toUpperCase();
31368    },
31369
31370    // private
31371    getParams : function(){
31372        var bp = this.form.baseParams;
31373        var p = this.options.params;
31374        if(p){
31375            if(typeof p == "object"){
31376                p = Ext.urlEncode(Ext.applyIf(p, bp));
31377            }else if(typeof p == 'string' && bp){
31378                p += '&' + Ext.urlEncode(bp);
31379            }
31380        }else if(bp){
31381            p = Ext.urlEncode(bp);
31382        }
31383        return p;
31384    },
31385
31386    // private
31387    createCallback : function(opts){
31388		var opts = opts || {};
31389        return {
31390            success: this.success,
31391            failure: this.failure,
31392            scope: this,
31393            timeout: (opts.timeout*1000) || (this.form.timeout*1000),
31394            upload: this.form.fileUpload ? this.success : undefined
31395        };
31396    }
31397};
31398
31399
31400Ext.form.Action.Submit = function(form, options){
31401    Ext.form.Action.Submit.superclass.constructor.call(this, form, options);
31402};
31403
31404Ext.extend(Ext.form.Action.Submit, Ext.form.Action, {
31405    
31406    
31407    type : 'submit',
31408
31409    // private
31410    run : function(){
31411        var o = this.options;
31412        var method = this.getMethod();
31413        var isGet = method == 'GET';
31414        if(o.clientValidation === false || this.form.isValid()){
31415            Ext.Ajax.request(Ext.apply(this.createCallback(o), {
31416                form:this.form.el.dom,
31417                url:this.getUrl(isGet),
31418                method: method,
31419                headers: o.headers,
31420                params:!isGet ? this.getParams() : null,
31421                isUpload: this.form.fileUpload
31422            }));
31423        }else if (o.clientValidation !== false){ // client validation failed
31424            this.failureType = Ext.form.Action.CLIENT_INVALID;
31425            this.form.afterAction(this, false);
31426        }
31427    },
31428
31429    // private
31430    success : function(response){
31431        var result = this.processResponse(response);
31432        if(result === true || result.success){
31433            this.form.afterAction(this, true);
31434            return;
31435        }
31436        if(result.errors){
31437            this.form.markInvalid(result.errors);
31438            this.failureType = Ext.form.Action.SERVER_INVALID;
31439        }
31440        this.form.afterAction(this, false);
31441    },
31442
31443    // private
31444    handleResponse : function(response){
31445        if(this.form.errorReader){
31446            var rs = this.form.errorReader.read(response);
31447            var errors = [];
31448            if(rs.records){
31449                for(var i = 0, len = rs.records.length; i < len; i++) {
31450                    var r = rs.records[i];
31451                    errors[i] = r.data;
31452                }
31453            }
31454            if(errors.length < 1){
31455                errors = null;
31456            }
31457            return {
31458                success : rs.success,
31459                errors : errors
31460            };
31461        }
31462        return Ext.decode(response.responseText);
31463    }
31464});
31465
31466
31467
31468Ext.form.Action.Load = function(form, options){
31469    Ext.form.Action.Load.superclass.constructor.call(this, form, options);
31470    this.reader = this.form.reader;
31471};
31472
31473Ext.extend(Ext.form.Action.Load, Ext.form.Action, {
31474    // private
31475    type : 'load',
31476
31477    // private
31478    run : function(){
31479        Ext.Ajax.request(Ext.apply(
31480                this.createCallback(this.options), {
31481                    method:this.getMethod(),
31482                    url:this.getUrl(false),
31483                    headers: this.options.headers,
31484                    params:this.getParams()
31485        }));
31486    },
31487
31488    // private
31489    success : function(response){
31490        var result = this.processResponse(response);
31491        if(result === true || !result.success || !result.data){
31492            this.failureType = Ext.form.Action.LOAD_FAILURE;
31493            this.form.afterAction(this, false);
31494            return;
31495        }
31496        this.form.clearInvalid();
31497        this.form.setValues(result.data);
31498        this.form.afterAction(this, true);
31499    },
31500
31501    // private
31502    handleResponse : function(response){
31503        if(this.form.reader){
31504            var rs = this.form.reader.read(response);
31505            var data = rs.records && rs.records[0] ? rs.records[0].data : null;
31506            return {
31507                success : rs.success,
31508                data : data
31509            };
31510        }
31511        return Ext.decode(response.responseText);
31512    }
31513});
31514
31515Ext.form.Action.ACTION_TYPES = {
31516    'load' : Ext.form.Action.Load,
31517    'submit' : Ext.form.Action.Submit
31518};
31519
31520
31521Ext.form.VTypes = function(){
31522    // closure these in so they are only created once.
31523    var alpha = /^[a-zA-Z_]+$/;
31524    var alphanum = /^[a-zA-Z0-9_]+$/;
31525    var email = /^([\w]+)(\.[\w]+)*@([\w\-]+\.){1,5}([A-Za-z]){2,4}$/;
31526    var url = /(((https?)|(ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
31527
31528    // All these messages and functions are configurable
31529    return {
31530        
31531        'email' : function(v){
31532            return email.test(v);
31533        },
31534        
31535        'emailText' : 'Este campo deverá ser um endereço de e-mail com o formato "[email protected]"',
31536        
31537        'emailMask' : /[a-z0-9_\.\-@]/i,
31538
31539        
31540        'url' : function(v){
31541            return url.test(v);
31542        },
31543        
31544        'urlText' : 'This field should be a URL in the format "http:/'+'/www.domain.com"',
31545        
31546        
31547        'alpha' : function(v){
31548            return alpha.test(v);
31549        },
31550        
31551        'alphaText' : 'This field should only contain letters and _',
31552        
31553        'alphaMask' : /[a-z_]/i,
31554
31555        
31556        'alphanum' : function(v){
31557            return alphanum.test(v);
31558        },
31559        
31560        'alphanumText' : 'This field should only contain letters, numbers and _',
31561        
31562        'alphanumMask' : /[a-z0-9_]/i
31563    };
31564}();
31565
31566Ext.grid.GridPanel = Ext.extend(Ext.Panel, {
31567    
31568    
31569    
31570    
31571    
31572    
31573    
31574    
31575    
31576    
31577    
31578    
31579
31580    
31581    ddText : "{0} selected row{1}",
31582    
31583    minColumnWidth : 25,
31584    
31585    trackMouseOver : true,
31586    
31587    enableDragDrop : false,
31588    
31589    enableColumnMove : true,
31590    
31591    enableColumnHide : true,
31592    
31593    enableHdMenu : true,
31594    
31595    stripeRows : false,
31596    
31597    autoExpandColumn : false,
31598    
31599    autoExpandMin : 50,
31600    
31601    autoExpandMax : 1000,
31602    
31603    view : null,
31604    
31605    loadMask : false,
31606
31607    
31608    deferRowRender : true,
31609
31610    // private
31611    rendered : false,
31612    // private
31613    viewReady: false,
31614    
31615    stateEvents: ["columnmove", "columnresize", "sortchange"],
31616
31617    // private
31618    initComponent : function(){
31619        Ext.grid.GridPanel.superclass.initComponent.call(this);
31620
31621        // override any provided value since it isn't valid
31622        this.autoScroll = false;
31623        this.autoWidth = false;
31624
31625        if(Ext.isArray(this.columns)){
31626            this.colModel = new Ext.grid.ColumnModel(this.columns);
31627            delete this.columns;
31628        }
31629
31630        // check and correct shorthanded configs
31631        if(this.ds){
31632            this.store = this.ds;
31633            delete this.ds;
31634        }
31635        if(this.cm){
31636            this.colModel = this.cm;
31637            delete this.cm;
31638        }
31639        if(this.sm){
31640            this.selModel = this.sm;
31641            delete this.sm;
31642        }
31643        this.store = Ext.StoreMgr.lookup(this.store);
31644
31645        this.addEvents(
31646            // raw events
31647            
31648            "click",
31649            
31650            "dblclick",
31651            
31652            "contextmenu",
31653            
31654            "mousedown",
31655            
31656            "mouseup",
31657            
31658            "mouseover",
31659            
31660            "mouseout",
31661            
31662            "keypress",
31663            
31664            "keydown",
31665
31666            // custom events
31667            
31668            "cellmousedown",
31669            
31670            "rowmousedown",
31671            
31672            "headermousedown",
31673
31674            
31675            "cellclick",
31676            
31677            "celldblclick",
31678            
31679            "rowclick",
31680            
31681            "rowdblclick",
31682            
31683            "headerclick",
31684            
31685            "headerdblclick",
31686            
31687            "rowcontextmenu",
31688            
31689            "cellcontextmenu",
31690            
31691            "headercontextmenu",
31692            
31693            "bodyscroll",
31694            
31695            "columnresize",
31696            
31697            "columnmove",
31698            
31699            "sortchange"
31700        );
31701    },
31702
31703    // private
31704    onRender : function(ct, position){
31705        Ext.grid.GridPanel.superclass.onRender.apply(this, arguments);
31706
31707        var c = this.body;
31708
31709        this.el.addClass('x-grid-panel');
31710
31711        var view = this.getView();
31712        view.init(this);
31713
31714        c.on("mousedown", this.onMouseDown, this);
31715        c.on("click", this.onClick, this);
31716        c.on("dblclick", this.onDblClick, this);
31717        c.on("contextmenu", this.onContextMenu, this);
31718        c.on("keydown", this.onKeyDown, this);
31719
31720        this.relayEvents(c, ["mousedown","mouseup","mouseover","mouseout","keypress"]);
31721
31722        this.getSelectionModel().init(this);
31723        this.view.render();
31724    },
31725
31726    // private
31727    initEvents : function(){
31728        Ext.grid.GridPanel.superclass.initEvents.call(this);
31729
31730        if(this.loadMask){
31731            this.loadMask = new Ext.LoadMask(this.bwrap,
31732                    Ext.apply({store:this.store}, this.loadMask));
31733        }
31734    },
31735
31736    initStateEvents : function(){
31737        Ext.grid.GridPanel.superclass.initStateEvents.call(this);
31738        this.colModel.on('hiddenchange', this.saveState, this, {delay: 100});
31739    },
31740
31741    applyState : function(state){
31742        var cm = this.colModel;
31743        var cs = state.columns;
31744        if(cs){
31745            for(var i = 0, len = cs.length; i < len; i++){
31746                var s = cs[i];
31747                var c = cm.getColumnById(s.id);
31748                if(c){
31749                    c.hidden = s.hidden;
31750                    c.width = s.width;
31751                    var oldIndex = cm.getIndexById(s.id);
31752                    if(oldIndex != i){
31753                        cm.moveColumn(oldIndex, i);
31754                    }
31755                }
31756            }
31757        }
31758        if(state.sort){
31759            this.store[this.store.remoteSort ? 'setDefaultSort' : 'sort'](state.sort.field, state.sort.direction);
31760        }
31761    },
31762
31763    getState : function(){
31764        var o = {columns: []};
31765        for(var i = 0, c; c = this.colModel.config[i]; i++){
31766            o.columns[i] = {
31767                id: c.id,
31768                width: c.width
31769            };
31770            if(c.hidden){
31771                o.columns[i].hidden = true;
31772            }
31773        }
31774        var ss = this.store.getSortState();
31775        if(ss){
31776            o.sort = ss;
31777        }
31778        return o;
31779    },
31780
31781    // private
31782    afterRender : function(){
31783        Ext.grid.GridPanel.superclass.afterRender.call(this);
31784        this.view.layout();
31785        if(this.deferRowRender){
31786            this.view.afterRender.defer(10, this.view);
31787        }else{
31788            this.view.afterRender();
31789        }
31790        this.viewReady = true;
31791    },
31792
31793    
31794    reconfigure : function(store, colModel){
31795        if(this.loadMask){
31796            this.loadMask.destroy();
31797            this.loadMask = new Ext.LoadMask(this.bwrap,
31798                    Ext.apply({store:store}, this.initialConfig.loadMask));
31799        }
31800        this.view.bind(store, colModel);
31801        this.store = store;
31802        this.colModel = colModel;
31803        if(this.rendered){
31804            this.view.refresh(true);
31805        }
31806    },
31807
31808    // private
31809    onKeyDown : function(e){
31810        this.fireEvent("keydown", e);
31811    },
31812
31813    // private
31814    onDestroy : function(){
31815        if(this.rendered){
31816            if(this.loadMask){
31817                this.loadMask.destroy();
31818            }
31819            var c = this.body;
31820            c.removeAllListeners();
31821            this.view.destroy();
31822            c.update("");
31823        }
31824        this.colModel.purgeListeners();
31825        Ext.grid.GridPanel.superclass.onDestroy.call(this);
31826    },
31827
31828    // private
31829    processEvent : function(name, e){
31830        this.fireEvent(name, e);
31831        var t = e.getTarget();
31832        var v = this.view;
31833        var header = v.findHeaderIndex(t);
31834        if(header !== false){
31835            this.fireEvent("header" + name, this, header, e);
31836        }else{
31837            var row = v.findRowIndex(t);
31838            var cell = v.findCellIndex(t);
31839            if(row !== false){
31840                this.fireEvent("row" + name, this, row, e);
31841                if(cell !== false){
31842                    this.fireEvent("cell" + name, this, row, cell, e);
31843                }
31844            }
31845        }
31846    },
31847
31848    // private
31849    onClick : function(e){
31850        this.processEvent("click", e);
31851    },
31852
31853    // private
31854    onMouseDown : function(e){
31855        this.processEvent("mousedown", e);
31856    },
31857
31858    // private
31859    onContextMenu : function(e, t){
31860        this.processEvent("contextmenu", e);
31861    },
31862
31863    // private
31864    onDblClick : function(e){
31865        this.processEvent("dblclick", e);
31866    },
31867
31868    // private
31869    walkCells : function(row, col, step, fn, scope){
31870        var cm = this.colModel, clen = cm.getColumnCount();
31871        var ds = this.store, rlen = ds.getCount(), first = true;
31872        if(step < 0){
31873            if(col < 0){
31874                row--;
31875                first = false;
31876            }
31877            while(row >= 0){
31878                if(!first){
31879                    col = clen-1;
31880                }
31881                first = false;
31882                while(col >= 0){
31883                    if(fn.call(scope || this, row, col, cm) === true){
31884                        return [row, col];
31885                    }
31886                    col--;
31887                }
31888                row--;
31889            }
31890        } else {
31891            if(col >= clen){
31892                row++;
31893                first = false;
31894            }
31895            while(row < rlen){
31896                if(!first){
31897                    col = 0;
31898                }
31899                first = false;
31900                while(col < clen){
31901                    if(fn.call(scope || this, row, col, cm) === true){
31902                        return [row, col];
31903                    }
31904                    col++;
31905                }
31906                row++;
31907            }
31908        }
31909        return null;
31910    },
31911
31912    // private
31913    getSelections : function(){
31914        return this.selModel.getSelections();
31915    },
31916
31917    // private
31918    onResize : function(){
31919        Ext.grid.GridPanel.superclass.onResize.apply(this, arguments);
31920        if(this.viewReady){
31921            this.view.layout();
31922        }
31923    },
31924
31925    
31926    getGridEl : function(){
31927        return this.body;
31928    },
31929
31930    // private for compatibility, overridden by editor grid
31931    stopEditing : Ext.emptyFn,
31932
31933    
31934    getSelectionModel : function(){
31935        if(!this.selModel){
31936            this.selModel = new Ext.grid.RowSelectionModel(
31937                    this.disableSelection ? {selectRow: Ext.emptyFn} : null);
31938        }
31939        return this.selModel;
31940    },
31941
31942    
31943    getStore : function(){
31944        return this.store;
31945    },
31946
31947    
31948    getColumnModel : function(){
31949        return this.colModel;
31950    },
31951
31952    
31953    getView : function(){
31954        if(!this.view){
31955            this.view = new Ext.grid.GridView(this.viewConfig);
31956        }
31957        return this.view;
31958    },
31959    
31960    getDragDropText : function(){
31961        var count = this.selModel.getCount();
31962        return String.format(this.ddText, count, count == 1 ? '' : 's');
31963    }
31964
31965    
31966    
31967    
31968    
31969    
31970    
31971    
31972    
31973    
31974    
31975    
31976    
31977    
31978    
31979    
31980    
31981    
31982    
31983    
31984    
31985    
31986    
31987    
31988    
31989    
31990    
31991    
31992    
31993    
31994    
31995    
31996
31997
31998
31999    
32000    
32001    
32002    
32003    
32004    
32005    
32006    
32007    
32008    
32009    
32010    
32011    
32012    
32013    
32014});
32015Ext.reg('grid', Ext.grid.GridPanel);
32016
32017Ext.grid.GridView = function(config){
32018    Ext.apply(this, config);
32019    // These events are only used internally by the grid components
32020    this.addEvents(
32021      
32022      "beforerowremoved",
32023      
32024      "beforerowsinserted",
32025      
32026      "beforerefresh",
32027      
32028      "rowremoved",
32029      
32030      "rowsinserted",
32031      
32032      "rowupdated",
32033      
32034      "refresh"
32035  );
32036    Ext.grid.GridView.superclass.constructor.call(this);
32037};
32038
32039Ext.extend(Ext.grid.GridView, Ext.util.Observable, {
32040    
32041    
32042    
32043    
32044    
32045    deferEmptyText: true,
32046    
32047    scrollOffset: 19,
32048    
32049    autoFill: false,
32050    
32051    forceFit: false,
32052    
32053    sortClasses : ["sort-asc", "sort-desc"],
32054    
32055    sortAscText : "Ordem Crescente ",
32056    
32057    sortDescText : "Ordem Decrescente",
32058    
32059    columnsText : "Colunas",
32060
32061    // private
32062    borderWidth: 2,
32063    tdClass: 'x-grid3-cell',
32064    hdCls: 'x-grid3-hd',
32065
32066    
32067    cellSelectorDepth: 4,
32068    
32069    rowSelectorDepth: 10,
32070
32071    
32072    cellSelector: 'td.x-grid3-cell',
32073    
32074    rowSelector: 'div.x-grid3-row',
32075
32076    
32077
32078    // private
32079    initTemplates : function(){
32080        var ts = this.templates || {};
32081        if(!ts.master){
32082            ts.master = new Ext.Template(
32083                    '<div class="x-grid3" hidefocus="true">',
32084                        '<div class="x-grid3-viewport">',
32085                            '<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>',
32086                            '<div class="x-grid3-scroller"><div class="x-grid3-body">{body}</div><a href="#" class="x-grid3-focus" tabIndex="-1"></a></div>',
32087                        "</div>",
32088                        '<div class="x-grid3-resize-marker">&#160;</div>',
32089                        '<div class="x-grid3-resize-proxy">&#160;</div>',
32090                    "</div>"
32091                    );
32092        }
32093
32094        if(!ts.header){
32095            ts.header = new Ext.Template(
32096                    '<table border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',
32097                    '<thead><tr class="x-grid3-hd-row">{cells}</tr></thead>',
32098                    "</table>"
32099                    );
32100        }
32101
32102        if(!ts.hcell){
32103            ts.hcell = new Ext.Template(
32104                    '<td class="x-grid3-hd x-grid3-cell x-grid3-td-{id} {css}" style="{style}"><div {tooltip} {attr} class="x-grid3-hd-inner x-grid3-hd-{id}" unselectable="on" style="{istyle}">', this.grid.enableHdMenu ? '<a class="x-grid3-hd-btn" href="#"></a>' : '',
32105                    '{value}<img class="x-grid3-sort-icon" src="', Ext.BLANK_IMAGE_URL, '" />',
32106                    "</div></td>"
32107                    );
32108        }
32109
32110        if(!ts.body){
32111            ts.body = new Ext.Template('{rows}');
32112        }
32113
32114        if(!ts.row){
32115            ts.row = new Ext.Template(
32116                    '<div class="x-grid3-row {alt}" style="{tstyle}"><table class="x-grid3-row-table" border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',
32117                    '<tbody><tr>{cells}</tr>',
32118                    (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>' : ''),
32119                    '</tbody></table></div>'
32120                    );
32121        }
32122
32123        if(!ts.cell){
32124            ts.cell = new Ext.Template(
32125                    '<td class="x-grid3-col x-grid3-cell x-grid3-td-{id} {css}" style="{style}" tabIndex="0" {cellAttr}>',
32126                    '<div class="x-grid3-cell-inner x-grid3-col-{id}" unselectable="on" {attr}>{value}</div>',
32127                    "</td>"
32128                    );
32129        }
32130
32131        for(var k in ts){
32132            var t = ts[k];
32133            if(t && typeof t.compile == 'function' && !t.compiled){
32134                t.disableFormats = true;
32135                t.compile();
32136            }
32137        }
32138
32139        this.templates = ts;
32140        this.colRe = new RegExp("x-grid3-td-([^\\s]+)", "");
32141    },
32142
32143    // private
32144    fly : function(el){
32145        if(!this._flyweight){
32146            this._flyweight = new Ext.Element.Flyweight(document.body);
32147        }
32148        this._flyweight.dom = el;
32149        return this._flyweight;
32150    },
32151
32152    // private
32153    getEditorParent : function(){
32154        return this.scroller.dom;
32155    },
32156
32157    // private
32158    initElements : function(){
32159        var E = Ext.Element;
32160
32161        var el = this.grid.getGridEl().dom.firstChild;
32162        var cs = el.childNodes;
32163
32164        this.el = new E(el);
32165
32166        this.mainWrap = new E(cs[0]);
32167        this.mainHd = new E(this.mainWrap.dom.firstChild);
32168
32169        if(this.grid.hideHeaders){
32170            this.mainHd.setDisplayed(false);
32171        }
32172
32173        this.innerHd = this.mainHd.dom.firstChild;
32174        this.scroller = new E(this.mainWrap.dom.childNodes[1]);
32175        if(this.forceFit){
32176            this.scroller.setStyle('overflow-x', 'hidden');
32177        }
32178        
32179        this.mainBody = new E(this.scroller.dom.firstChild);
32180
32181        this.focusEl = new E(this.scroller.dom.childNodes[1]);
32182        this.focusEl.swallowEvent("click", true);
32183
32184        this.resizeMarker = new E(cs[1]);
32185        this.resizeProxy = new E(cs[2]);
32186    },
32187
32188    // private
32189    getRows : function(){
32190        return this.hasRows() ? this.mainBody.dom.childNodes : [];
32191    },
32192
32193    // finder methods, used with delegation
32194
32195    // private
32196    findCell : function(el){
32197        if(!el){
32198            return false;
32199        }
32200        return this.fly(el).findParent(this.cellSelector, this.cellSelectorDepth);
32201    },
32202
32203    // private
32204    findCellIndex : function(el, requiredCls){
32205        var cell = this.findCell(el);
32206        if(cell && (!requiredCls || this.fly(cell).hasClass(requiredCls))){
32207            return this.getCellIndex(cell);
32208        }
32209        return false;
32210    },
32211
32212    // private
32213    getCellIndex : function(el){
32214        if(el){
32215            var m = el.className.match(this.colRe);
32216            if(m && m[1]){
32217                return this.cm.getIndexById(m[1]);
32218            }
32219        }
32220        return false;
32221    },
32222
32223    // private
32224    findHeaderCell : function(el){
32225        var cell = this.findCell(el);
32226        return cell && this.fly(cell).hasClass(this.hdCls) ? cell : null;
32227    },
32228
32229    // private
32230    findHeaderIndex : function(el){
32231        return this.findCellIndex(el, this.hdCls);
32232    },
32233
32234
32235    findRow : function(el){
32236        if(!el){
32237            return false;
32238        }
32239        return this.fly(el).findParent(this.rowSelector, this.rowSelectorDepth);
32240    },
32241
32242
32243    findRowIndex : function(el){
32244        var r = this.findRow(el);
32245        return r ? r.rowIndex : false;
32246    },
32247
32248    // getter methods for fetching elements dynamically in the grid
32249
32250
32251    getRow : function(row){
32252        return this.getRows()[row];
32253    },
32254
32255
32256    getCell : function(row, col){
32257        return this.getRow(row).getElementsByTagName('td')[col];
32258    },
32259
32260
32261    getHeaderCell : function(index){
32262      return this.mainHd.dom.getElementsByTagName('td')[index];
32263    },
32264
32265    // manipulating elements
32266
32267    // private - use getRowClass to apply custom row classes
32268    addRowClass : function(row, cls){
32269        var r = this.getRow(row);
32270        if(r){
32271            this.fly(r).addClass(cls);
32272        }
32273    },
32274
32275    // private
32276    removeRowClass : function(row, cls){
32277        var r = this.getRow(row);
32278        if(r){
32279            this.fly(r).removeClass(cls);
32280        }
32281    },
32282
32283    // private
32284    removeRow : function(row){
32285        Ext.removeNode(this.getRow(row));
32286        this.syncFocusEl(row);
32287    },
32288    
32289    // private
32290    removeRows : function(firstRow, lastRow){
32291        var bd = this.mainBody.dom;
32292        for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){
32293            Ext.removeNode(bd.childNodes[firstRow]);
32294        }
32295        this.syncFocusEl(firstRow);
32296    },
32297
32298    // scrolling stuff
32299
32300    // private
32301    getScrollState : function(){
32302        var sb = this.scroller.dom;
32303        return {left: sb.scrollLeft, top: sb.scrollTop};
32304    },
32305
32306    // private
32307    restoreScroll : function(state){
32308        var sb = this.scroller.dom;
32309        sb.scrollLeft = state.left;
32310        sb.scrollTop = state.top;
32311    },
32312
32313    
32314    scrollToTop : function(){
32315        this.scroller.dom.scrollTop = 0;
32316        this.scroller.dom.scrollLeft = 0;
32317    },
32318
32319    // private
32320    syncScroll : function(){
32321      this.syncHeaderScroll();
32322      var mb = this.scroller.dom;
32323        this.grid.fireEvent("bodyscroll", mb.scrollLeft, mb.scrollTop);
32324    },
32325
32326    // private
32327    syncHeaderScroll : function(){
32328        var mb = this.scroller.dom;
32329        this.innerHd.scrollLeft = mb.scrollLeft;
32330        this.innerHd.scrollLeft = mb.scrollLeft; // second time for IE (1/2 time first fails, other browsers ignore)
32331    },
32332
32333    // private
32334    updateSortIcon : function(col, dir){
32335        var sc = this.sortClasses;
32336        var hds = this.mainHd.select('td').removeClass(sc);
32337        hds.item(col).addClass(sc[dir == "DESC" ? 1 : 0]);
32338    },
32339
32340    // private
32341    updateAllColumnWidths : function(){
32342        var tw = this.getTotalWidth();
32343        var clen = this.cm.getColumnCount();
32344        var ws = [];
32345        for(var i = 0; i < clen; i++){
32346            ws[i] = this.getColumnWidth(i);
32347        }
32348
32349        this.innerHd.firstChild.firstChild.style.width = tw;
32350
32351        for(var i = 0; i < clen; i++){
32352            var hd = this.getHeaderCell(i);
32353            hd.style.width = ws[i];
32354        }
32355
32356        var ns = this.getRows(), row, trow;
32357        for(var i = 0, len = ns.length; i < len; i++){
32358            row = ns[i];
32359            row.style.width = tw;
32360            if(row.firstChild){
32361                row.firstChild.style.width = tw;
32362                trow = row.firstChild.rows[0];
32363                for (var j = 0; j < clen; j++) {
32364                   trow.childNodes[j].style.width = ws[j];
32365                }
32366            }
32367        }
32368
32369        this.onAllColumnWidthsUpdated(ws, tw);
32370    },
32371
32372    // private
32373    updateColumnWidth : function(col, width){
32374        var w = this.getColumnWidth(col);
32375        var tw = this.getTotalWidth();
32376
32377        this.innerHd.firstChild.firstChild.style.width = tw;
32378        var hd = this.getHeaderCell(col);
32379        hd.style.width = w;
32380
32381        var ns = this.getRows(), row;
32382        for(var i = 0, len = ns.length; i < len; i++){
32383            row = ns[i];
32384            row.style.width = tw;
32385            if(row.firstChild){
32386                row.firstChild.style.width = tw;
32387                row.firstChild.rows[0].childNodes[col].style.width = w;
32388            }
32389        }
32390
32391        this.onColumnWidthUpdated(col, w, tw);
32392    },
32393
32394    // private
32395    updateColumnHidden : function(col, hidden){
32396        var tw = this.getTotalWidth();
32397
32398        this.innerHd.firstChild.firstChild.style.width = tw;
32399
32400        var display = hidden ? 'none' : '';
32401
32402        var hd = this.getHeaderCell(col);
32403        hd.style.display = display;
32404
32405        var ns = this.getRows(), row;
32406        for(var i = 0, len = ns.length; i < len; i++){
32407            row = ns[i];
32408            row.style.width = tw;
32409            if(row.firstChild){
32410                row.firstChild.style.width = tw;
32411                row.firstChild.rows[0].childNodes[col].style.display = display;
32412            }
32413        }
32414
32415        this.onColumnHiddenUpdated(col, hidden, tw);
32416
32417        delete this.lastViewWidth; // force recalc
32418        this.layout();
32419    },
32420
32421    // private
32422    doRender : function(cs, rs, ds, startRow, colCount, stripe){
32423        var ts = this.templates, ct = ts.cell, rt = ts.row, last = colCount-1;
32424        var tstyle = 'width:'+this.getTotalWidth()+';';
32425        // buffers
32426        var buf = [], cb, c, p = {}, rp = {tstyle: tstyle}, r;
32427        for(var j = 0, len = rs.length; j < len; j++){
32428            r = rs[j]; cb = [];
32429            var rowIndex = (j+startRow);
32430            for(var i = 0; i < colCount; i++){
32431                c = cs[i];
32432                p.id = c.id;
32433                p.css = i == 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');
32434                p.attr = p.cellAttr = "";
32435                p.value = c.renderer(r.data[c.name], p, r, rowIndex, i, ds);
32436                p.style = c.style;
32437                if(p.value == undefined || p.value === "") p.value = "&#160;";
32438                if(r.dirty && typeof r.modified[c.name] !== 'undefined'){
32439                    p.css += ' x-grid3-dirty-cell';
32440                }
32441                cb[cb.length] = ct.apply(p);
32442            }
32443            var alt = [];
32444            if(stripe && ((rowIndex+1) % 2 == 0)){
32445                alt[0] = "x-grid3-row-alt";
32446            }
32447            if(r.dirty){
32448                alt[1] = " x-grid3-dirty-row";
32449            }
32450            rp.cols = colCount;
32451            if(this.getRowClass){
32452                alt[2] = this.getRowClass(r, rowIndex, rp, ds);
32453            }
32454            rp.alt = alt.join(" ");
32455            rp.cells = cb.join("");
32456            buf[buf.length] =  rt.apply(rp);
32457        }
32458        return buf.join("");
32459    },
32460
32461    // private
32462    processRows : function(startRow, skipStripe){
32463        if(this.ds.getCount() < 1){
32464            return;
32465        }
32466        skipStripe = skipStripe || !this.grid.stripeRows;
32467        startRow = startRow || 0;
32468        var rows = this.getRows();
32469        var cls = ' x-grid3-row-alt ';
32470        rows[0].className += ' x-grid3-row-first';
32471        rows[rows.length - 1].className += ' x-grid3-row-last';
32472        for(var i = startRow, len = rows.length; i < len; i++){
32473            var row = rows[i];
32474            row.rowIndex = i;
32475            if(!skipStripe){
32476                var isAlt = ((i+1) % 2 == 0);
32477                var hasAlt = (' '+row.className + ' ').indexOf(cls) != -1;
32478                if(isAlt == hasAlt){
32479                    continue;
32480                }
32481                if(isAlt){
32482                    row.className += " x-grid3-row-alt";
32483                }else{
32484                    row.className = row.className.replace("x-grid3-row-alt", "");
32485                }
32486            }
32487        }
32488    },
32489
32490    afterRender: function(){
32491        this.mainBody.dom.innerHTML = this.renderRows();
32492        this.processRows(0, true);
32493
32494        if(this.deferEmptyText !== true){
32495            this.applyEmptyText();
32496        }
32497    },
32498
32499    // private
32500    renderUI : function(){
32501
32502        var header = this.renderHeaders();
32503        var body = this.templates.body.apply({rows:''});
32504
32505
32506        var html = this.templates.master.apply({
32507            body: body,
32508            header: header
32509        });
32510
32511        var g = this.grid;
32512
32513        g.getGridEl().dom.innerHTML = html;
32514
32515        this.initElements();
32516
32517        // get mousedowns early
32518        Ext.fly(this.innerHd).on("click", this.handleHdDown, this);
32519        this.mainHd.on("mouseover", this.handleHdOver, this);
32520        this.mainHd.on("mouseout", this.handleHdOut, this);
32521        this.mainHd.on("mousemove", this.handleHdMove, this);
32522
32523        this.scroller.on('scroll', this.syncScroll,  this);
32524        if(g.enableColumnResize !== false){
32525            this.splitZone = new Ext.grid.GridView.SplitDragZone(g, this.mainHd.dom);
32526        }
32527
32528        if(g.enableColumnMove){
32529            this.columnDrag = new Ext.grid.GridView.ColumnDragZone(g, this.innerHd);
32530            this.columnDrop = new Ext.grid.HeaderDropZone(g, this.mainHd.dom);
32531        }
32532
32533        if(g.enableHdMenu !== false){
32534            if(g.enableColumnHide !== false){
32535                this.colMenu = new Ext.menu.Menu({id:g.id + "-hcols-menu"});
32536                this.colMenu.on("beforeshow", this.beforeColMenuShow, this);
32537                this.colMenu.on("itemclick", this.handleHdMenuClick, this);
32538            }
32539            this.hmenu = new Ext.menu.Menu({id: g.id + "-hctx"});
32540            this.hmenu.add(
32541                {id:"asc", text: this.sortAscText, cls: "xg-hmenu-sort-asc"},
32542                {id:"desc", text: this.sortDescText, cls: "xg-hmenu-sort-desc"}
32543            );
32544            if(g.enableColumnHide !== false){
32545                this.hmenu.add('-',
32546                    {id:"columns", text: this.columnsText, menu: this.colMenu, iconCls: 'x-cols-icon'}
32547                );
32548            }
32549            this.hmenu.on("itemclick", this.handleHdMenuClick, this);
32550
32551            //g.on("headercontextmenu", this.handleHdCtx, this);
32552        }
32553
32554        if(g.trackMouseOver){
32555            this.mainBody.on("mouseover", this.onRowOver, this);
32556            this.mainBody.on("mouseout", this.onRowOut, this);
32557        }
32558        if(g.enableDragDrop || g.enableDrag){
32559            this.dragZone = new Ext.grid.GridDragZone(g, {
32560                ddGroup : g.ddGroup || 'GridDD'
32561            });
32562        }
32563
32564        this.updateHeaderSortState();
32565
32566    },
32567
32568    // private
32569    layout : function(){
32570        if(!this.mainBody){
32571            return; // not rendered
32572        }
32573        var g = this.grid;
32574        var c = g.getGridEl();
32575        var csize = c.getSize(true);
32576        var vw = csize.width;
32577
32578        if(vw < 20 || csize.height < 20){ // display: none?
32579            return;
32580        }
32581
32582        if(g.autoHeight){
32583            this.scroller.dom.style.overflow = 'visible';
32584            if(Ext.isSafari){
32585                this.scroller.dom.style.position = 'static';
32586            }
32587        }else{
32588            this.el.setSize(csize.width, csize.height);
32589
32590            var hdHeight = this.mainHd.getHeight();
32591            var vh = csize.height - (hdHeight);
32592
32593            this.scroller.setSize(vw, vh);
32594            if(this.innerHd){
32595                this.innerHd.style.width = (vw)+'px';
32596            }
32597        }
32598        if(this.forceFit){
32599            if(this.lastViewWidth != vw){
32600                this.fitColumns(false, false);
32601                this.lastViewWidth = vw;
32602            }
32603        }else {
32604            this.autoExpand();
32605            this.syncHeaderScroll();
32606        }
32607        this.onLayout(vw, vh);
32608    },
32609
32610    // template functions for subclasses and plugins
32611    // these functions include precalculated values
32612    onLayout : function(vw, vh){
32613        // do nothing
32614    },
32615
32616    onColumnWidthUpdated : function(col, w, tw){
32617        //template method
32618        this.focusEl.setWidth(tw);
32619    },
32620
32621    onAllColumnWidthsUpdated : function(ws, tw){
32622        //template method
32623        this.focusEl.setWidth(tw);
32624    },
32625
32626    onColumnHiddenUpdated : function(col, hidden, tw){
32627        // template method
32628        this.focusEl.setWidth(tw);
32629    },
32630
32631    updateColumnText : function(col, text){
32632        // template method
32633    },
32634
32635    afterMove : function(colIndex){
32636        // template method
32637    },
32638
32639    
32640    // private
32641    init: function(grid){
32642        this.grid = grid;
32643
32644        this.initTemplates();
32645        this.initData(grid.store, grid.colModel);
32646        this.initUI(grid);
32647    },
32648
32649    // private
32650    getColumnId : function(index){
32651      return this.cm.getColumnId(index);
32652    },
32653
32654    // private
32655    renderHeaders : function(){
32656        var cm = this.cm, ts = this.templates;
32657        var ct = ts.hcell;
32658
32659        var cb = [], sb = [], p = {};
32660        var len = cm.getColumnCount();
32661        var last = len - 1;
32662        for(var i = 0; i < len; i++){
32663            p.id = cm.getColumnId(i);
32664            p.value = cm.getColumnHeader(i) || "";
32665            p.style = this.getColumnStyle(i, true);
32666            p.tooltip = this.getColumnTooltip(i);
32667            p.css = i == 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');
32668            if(cm.config[i].align == 'right'){
32669                p.istyle = 'padding-right:16px';
32670            } else {
32671                delete p.istyle;
32672            }
32673            cb[cb.length] = ct.apply(p);
32674        }
32675        return ts.header.apply({cells: cb.join(""), tstyle:'width:'+this.getTotalWidth()+';'});
32676    },
32677
32678    // private
32679    getColumnTooltip : function(i){
32680        var tt = this.cm.getColumnTooltip(i);
32681        if(tt){
32682            if(Ext.QuickTips.isEnabled()){
32683                return 'ext:qtip="'+tt+'"';
32684            }else{
32685                return 'title="'+tt+'"';
32686            }
32687        }
32688        return "";
32689    },
32690
32691    // private
32692    beforeUpdate : function(){
32693        this.grid.stopEditing(true);
32694    },
32695
32696    // private
32697    updateHeaders : function(){
32698        this.innerHd.firstChild.innerHTML = this.renderHeaders();
32699    },
32700
32701    
32702    focusRow : function(row){
32703        this.focusCell(row, 0, false);
32704    },
32705
32706    
32707    focusCell : function(row, col, hscroll){
32708		this.syncFocusEl(this.ensureVisible(row, col, hscroll));
32709        if(Ext.isGecko){
32710            this.focusEl.focus();
32711        }else{
32712            this.focusEl.focus.defer(1, this.focusEl);
32713        }
32714    },
32715
32716	resolveCell : function(row, col, hscroll){
32717		if(typeof row != "number"){
32718            row = row.rowIndex;
32719        }
32720        if(!this.ds){
32721            return null;
32722        }
32723        if(row < 0 || row >= this.ds.getCount()){
32724            return null;
32725        }
32726        col = (col !== undefined ? col : 0);
32727
32728        var rowEl = this.getRow(row), cellEl;
32729        if(!(hscroll === false && col === 0)){
32730            while(this.cm.isHidden(col)){
32731                col++;
32732            }
32733            cellEl = this.getCell(row, col);
32734        }
32735
32736		return {row: rowEl, cell: cellEl};
32737	},
32738
32739	getResolvedXY : function(resolved){
32740		if(!resolved){
32741			return null;
32742		}
32743		var s = this.scroller.dom, c = resolved.cell, r = resolved.row;
32744		return c ? Ext.fly(c).getXY() : [this.el.getX(), Ext.fly(r).getY()];
32745	},
32746
32747	syncFocusEl : function(row, col, hscroll){
32748		var xy = row;
32749		if(!Ext.isArray(xy)){
32750			row = Math.min(row, Math.max(0, this.getRows().length-1));
32751        	xy = this.getResolvedXY(this.resolveCell(row, col, hscroll));
32752		}
32753        this.focusEl.setXY(xy||this.scroller.getXY());
32754    },
32755
32756	ensureVisible : function(row, col, hscroll){
32757        var resolved = this.resolveCell(row, col, hscroll);
32758		if(!resolved || !resolved.row){
32759			return;
32760		}
32761
32762		var rowEl = resolved.row, cellEl = resolved.cell;
32763
32764		var c = this.scroller.dom;
32765
32766        var ctop = 0;
32767        var p = rowEl, stop = this.el.dom;
32768        while(p && p != stop){
32769            ctop += p.offsetTop;
32770            p = p.offsetParent;
32771        }
32772        ctop -= this.mainHd.dom.offsetHeight;
32773
32774        var cbot = ctop + rowEl.offsetHeight;
32775
32776        var ch = c.clientHeight;
32777        var stop = parseInt(c.scrollTop, 10);
32778        var sbot = stop + ch;
32779
32780		if(ctop < stop){
32781          c.scrollTop = ctop;
32782        }else if(cbot > sbot){
32783            c.scrollTop = cbot-ch;
32784        }
32785
32786        if(hscroll !== false){
32787            var cleft = parseInt(cellEl.offsetLeft, 10);
32788            var cright = cleft + cellEl.offsetWidth;
32789
32790            var sleft = parseInt(c.scrollLeft, 10);
32791            var sright = sleft + c.clientWidth;
32792            if(cleft < sleft){
32793                c.scrollLeft = cleft;
32794            }else if(cright > sright){
32795                c.scrollLeft = cright-c.clientWidth;
32796            }
32797        }
32798        return this.getResolvedXY(resolved);
32799    },
32800
32801    // private
32802    insertRows : function(dm, firstRow, lastRow, isUpdate){
32803        if(!isUpdate && firstRow === 0 && lastRow >= dm.getCount()-1){
32804            this.refresh();
32805        }else{
32806            if(!isUpdate){
32807                this.fireEvent("beforerowsinserted", this, firstRow, lastRow);
32808            }
32809            var html = this.renderRows(firstRow, lastRow);
32810            var before = this.getRow(firstRow);
32811            if(before){
32812                Ext.DomHelper.insertHtml('beforeBegin', before, html);
32813            }else{
32814                Ext.DomHelper.insertHtml('beforeEnd', this.mainBody.dom, html);
32815            }
32816            if(!isUpdate){
32817                this.fireEvent("rowsinserted", this, firstRow, lastRow);
32818                this.processRows(firstRow);
32819            }
32820        }
32821        this.syncFocusEl(firstRow);
32822    },
32823
32824    // private
32825    deleteRows : function(dm, firstRow, lastRow){
32826        if(dm.getRowCount()<1){
32827            this.refresh();
32828        }else{
32829            this.fireEvent("beforerowsdeleted", this, firstRow, lastRow);
32830
32831            this.removeRows(firstRow, lastRow);
32832
32833            this.processRows(firstRow);
32834            this.fireEvent("rowsdeleted", this, firstRow, lastRow);
32835        }
32836    },
32837
32838    // private
32839    getColumnStyle : function(col, isHeader){
32840        var style = !isHeader ? (this.cm.config[col].css || '') : '';
32841        style += 'width:'+this.getColumnWidth(col)+';';
32842        if(this.cm.isHidden(col)){
32843            style += 'display:none;';
32844        }
32845        var align = this.cm.config[col].align;
32846        if(align){
32847            style += 'text-align:'+align+';';
32848        }
32849        return style;
32850    },
32851
32852    // private
32853    getColumnWidth : function(col){
32854        var w = this.cm.getColumnWidth(col);
32855        if(typeof w == 'number'){
32856            return (Ext.isBorderBox ? w : (w-this.borderWidth > 0 ? w-this.borderWidth:0)) + 'px';
32857        }
32858        return w;
32859    },
32860
32861    // private
32862    getTotalWidth : function(){
32863        return this.cm.getTotalWidth()+'px';
32864    },
32865
32866    // private
32867    fitColumns : function(preventRefresh, onlyExpand, omitColumn){
32868        var cm = this.cm, leftOver, dist, i;
32869        var tw = cm.getTotalWidth(false);
32870        var aw = this.grid.getGridEl().getWidth(true)-this.scrollOffset;
32871
32872        if(aw < 20){ // not initialized, so don't screw up the default widths
32873            return;
32874        }
32875        var extra = aw - tw;
32876
32877        if(extra === 0){
32878            return false;
32879        }
32880
32881        var vc = cm.getColumnCount(true);
32882        var ac = vc-(typeof omitColumn == 'number' ? 1 : 0);
32883        if(ac === 0){
32884            ac = 1;
32885            omitColumn = undefined;
32886        }
32887        var colCount = cm.getColumnCount();
32888        var cols = [];
32889        var extraCol = 0;
32890        var width = 0;
32891        var w;
32892        for (i = 0; i < colCount; i++){
32893            if(!cm.isHidden(i) && !cm.isFixed(i) && i !== omitColumn){
32894                w = cm.getColumnWidth(i);
32895                cols.push(i);
32896                extraCol = i;
32897                cols.push(w);
32898                width += w;
32899            }
32900        }
32901        var frac = (aw - cm.getTotalWidth())/width;
32902        while (cols.length){
32903            w = cols.pop();
32904            i = cols.pop();
32905            cm.setColumnWidth(i, Math.max(this.grid.minColumnWidth, Math.floor(w + w*frac)), true);
32906        }
32907
32908        if((tw = cm.getTotalWidth(false)) > aw){
32909            var adjustCol = ac != vc ? omitColumn : extraCol;
32910             cm.setColumnWidth(adjustCol, Math.max(1,
32911                     cm.getColumnWidth(adjustCol)- (tw-aw)), true);
32912        }
32913
32914        if(preventRefresh !== true){
32915            this.updateAllColumnWidths();
32916        }
32917
32918
32919        return true;
32920    },
32921
32922    // private
32923    autoExpand : function(preventUpdate){
32924        var g = this.grid, cm = this.cm;
32925        if(!this.userResized && g.autoExpandColumn){
32926            var tw = cm.getTotalWidth(false);
32927            var aw = this.grid.getGridEl().getWidth(true)-this.scrollOffset;
32928            if(tw != aw){
32929                var ci = cm.getIndexById(g.autoExpandColumn);
32930                var currentWidth = cm.getColumnWidth(ci);
32931                var cw = Math.min(Math.max(((aw-tw)+currentWidth), g.autoExpandMin), g.autoExpandMax);
32932                if(cw != currentWidth){
32933                    cm.setColumnWidth(ci, cw, true);
32934                    if(preventUpdate !== true){
32935                        this.updateColumnWidth(ci, cw);
32936                    }
32937                }
32938            }
32939        }
32940    },
32941
32942    // private
32943    getColumnData : function(){
32944        // build a map for all the columns
32945        var cs = [], cm = this.cm, colCount = cm.getColumnCount();
32946        for(var i = 0; i < colCount; i++){
32947            var name = cm.getDataIndex(i);
32948            cs[i] = {
32949                name : (typeof name == 'undefined' ? this.ds.fields.get(i).name : name),
32950                renderer : cm.getRenderer(i),
32951                id : cm.getColumnId(i),
32952                style : this.getColumnStyle(i)
32953            };
32954        }
32955        return cs;
32956    },
32957
32958    // private
32959    renderRows : function(startRow, endRow){
32960        // pull in all the crap needed to render rows
32961        var g = this.grid, cm = g.colModel, ds = g.store, stripe = g.stripeRows;
32962        var colCount = cm.getColumnCount();
32963
32964        if(ds.getCount() < 1){
32965            return "";
32966        }
32967
32968        var cs = this.getColumnData();
32969
32970        startRow = startRow || 0;
32971        endRow = typeof endRow == "undefined"? ds.getCount()-1 : endRow;
32972
32973        // records to render
32974        var rs = ds.getRange(startRow, endRow);
32975
32976        return this.doRender(cs, rs, ds, startRow, colCount, stripe);
32977    },
32978
32979    // private
32980    renderBody : function(){
32981        var markup = this.renderRows();
32982        return this.templates.body.apply({rows: markup});
32983    },
32984
32985    // private
32986    refreshRow : function(record){
32987        var ds = this.ds, index;
32988        if(typeof record == 'number'){
32989            index = record;
32990            record = ds.getAt(index);
32991        }else{
32992            index = ds.indexOf(record);
32993        }
32994        var cls = [];
32995        this.insertRows(ds, index, index, true);
32996        this.getRow(index).rowIndex = index;
32997        this.onRemove(ds, record, index+1, true);
32998        this.fireEvent("rowupdated", this, index, record);
32999    },
33000
33001    
33002    refresh : function(headersToo){
33003        this.fireEvent("beforerefresh", this);
33004        this.grid.stopEditing(true);
33005
33006        var result = this.renderBody();
33007        this.mainBody.update(result);
33008
33009        if(headersToo === true){
33010            this.updateHeaders();
33011            this.updateHeaderSortState();
33012        }
33013        this.processRows(0, true);
33014        this.layout();
33015        this.applyEmptyText();
33016        this.fireEvent("refresh", this);
33017    },
33018
33019    // private
33020    applyEmptyText : function(){
33021        if(this.emptyText && !this.hasRows()){
33022            this.mainBody.update('<div class="x-grid-empty">' + this.emptyText + '</div>');
33023        }
33024    },
33025
33026    // private
33027    updateHeaderSortState : function(){
33028        var state = this.ds.getSortState();
33029        if(!state){
33030            return;
33031        }
33032        if(!this.sortState || (this.sortState.field != state.field || this.sortState.direction != state.direction)){
33033            this.grid.fireEvent('sortchange', this.grid, state);
33034        }
33035        this.sortState = state;
33036        var sortColumn = this.cm.findColumnIndex(state.field);
33037        if(sortColumn != -1){
33038            var sortDir = state.direction;
33039            this.updateSortIcon(sortColumn, sortDir);
33040        }
33041    },
33042
33043    // private
33044    destroy : function(){
33045        if(this.colMenu){
33046            Ext.menu.MenuMgr.unregister(this.colMenu);
33047            this.colMenu.destroy();
33048            delete this.colMenu;
33049        }
33050        if(this.hmenu){
33051            Ext.menu.MenuMgr.unregister(this.hmenu);
33052            this.hmenu.destroy();
33053            delete this.hmenu;
33054        }
33055        if(this.grid.enableColumnMove){
33056            var dds = Ext.dd.DDM.ids['gridHeader' + this.grid.getGridEl().id];
33057            if(dds){
33058                for(var dd in dds){
33059                    if(!dds[dd].config.isTarget && dds[dd].dragElId){
33060                        var elid = dds[dd].dragElId;
33061                        dds[dd].unreg();
33062                        Ext.get(elid).remove();
33063                    } else if(dds[dd].config.isTarget){
33064                        dds[dd].proxyTop.remove();
33065                        dds[dd].proxyBottom.remove();
33066                        dds[dd].unreg();
33067                    }
33068                    if(Ext.dd.DDM.locationCache[dd]){
33069                        delete Ext.dd.DDM.locationCache[dd];
33070                    }
33071                }
33072                delete Ext.dd.DDM.ids['gridHeader' + this.grid.getGridEl().id];
33073            }
33074        }
33075        
33076        if(this.dragZone){
33077            this.dragZone.unreg();
33078        }
33079        
33080        Ext.fly(this.innerHd).removeAllListeners();
33081        Ext.removeNode(this.innerHd);
33082        
33083        Ext.destroy(this.resizeMarker, this.resizeProxy, this.focusEl, this.mainBody, 
33084                    this.scroller, this.mainHd, this.mainWrap, this.dragZone, 
33085                    this.splitZone, this.columnDrag, this.columnDrop);
33086
33087        this.initData(null, null);
33088        Ext.EventManager.removeResizeListener(this.onWindowResize, this);
33089        this.purgeListeners();
33090    },
33091
33092    // private
33093    onDenyColumnHide : function(){
33094
33095    },
33096
33097    // private
33098    render : function(){
33099        if(this.autoFill){
33100            var ct = this.grid.ownerCt;
33101            if (ct && ct.getLayout()){
33102                ct.on('afterlayout', function(){ 
33103                    this.fitColumns(true, true);
33104                    this.updateHeaders(); 
33105                }, this, {single: true}); 
33106            }else{ 
33107                this.fitColumns(true, true); 
33108            }
33109        }else if(this.forceFit){
33110            this.fitColumns(true, false);
33111        }else if(this.grid.autoExpandColumn){
33112            this.autoExpand(true);
33113        }
33114
33115        this.renderUI();
33116    },
33117
33118    
33119    // private
33120    initData : function(ds, cm){
33121        if(this.ds){
33122            this.ds.un("load", this.onLoad, this);
33123            this.ds.un("datachanged", this.onDataChange, this);
33124            this.ds.un("add", this.onAdd, this);
33125            this.ds.un("remove", this.onRemove, this);
33126            this.ds.un("update", this.onUpdate, this);
33127            this.ds.un("clear", this.onClear, this);
33128        }
33129        if(ds){
33130            ds.on("load", this.onLoad, this);
33131            ds.on("datachanged", this.onDataChange, this);
33132            ds.on("add", this.onAdd, this);
33133            ds.on("remove", this.onRemove, this);
33134            ds.on("update", this.onUpdate, this);
33135            ds.on("clear", this.onClear, this);
33136        }
33137        this.ds = ds;
33138
33139        if(this.cm){
33140            this.cm.un("configchange", this.onColConfigChange, this);
33141            this.cm.un("widthchange", this.onColWidthChange, this);
33142            this.cm.un("headerchange", this.onHeaderChange, this);
33143            this.cm.un("hiddenchange", this.onHiddenChange, this);
33144            this.cm.un("columnmoved", this.onColumnMove, this);
33145            this.cm.un("columnlockchange", this.onColumnLock, this);
33146        }
33147        if(cm){
33148            delete this.lastViewWidth;
33149            cm.on("configchange", this.onColConfigChange, this);
33150            cm.on("widthchange", this.onColWidthChange, this);
33151            cm.on("headerchange", this.onHeaderChange, this);
33152            cm.on("hiddenchange", this.onHiddenChange, this);
33153            cm.on("columnmoved", this.onColumnMove, this);
33154            cm.on("columnlockchange", this.onColumnLock, this);
33155        }
33156        this.cm = cm;
33157    },
33158
33159    // private
33160    onDataChange : function(){
33161        this.refresh();
33162        this.updateHeaderSortState();
33163        this.syncFocusEl(0);
33164    },
33165
33166    // private
33167    onClear : function(){
33168        this.refresh();
33169        this.syncFocusEl(0);
33170    },
33171
33172    // private
33173    onUpdate : function(ds, record){
33174        this.refreshRow(record);
33175    },
33176
33177    // private
33178    onAdd : function(ds, records, index){
33179        this.insertRows(ds, index, index + (records.length-1));
33180    },
33181
33182    // private
33183    onRemove : function(ds, record, index, isUpdate){
33184        if(isUpdate !== true){
33185            this.fireEvent("beforerowremoved", this, index, record);
33186        }
33187        this.removeRow(index);
33188        if(isUpdate !== true){
33189            this.processRows(index);
33190            this.applyEmptyText();
33191            this.fireEvent("rowremoved", this, index, record);
33192        }
33193    },
33194
33195    // private
33196    onLoad : function(){
33197        this.scrollToTop();
33198    },
33199
33200    // private
33201    onColWidthChange : function(cm, col, width){
33202        this.updateColumnWidth(col, width);
33203    },
33204
33205    // private
33206    onHeaderChange : function(cm, col, text){
33207        this.updateHeaders();
33208    },
33209
33210    // private
33211    onHiddenChange : function(cm, col, hidden){
33212        this.updateColumnHidden(col, hidden);
33213    },
33214
33215    // private
33216    onColumnMove : function(cm, oldIndex, newIndex){
33217        this.indexMap = null;
33218        var s = this.getScrollState();
33219        this.refresh(true);
33220        this.restoreScroll(s);
33221        this.afterMove(newIndex);
33222    },
33223
33224    // private
33225    onColConfigChange : function(){
33226        delete this.lastViewWidth;
33227        this.indexMap = null;
33228        this.refresh(true);
33229    },
33230
33231    
33232    // private
33233    initUI : function(grid){
33234        grid.on("headerclick", this.onHeaderClick, this);
33235    },
33236
33237    // private
33238    initEvents : function(){
33239
33240    },
33241
33242    // private
33243    onHeaderClick : function(g, index){
33244        if(this.headersDisabled || !this.cm.isSortable(index)){
33245            return;
33246        }
33247        g.stopEditing(true);
33248        g.store.sort(this.cm.getDataIndex(index));
33249    },
33250
33251    // private
33252    onRowOver : function(e, t){
33253        var row;
33254        if((row = this.findRowIndex(t)) !== false){
33255            this.addRowClass(row, "x-grid3-row-over");
33256        }
33257    },
33258
33259    // private
33260    onRowOut : function(e, t){
33261        var row;
33262        if((row = this.findRowIndex(t)) !== false && !e.within(this.getRow(row), true)){
33263            this.removeRowClass(row, "x-grid3-row-over");
33264        }
33265    },
33266
33267    // private
33268    handleWheel : function(e){
33269        e.stopPropagation();
33270    },
33271
33272    // private
33273    onRowSelect : function(row){
33274        this.addRowClass(row, "x-grid3-row-selected");
33275    },
33276
33277    // private
33278    onRowDeselect : function(row){
33279        this.removeRowClass(row, "x-grid3-row-selected");
33280    },
33281
33282    // private
33283    onCellSelect : function(row, col){
33284        var cell = this.getCell(row, col);
33285        if(cell){
33286            this.fly(cell).addClass("x-grid3-cell-selected");
33287        }
33288    },
33289
33290    // private
33291    onCellDeselect : function(row, col){
33292        var cell = this.getCell(row, col);
33293        if(cell){
33294            this.fly(cell).removeClass("x-grid3-cell-selected");
33295        }
33296    },
33297
33298    // private
33299    onColumnSplitterMoved : function(i, w){
33300        this.userResized = true;
33301        var cm = this.grid.colModel;
33302        cm.setColumnWidth(i, w, true);
33303
33304        if(this.forceFit){
33305            this.fitColumns(true, false, i);
33306            this.updateAllColumnWidths();
33307        }else{
33308            this.updateColumnWidth(i, w);
33309            this.syncHeaderScroll();
33310        }
33311
33312        this.grid.fireEvent("columnresize", i, w);
33313    },
33314
33315    // private
33316    handleHdMenuClick : function(item){
33317        var index = this.hdCtxIndex;
33318        var cm = this.cm, ds = this.ds;
33319        switch(item.id){
33320            case "asc":
33321                ds.sort(cm.getDataIndex(index), "ASC");
33322                break;
33323            case "desc":
33324                ds.sort(cm.getDataIndex(index), "DESC");
33325                break;
33326            default:
33327                index = cm.getIndexById(item.id.substr(4));
33328                if(index != -1){
33329                    if(item.checked && cm.getColumnsBy(this.isHideableColumn, this).length <= 1){
33330                        this.onDenyColumnHide();
33331                        return false;
33332                    }
33333                    cm.setHidden(index, item.checked);
33334                }
33335        }
33336        return true;
33337    },
33338
33339    // private
33340    isHideableColumn : function(c){
33341        return !c.hidden && !c.fixed;
33342    },
33343
33344    // private
33345    beforeColMenuShow : function(){
33346        var cm = this.cm,  colCount = cm.getColumnCount();
33347        this.colMenu.removeAll();
33348        for(var i = 0; i < colCount; i++){
33349            if(cm.config[i].fixed !== true && cm.config[i].hideable !== false){
33350                this.colMenu.add(new Ext.menu.CheckItem({
33351                    id: "col-"+cm.getColumnId(i),
33352                    text: cm.getColumnHeader(i),
33353                    checked: !cm.isHidden(i),
33354                    hideOnClick:false,
33355                    disabled: cm.config[i].hideable === false
33356                }));
33357            }
33358        }
33359    },
33360
33361    // private
33362    handleHdDown : function(e, t){
33363        if(Ext.fly(t).hasClass('x-grid3-hd-btn')){
33364            e.stopEvent();
33365            var hd = this.findHeaderCell(t);
33366            Ext.fly(hd).addClass('x-grid3-hd-menu-open');
33367            var index = this.getCellIndex(hd);
33368            this.hdCtxIndex = index;
33369            var ms = this.hmenu.items, cm = this.cm;
33370            ms.get("asc").setDisabled(!cm.isSortable(index));
33371            ms.get("desc").setDisabled(!cm.isSortable(index));
33372            this.hmenu.on("hide", function(){
33373                Ext.fly(hd).removeClass('x-grid3-hd-menu-open');
33374            }, this, {single:true});
33375            this.hmenu.show(t, "tl-bl?");
33376        }
33377    },
33378
33379    // private
33380    handleHdOver : function(e, t){
33381        var hd = this.findHeaderCell(t);
33382        if(hd && !this.headersDisabled){
33383            this.activeHd = hd;
33384            this.activeHdIndex = this.getCellIndex(hd);
33385            var fly = this.fly(hd);
33386            this.activeHdRegion = fly.getRegion();
33387            if(!this.cm.isMenuDisabled(this.activeHdIndex)){
33388                fly.addClass("x-grid3-hd-over");
33389                this.activeHdBtn = fly.child('.x-grid3-hd-btn');
33390                if(this.activeHdBtn){
33391                    this.activeHdBtn.dom.style.height = (hd.firstChild.offsetHeight-1)+'px';
33392                }
33393            }
33394        }
33395    },
33396
33397    // private
33398    handleHdMove : function(e, t){
33399        if(this.activeHd && !this.headersDisabled){
33400            var hw = this.splitHandleWidth || 5;
33401            var r = this.activeHdRegion;
33402            var x = e.getPageX();
33403            var ss = this.activeHd.style;
33404            if(x - r.left <= hw && this.cm.isResizable(this.activeHdIndex-1)){
33405                ss.cursor = Ext.isAir ? 'move' : Ext.isSafari ? 'e-resize' : 'col-resize'; // col-resize not always supported
33406            }else if(r.right - x <= (!this.activeHdBtn ? hw : 2) && this.cm.isResizable(this.activeHdIndex)){
33407                ss.cursor = Ext.isAir ? 'move' : Ext.isSafari ? 'w-resize' : 'col-resize';
33408            }else{
33409                ss.cursor = '';
33410            }
33411        }
33412    },
33413
33414    // private
33415    handleHdOut : function(e, t){
33416        var hd = this.findHeaderCell(t);
33417        if(hd && (!Ext.isIE || !e.within(hd, true))){
33418            this.activeHd = null;
33419            this.fly(hd).removeClass("x-grid3-hd-over");
33420            hd.style.cursor = '';
33421        }
33422    },
33423
33424    // private
33425    hasRows : function(){
33426        var fc = this.mainBody.dom.firstChild;
33427        return fc && fc.className != 'x-grid-empty';
33428    },
33429
33430    // back compat
33431    bind : function(d, c){
33432        this.initData(d, c);
33433    }
33434});
33435
33436
33437// private
33438// This is a support class used internally by the Grid components
33439Ext.grid.GridView.SplitDragZone = function(grid, hd){
33440    this.grid = grid;
33441    this.view = grid.getView();
33442    this.marker = this.view.resizeMarker;
33443    this.proxy = this.view.resizeProxy;
33444    Ext.grid.GridView.SplitDragZone.superclass.constructor.call(this, hd,
33445        "gridSplitters" + this.grid.getGridEl().id, {
33446        dragElId : Ext.id(this.proxy.dom), resizeFrame:false
33447    });
33448    this.scroll = false;
33449    this.hw = this.view.splitHandleWidth || 5;
33450};
33451Ext.extend(Ext.grid.GridView.SplitDragZone, Ext.dd.DDProxy, {
33452
33453    b4StartDrag : function(x, y){
33454        this.view.headersDisabled = true;
33455        var h = this.view.mainWrap.getHeight();
33456        this.marker.setHeight(h);
33457        this.marker.show();
33458        this.marker.alignTo(this.view.getHeaderCell(this.cellIndex), 'tl-tl', [-2, 0]);
33459        this.proxy.setHeight(h);
33460        var w = this.cm.getColumnWidth(this.cellIndex);
33461        var minw = Math.max(w-this.grid.minColumnWidth, 0);
33462        this.resetConstraints();
33463        this.setXConstraint(minw, 1000);
33464        this.setYConstraint(0, 0);
33465        this.minX = x - minw;
33466        this.maxX = x + 1000;
33467        this.startPos = x;
33468        Ext.dd.DDProxy.prototype.b4StartDrag.call(this, x, y);
33469    },
33470
33471
33472    handleMouseDown : function(e){
33473        var t = this.view.findHeaderCell(e.getTarget());
33474        if(t){
33475            var xy = this.view.fly(t).getXY(), x = xy[0], y = xy[1];
33476            var exy = e.getXY(), ex = exy[0], ey = exy[1];
33477            var w = t.offsetWidth, adjust = false;
33478            if((ex - x) <= this.hw){
33479                adjust = -1;
33480            }else if((x+w) - ex <= this.hw){
33481                adjust = 0;
33482            }
33483            if(adjust !== false){
33484                this.cm = this.grid.colModel;
33485                var ci = this.view.getCellIndex(t);
33486                if(adjust == -1){
33487                  if (ci + adjust < 0) {
33488                    return;
33489                  }
33490                    while(this.cm.isHidden(ci+adjust)){
33491                        --adjust;
33492                        if(ci+adjust < 0){
33493                            return;
33494                        }
33495                    }
33496                }
33497                this.cellIndex = ci+adjust;
33498                this.split = t.dom;
33499                if(this.cm.isResizable(this.cellIndex) && !this.cm.isFixed(this.cellIndex)){
33500                    Ext.grid.GridView.SplitDragZone.superclass.handleMouseDown.apply(this, arguments);
33501                }
33502            }else if(this.view.columnDrag){
33503                this.view.columnDrag.callHandleMouseDown(e);
33504            }
33505        }
33506    },
33507
33508    endDrag : function(e){
33509        this.marker.hide();
33510        var v = this.view;
33511        var endX = Math.max(this.minX, e.getPageX());
33512        var diff = endX - this.startPos;
33513        v.onColumnSplitterMoved(this.cellIndex, this.cm.getColumnWidth(this.cellIndex)+diff);
33514        setTimeout(function(){
33515            v.headersDisabled = false;
33516        }, 50);
33517    },
33518
33519    autoOffset : function(){
33520        this.setDelta(0,0);
33521    }
33522});
33523
33524
33525Ext.grid.GroupingView = Ext.extend(Ext.grid.GridView, {
33526    
33527    hideGroupedColumn:false,
33528    
33529    showGroupName:true,
33530    
33531    startCollapsed:false,
33532    
33533    enableGrouping:true,
33534    
33535    enableGroupingMenu:true,
33536    
33537    enableNoGroups:true,
33538    
33539    emptyGroupText : '(None)',
33540    
33541    ignoreAdd: false,
33542    
33543    groupTextTpl : '{text}',
33544    
33545    
33546
33547    // private
33548    gidSeed : 1000,
33549
33550    // private
33551    initTemplates : function(){
33552        Ext.grid.GroupingView.superclass.initTemplates.call(this);
33553        this.state = {};
33554
33555        var sm = this.grid.getSelectionModel();
33556        sm.on(sm.selectRow ? 'beforerowselect' : 'beforecellselect',
33557                this.onBeforeRowSelect, this);
33558
33559        if(!this.startGroup){
33560            this.startGroup = new Ext.XTemplate(
33561                '<div id="{groupId}" class="x-grid-group {cls}">',
33562                    '<div id="{groupId}-hd" class="x-grid-group-hd" style="{style}"><div>', this.groupTextTpl ,'</div></div>',
33563                    '<div id="{groupId}-bd" class="x-grid-group-body">'
33564            );
33565        }
33566        this.startGroup.compile();
33567        this.endGroup = '</div></div>';
33568    },
33569
33570    // private
33571    findGroup : function(el){
33572        return Ext.fly(el).up('.x-grid-group', this.mainBody.dom);
33573    },
33574
33575    // private
33576    getGroups : function(){
33577        return this.hasRows() ? this.mainBody.dom.childNodes : [];
33578    },
33579
33580    // private
33581    onAdd : function(){
33582        if(this.enableGrouping && !this.ignoreAdd){
33583            var ss = this.getScrollState();
33584            this.refresh();
33585            this.restoreScroll(ss);
33586        }else if(!this.enableGrouping){
33587            Ext.grid.GroupingView.superclass.onAdd.apply(this, arguments);
33588        }
33589    },
33590
33591    // private
33592    onRemove : function(ds, record, index, isUpdate){
33593        Ext.grid.GroupingView.superclass.onRemove.apply(this, arguments);
33594        var g = document.getElementById(record._groupId);
33595        if(g && g.childNodes[1].childNodes.length < 1){
33596            Ext.removeNode(g);
33597        }
33598        this.applyEmptyText();
33599    },
33600
33601    // private
33602    refreshRow : function(record){
33603        if(this.ds.getCount()==1){
33604            this.refresh();
33605        }else{
33606            this.isUpdating = true;
33607            Ext.grid.GroupingView.superclass.refreshRow.apply(this, arguments);
33608            this.isUpdating = false;
33609        }
33610    },
33611
33612    // private
33613    beforeMenuShow : function(){
33614        var field = this.getGroupField();
33615        var g = this.hmenu.items.get('groupBy');
33616        if(g){
33617            g.setDisabled(this.cm.config[this.hdCtxIndex].groupable === false);
33618        }
33619        var s = this.hmenu.items.get('showGroups');
33620        if(s){
33621           s.setDisabled(!field && this.cm.config[this.hdCtxIndex].groupable === false);
33622			s.setChecked(!!field, true);
33623        }
33624    },
33625
33626    // private
33627    renderUI : function(){
33628        Ext.grid.GroupingView.superclass.renderUI.call(this);
33629        this.mainBody.on('mousedown', this.interceptMouse, this);
33630
33631        if(this.enableGroupingMenu && this.hmenu){
33632            this.hmenu.add('-',{
33633                id:'groupBy',
33634                text: this.groupByText,
33635                handler: this.onGroupByClick,
33636                scope: this,
33637                iconCls:'x-group-by-icon'
33638            });
33639            if(this.enableNoGroups){
33640                this.hmenu.add({
33641                    id:'showGroups',
33642                    text: this.showGroupsText,
33643                    checked: true,
33644                    checkHandler: this.onShowGroupsClick,
33645                    scope: this
33646                });
33647            }
33648            this.hmenu.on('beforeshow', this.beforeMenuShow, this);
33649        }
33650    },
33651
33652    // private
33653    onGroupByClick : function(){
33654        this.grid.store.groupBy(this.cm.getDataIndex(this.hdCtxIndex));
33655        this.beforeMenuShow(); // Make sure the checkboxes get properly set when changing groups
33656    },
33657
33658    // private
33659    onShowGroupsClick : function(mi, checked){
33660        if(checked){
33661            this.onGroupByClick();
33662        }else{
33663            this.grid.store.clearGrouping();
33664        }
33665    },
33666
33667    
33668    toggleGroup : function(group, expanded){
33669        this.grid.stopEditing(true);
33670        group = Ext.getDom(group);
33671        var gel = Ext.fly(group);
33672        expanded = expanded !== undefined ?
33673                expanded : gel.hasClass('x-grid-group-collapsed');
33674
33675        this.state[gel.dom.id] = expanded;
33676        gel[expanded ? 'removeClass' : 'addClass']('x-grid-group-collapsed');
33677    },
33678
33679    
33680    toggleAllGroups : function(expanded){
33681        var groups = this.getGroups();
33682        for(var i = 0, len = groups.length; i < len; i++){
33683            this.toggleGroup(groups[i], expanded);
33684        }
33685    },
33686
33687    
33688    expandAllGroups : function(){
33689        this.toggleAllGroups(true);
33690    },
33691
33692    
33693    collapseAllGroups : function(){
33694        this.toggleAllGroups(false);
33695    },
33696
33697    // private
33698    interceptMouse : function(e){
33699        var hd = e.getTarget('.x-grid-group-hd', this.mainBody);
33700        if(hd){
33701            e.stopEvent();
33702            this.toggleGroup(hd.parentNode);
33703        }
33704    },
33705
33706    // private
33707    getGroup : function(v, r, groupRenderer, rowIndex, colIndex, ds){
33708        var g = groupRenderer ? groupRenderer(v, {}, r, rowIndex, colIndex, ds) : String(v);
33709        if(g === ''){
33710            g = this.cm.config[colIndex].emptyGroupText || this.emptyGroupText;
33711        }
33712        return g;
33713    },
33714
33715    // private
33716    getGroupField : function(){
33717        return this.grid.store.getGroupState();
33718    },
33719
33720    // private
33721    renderRows : function(){
33722        var groupField = this.getGroupField();
33723        var eg = !!groupField;
33724        // if they turned off grouping and the last grouped field is hidden
33725        if(this.hideGroupedColumn) {
33726            var colIndex = this.cm.findColumnIndex(groupField);
33727            if(!eg && this.lastGroupField !== undefined) {
33728                this.mainBody.update('');
33729                this.cm.setHidden(this.cm.findColumnIndex(this.lastGroupField), false);
33730                delete this.lastGroupField;
33731            }else if (eg && this.lastGroupField === undefined) {
33732                this.lastGroupField = groupField;
33733                this.cm.setHidden(colIndex, true);
33734            }else if (eg && this.lastGroupField !== undefined && groupField !== this.lastGroupField) {
33735                this.mainBody.update('');
33736                var oldIndex = this.cm.findColumnIndex(this.lastGroupField);
33737                this.cm.setHidden(oldIndex, false);
33738                this.lastGroupField = groupField;
33739                this.cm.setHidden(colIndex, true);
33740            }
33741        }
33742        return Ext.grid.GroupingView.superclass.renderRows.apply(
33743                    this, arguments);
33744    },
33745
33746    // private
33747    doRender : function(cs, rs, ds, startRow, colCount, stripe){
33748        if(rs.length < 1){
33749            return '';
33750        }
33751        var groupField = this.getGroupField();
33752        var colIndex = this.cm.findColumnIndex(groupField);
33753
33754        this.enableGrouping = !!groupField;
33755
33756        if(!this.enableGrouping || this.isUpdating){
33757            return Ext.grid.GroupingView.superclass.doRender.apply(
33758                    this, arguments);
33759        }
33760        var gstyle = 'width:'+this.getTotalWidth()+';';
33761
33762        var gidPrefix = this.grid.getGridEl().id;
33763        var cfg = this.cm.config[colIndex];
33764        var groupRenderer = cfg.groupRenderer || cfg.renderer;
33765        var prefix = this.showGroupName ?
33766                     (cfg.groupName || cfg.header)+': ' : '';
33767
33768        var groups = [], curGroup, i, len, gid;
33769        for(i = 0, len = rs.length; i < len; i++){
33770            var rowIndex = startRow + i;
33771            var r = rs[i],
33772                gvalue = r.data[groupField],
33773                g = this.getGroup(gvalue, r, groupRenderer, rowIndex, colIndex, ds);
33774            if(!curGroup || curGroup.group != g){
33775                gid = gidPrefix + '-gp-' + groupField + '-' + Ext.util.Format.htmlEncode(g);
33776               	// if state is defined use it, however state is in terms of expanded
33777				// so negate it, otherwise use the default.
33778				var isCollapsed  = typeof this.state[gid] !== 'undefined' ? !this.state[gid] : this.startCollapsed;
33779				var gcls = isCollapsed ? 'x-grid-group-collapsed' : '';	
33780                curGroup = {
33781                    group: g,
33782                    gvalue: gvalue,
33783                    text: prefix + g,
33784                    groupId: gid,
33785                    startRow: rowIndex,
33786                    rs: [r],
33787                    cls: gcls,
33788                    style: gstyle
33789                };
33790                groups.push(curGroup);
33791            }else{
33792                curGroup.rs.push(r);
33793            }
33794            r._groupId = gid;
33795        }
33796
33797        var buf = [];
33798        for(i = 0, len = groups.length; i < len; i++){
33799            var g = groups[i];
33800            this.doGroupStart(buf, g, cs, ds, colCount);
33801            buf[buf.length] = Ext.grid.GroupingView.superclass.doRender.call(
33802                    this, cs, g.rs, ds, g.startRow, colCount, stripe);
33803
33804            this.doGroupEnd(buf, g, cs, ds, colCount);
33805        }
33806        return buf.join('');
33807    },
33808
33809    
33810    getGroupId : function(value){
33811        var gidPrefix = this.grid.getGridEl().id;
33812        var groupField = this.getGroupField();
33813        var colIndex = this.cm.findColumnIndex(groupField);
33814        var cfg = this.cm.config[colIndex];
33815        var groupRenderer = cfg.groupRenderer || cfg.renderer;
33816        var gtext = this.getGroup(value, {data:{}}, groupRenderer, 0, colIndex, this.ds);
33817        return gidPrefix + '-gp-' + groupField + '-' + Ext.util.Format.htmlEncode(value);
33818    },
33819
33820    // private
33821    doGroupStart : function(buf, g, cs, ds, colCount){
33822        buf[buf.length] = this.startGroup.apply(g);
33823    },
33824
33825    // private
33826    doGroupEnd : function(buf, g, cs, ds, colCount){
33827        buf[buf.length] = this.endGroup;
33828    },
33829
33830    // private
33831    getRows : function(){
33832        if(!this.enableGrouping){
33833            return Ext.grid.GroupingView.superclass.getRows.call(this);
33834        }
33835        var r = [];
33836        var g, gs = this.getGroups();
33837        for(var i = 0, len = gs.length; i < len; i++){
33838            g = gs[i].childNodes[1].childNodes;
33839            for(var j = 0, jlen = g.length; j < jlen; j++){
33840                r[r.length] = g[j];
33841            }
33842        }
33843        return r;
33844    },
33845
33846    // private
33847    updateGroupWidths : function(){
33848        if(!this.enableGrouping || !this.hasRows()){
33849            return;
33850        }
33851        var tw = Math.max(this.cm.getTotalWidth(), this.el.dom.offsetWidth-this.scrollOffset) +'px';
33852        var gs = this.getGroups();
33853        for(var i = 0, len = gs.length; i < len; i++){
33854            gs[i].firstChild.style.width = tw;
33855        }
33856    },
33857
33858    // private
33859    onColumnWidthUpdated : function(col, w, tw){
33860        Ext.grid.GroupingView.superclass.onColumnWidthUpdated.call(this, col, w, tw);
33861        this.updateGroupWidths();
33862    },
33863
33864    // private
33865    onAllColumnWidthsUpdated : function(ws, tw){
33866        Ext.grid.GroupingView.superclass.onAllColumnWidthsUpdated.call(this, ws, tw);
33867        this.updateGroupWidths();
33868    },
33869
33870    // private
33871    onColumnHiddenUpdated : function(col, hidden, tw){
33872        Ext.grid.GroupingView.superclass.onColumnHiddenUpdated.call(this, col, hidden, tw);
33873        this.updateGroupWidths();
33874    },
33875
33876    // private
33877    onLayout : function(){
33878        this.updateGroupWidths();
33879    },
33880
33881    // private
33882    onBeforeRowSelect : function(sm, rowIndex){
33883        if(!this.enableGrouping){
33884            return;
33885        }
33886        var row = this.getRow(rowIndex);
33887        if(row && !row.offsetParent){
33888            var g = this.findGroup(row);
33889            this.toggleGroup(g, true);
33890        }
33891    },
33892
33893    
33894    groupByText: 'Agrupar por este campo',
33895    
33896    showGroupsText: 'Mostrar nos Grupos'
33897});
33898// private
33899Ext.grid.GroupingView.GROUP_ID = 1000;
33900// private
33901// This is a support class used internally by the Grid components
33902Ext.grid.HeaderDragZone = function(grid, hd, hd2){
33903    this.grid = grid;
33904    this.view = grid.getView();
33905    this.ddGroup = "gridHeader" + this.grid.getGridEl().id;
33906    Ext.grid.HeaderDragZone.superclass.constructor.call(this, hd);
33907    if(hd2){
33908        this.setHandleElId(Ext.id(hd));
33909        this.setOuterHandleElId(Ext.id(hd2));
33910    }
33911    this.scroll = false;
33912};
33913Ext.extend(Ext.grid.HeaderDragZone, Ext.dd.DragZone, {
33914    maxDragWidth: 120,
33915    getDragData : function(e){
33916        var t = Ext.lib.Event.getTarget(e);
33917        var h = this.view.findHeaderCell(t);
33918        if(h){
33919            return {ddel: h.firstChild, header:h};
33920        }
33921        return false;
33922    },
33923
33924    onInitDrag : function(e){
33925        this.view.headersDisabled = true;
33926        var clone = this.dragData.ddel.cloneNode(true);
33927        clone.id = Ext.id();
33928        clone.style.width = Math.min(this.dragData.header.offsetWidth,this.maxDragWidth) + "px";
33929        this.proxy.update(clone);
33930        return true;
33931    },
33932
33933    afterValidDrop : function(){
33934        var v = this.view;
33935        setTimeout(function(){
33936            v.headersDisabled = false;
33937        }, 50);
33938    },
33939
33940    afterInvalidDrop : function(){
33941        var v = this.view;
33942        setTimeout(function(){
33943            v.headersDisabled = false;
33944        }, 50);
33945    }
33946});
33947
33948// private
33949// This is a support class used internally by the Grid components
33950Ext.grid.HeaderDropZone = function(grid, hd, hd2){
33951    this.grid = grid;
33952    this.view = grid.getView();
33953    // split the proxies so they don't interfere with mouse events
33954    this.proxyTop = Ext.DomHelper.append(document.body, {
33955        cls:"col-move-top", html:"&#160;"
33956    }, true);
33957    this.proxyBottom = Ext.DomHelper.append(document.body, {
33958        cls:"col-move-bottom", html:"&#160;"
33959    }, true);
33960    this.proxyTop.hide = this.proxyBottom.hide = function(){
33961        this.setLeftTop(-100,-100);
33962        this.setStyle("visibility", "hidden");
33963    };
33964    this.ddGroup = "gridHeader" + this.grid.getGridEl().id;
33965    // temporarily disabled
33966    //Ext.dd.ScrollManager.register(this.view.scroller.dom);
33967    Ext.grid.HeaderDropZone.superclass.constructor.call(this, grid.getGridEl().dom);
33968};
33969Ext.extend(Ext.grid.HeaderDropZone, Ext.dd.DropZone, {
33970    proxyOffsets : [-4, -9],
33971    fly: Ext.Element.fly,
33972
33973    getTargetFromEvent : function(e){
33974        var t = Ext.lib.Event.getTarget(e);
33975        var cindex = this.view.findCellIndex(t);
33976        if(cindex !== false){
33977            return this.view.getHeaderCell(cindex);
33978        }
33979    },
33980
33981    nextVisible : function(h){
33982        var v = this.view, cm = this.grid.colModel;
33983        h = h.nextSibling;
33984        while(h){
33985            if(!cm.isHidden(v.getCellIndex(h))){
33986                return h;
33987            }
33988            h = h.nextSibling;
33989        }
33990        return null;
33991    },
33992
33993    prevVisible : function(h){
33994        var v = this.view, cm = this.grid.colModel;
33995        h = h.prevSibling;
33996        while(h){
33997            if(!cm.isHidden(v.getCellIndex(h))){
33998                return h;
33999            }
34000            h = h.prevSibling;
34001        }
34002        return null;
34003    },
34004
34005    positionIndicator : function(h, n, e){
34006        var x = Ext.lib.Event.getPageX(e);
34007        var r = Ext.lib.Dom.getRegion(n.firstChild);
34008        var px, pt, py = r.top + this.proxyOffsets[1];
34009        if((r.right - x) <= (r.right-r.left)/2){
34010            px = r.right+this.view.borderWidth;
34011            pt = "after";
34012        }else{
34013            px = r.left;
34014            pt = "before";
34015        }
34016        var oldIndex = this.view.getCellIndex(h);
34017        var newIndex = this.view.getCellIndex(n);
34018
34019        if(this.grid.colModel.isFixed(newIndex)){
34020            return false;
34021        }
34022
34023        var locked = this.grid.colModel.isLocked(newIndex);
34024
34025        if(pt == "after"){
34026            newIndex++;
34027        }
34028        if(oldIndex < newIndex){
34029            newIndex--;
34030        }
34031        if(oldIndex == newIndex && (locked == this.grid.colModel.isLocked(oldIndex))){
34032            return false;
34033        }
34034        px +=  this.proxyOffsets[0];
34035        this.proxyTop.setLeftTop(px, py);
34036        this.proxyTop.show();
34037        if(!this.bottomOffset){
34038            this.bottomOffset = this.view.mainHd.getHeight();
34039        }
34040        this.proxyBottom.setLeftTop(px, py+this.proxyTop.dom.offsetHeight+this.bottomOffset);
34041        this.proxyBottom.show();
34042        return pt;
34043    },
34044
34045    onNodeEnter : function(n, dd, e, data){
34046        if(data.header != n){
34047            this.positionIndicator(data.header, n, e);
34048        }
34049    },
34050
34051    onNodeOver : function(n, dd, e, data){
34052        var result = false;
34053        if(data.header != n){
34054            result = this.positionIndicator(data.header, n, e);
34055        }
34056        if(!result){
34057            this.proxyTop.hide();
34058            this.proxyBottom.hide();
34059        }
34060        return result ? this.dropAllowed : this.dropNotAllowed;
34061    },
34062
34063    onNodeOut : function(n, dd, e, data){
34064        this.proxyTop.hide();
34065        this.proxyBottom.hide();
34066    },
34067
34068    onNodeDrop : function(n, dd, e, data){
34069        var h = data.header;
34070        if(h != n){
34071            var cm = this.grid.colModel;
34072            var x = Ext.lib.Event.getPageX(e);
34073            var r = Ext.lib.Dom.getRegion(n.firstChild);
34074            var pt = (r.right - x) <= ((r.right-r.left)/2) ? "after" : "before";
34075            var oldIndex = this.view.getCellIndex(h);
34076            var newIndex = this.view.getCellIndex(n);
34077            var locked = cm.isLocked(newIndex);
34078            if(pt == "after"){
34079                newIndex++;
34080            }
34081            if(oldIndex < newIndex){
34082                newIndex--;
34083            }
34084            if(oldIndex == newIndex && (locked == cm.isLocked(oldIndex))){
34085                return false;
34086            }
34087            cm.setLocked(oldIndex, locked, true);
34088            cm.moveColumn(oldIndex, newIndex);
34089            this.grid.fireEvent("columnmove", oldIndex, newIndex);
34090            return true;
34091        }
34092        return false;
34093    }
34094});
34095
34096
34097Ext.grid.GridView.ColumnDragZone = function(grid, hd){
34098    Ext.grid.GridView.ColumnDragZone.superclass.constructor.call(this, grid, hd, null);
34099    this.proxy.el.addClass('x-grid3-col-dd');
34100};
34101
34102Ext.extend(Ext.grid.GridView.ColumnDragZone, Ext.grid.HeaderDragZone, {
34103    handleMouseDown : function(e){
34104
34105    },
34106
34107    callHandleMouseDown : function(e){
34108        Ext.grid.GridView.ColumnDragZone.superclass.handleMouseDown.call(this, e);
34109    }
34110});
34111// private
34112// This is a support class used internally by the Grid components
34113Ext.grid.SplitDragZone = function(grid, hd, hd2){
34114    this.grid = grid;
34115    this.view = grid.getView();
34116    this.proxy = this.view.resizeProxy;
34117    Ext.grid.SplitDragZone.superclass.constructor.call(this, hd,
34118        "gridSplitters" + this.grid.getGridEl().id, {
34119        dragElId : Ext.id(this.proxy.dom), resizeFrame:false
34120    });
34121    this.setHandleElId(Ext.id(hd));
34122    this.setOuterHandleElId(Ext.id(hd2));
34123    this.scroll = false;
34124};
34125Ext.extend(Ext.grid.SplitDragZone, Ext.dd.DDProxy, {
34126    fly: Ext.Element.fly,
34127
34128    b4StartDrag : function(x, y){
34129        this.view.headersDisabled = true;
34130        this.proxy.setHeight(this.view.mainWrap.getHeight());
34131        var w = this.cm.getColumnWidth(this.cellIndex);
34132        var minw = Math.max(w-this.grid.minColumnWidth, 0);
34133        this.resetConstraints();
34134        this.setXConstraint(minw, 1000);
34135        this.setYConstraint(0, 0);
34136        this.minX = x - minw;
34137        this.maxX = x + 1000;
34138        this.startPos = x;
34139        Ext.dd.DDProxy.prototype.b4StartDrag.call(this, x, y);
34140    },
34141
34142
34143    handleMouseDown : function(e){
34144        ev = Ext.EventObject.setEvent(e);
34145        var t = this.fly(ev.getTarget());
34146        if(t.hasClass("x-grid-split")){
34147            this.cellIndex = this.view.getCellIndex(t.dom);
34148            this.split = t.dom;
34149            this.cm = this.grid.colModel;
34150            if(this.cm.isResizable(this.cellIndex) && !this.cm.isFixed(this.cellIndex)){
34151                Ext.grid.SplitDragZone.superclass.handleMouseDown.apply(this, arguments);
34152            }
34153        }
34154    },
34155
34156    endDrag : function(e){
34157        this.view.headersDisabled = false;
34158        var endX = Math.max(this.minX, Ext.lib.Event.getPageX(e));
34159        var diff = endX - this.startPos;
34160        this.view.onColumnSplitterMoved(this.cellIndex, this.cm.getColumnWidth(this.cellIndex)+diff);
34161    },
34162
34163    autoOffset : function(){
34164        this.setDelta(0,0);
34165    }
34166});
34167
34168Ext.grid.GridDragZone = function(grid, config){
34169    this.view = grid.getView();
34170    Ext.grid.GridDragZone.superclass.constructor.call(this, this.view.mainBody.dom, config);
34171    if(this.view.lockedBody){
34172        this.setHandleElId(Ext.id(this.view.mainBody.dom));
34173        this.setOuterHandleElId(Ext.id(this.view.lockedBody.dom));
34174    }
34175    this.scroll = false;
34176    this.grid = grid;
34177    this.ddel = document.createElement('div');
34178    this.ddel.className = 'x-grid-dd-wrap';
34179};
34180
34181Ext.extend(Ext.grid.GridDragZone, Ext.dd.DragZone, {
34182    ddGroup : "GridDD",
34183
34184    
34185    getDragData : function(e){
34186        var t = Ext.lib.Event.getTarget(e);
34187        var rowIndex = this.view.findRowIndex(t);
34188        if(rowIndex !== false){
34189            var sm = this.grid.selModel;
34190            if(!sm.isSelected(rowIndex) || e.hasModifier()){
34191                sm.handleMouseDown(this.grid, rowIndex, e);
34192            }
34193            return {grid: this.grid, ddel: this.ddel, rowIndex: rowIndex, selections:sm.getSelections()};
34194        }
34195        return false;
34196    },
34197
34198    
34199    onInitDrag : function(e){
34200        var data = this.dragData;
34201        this.ddel.innerHTML = this.grid.getDragDropText();
34202        this.proxy.update(this.ddel);
34203        // fire start drag?
34204    },
34205
34206    
34207    afterRepair : function(){
34208        this.dragging = false;
34209    },
34210
34211    
34212    getRepairXY : function(e, data){
34213        return false;
34214    },
34215
34216    onEndDrag : function(data, e){
34217        // fire end drag?
34218    },
34219
34220    onValidDrop : function(dd, e, id){
34221        // fire drag drop?
34222        this.hideProxy();
34223    },
34224
34225    beforeInvalidDrop : function(e, id){
34226
34227    }
34228});
34229
34230
34231Ext.grid.ColumnModel = function(config){
34232    
34233    this.defaultWidth = 100;
34234
34235    
34236    this.defaultSortable = false;
34237
34238    
34239    if(config.columns){
34240        Ext.apply(this, config);
34241        this.setConfig(config.columns, true);
34242    }else{
34243        this.setConfig(config, true);
34244    }
34245    this.addEvents(
34246        
34247        "widthchange",
34248        
34249        "headerchange",
34250        
34251        "hiddenchange",
34252        
34253        "columnmoved",
34254        // deprecated - to be removed
34255        "columnlockchange",
34256        
34257        "configchange"
34258    );
34259    Ext.grid.ColumnModel.superclass.constructor.call(this);
34260};
34261Ext.extend(Ext.grid.ColumnModel, Ext.util.Observable, {
34262    
34263    
34264    
34265    
34266    
34267    
34268    
34269    
34270    
34271    
34272    
34273    
34274    
34275    
34276    
34277
34278    
34279    getColumnId : function(index){
34280        return this.config[index].id;
34281    },
34282
34283    
34284    setConfig : function(config, initial){
34285        if(!initial){ // cleanup
34286            delete this.totalWidth;
34287            for(var i = 0, len = this.config.length; i < len; i++){
34288                var c = this.config[i];
34289                if(c.editor){
34290                    c.editor.destroy();
34291                }
34292            }
34293        }
34294        this.config = config;
34295        this.lookup = {};
34296        // if no id, create one
34297        for(var i = 0, len = config.length; i < len; i++){
34298            var c = config[i];
34299            if(typeof c.renderer == "string"){
34300                c.renderer = Ext.util.Format[c.renderer];
34301            }
34302            if(typeof c.id == "undefined"){
34303                c.id = i;
34304            }
34305            if(c.editor && c.editor.isFormField){
34306                c.editor = new Ext.grid.GridEditor(c.editor);
34307            }
34308            this.lookup[c.id] = c;
34309        }
34310        if(!initial){
34311            this.fireEvent('configchange', this);
34312        }
34313    },
34314
34315    
34316    getColumnById : function(id){
34317        return this.lookup[id];
34318    },
34319
34320    
34321    getIndexById : function(id){
34322        for(var i = 0, len = this.config.length; i < len; i++){
34323            if(this.config[i].id == id){
34324                return i;
34325            }
34326        }
34327        return -1;
34328    },
34329
34330    
34331    moveColumn : function(oldIndex, newIndex){
34332        var c = this.config[oldIndex];
34333        this.config.splice(oldIndex, 1);
34334        this.config.splice(newIndex, 0, c);
34335        this.dataMap = null;
34336        this.fireEvent("columnmoved", this, oldIndex, newIndex);
34337    },
34338
34339    // deprecated - to be removed
34340    isLocked : function(colIndex){
34341        return this.config[colIndex].locked === true;
34342    },
34343
34344    // deprecated - to be removed
34345    setLocked : function(colIndex, value, suppressEvent){
34346        if(this.isLocked(colIndex) == value){
34347            return;
34348        }
34349        this.config[colIndex].locked = value;
34350        if(!suppressEvent){
34351            this.fireEvent("columnlockchange", this, colIndex, value);
34352        }
34353    },
34354
34355    // deprecated - to be removed
34356    getTotalLockedWidth : function(){
34357        var totalWidth = 0;
34358        for(var i = 0; i < this.config.length; i++){
34359            if(this.isLocked(i) && !this.isHidden(i)){
34360                this.totalWidth += this.getColumnWidth(i);
34361            }
34362        }
34363        return totalWidth;
34364    },
34365
34366    // deprecated - to be removed
34367    getLockedCount : function(){
34368        for(var i = 0, len = this.config.length; i < len; i++){
34369            if(!this.isLocked(i)){
34370                return i;
34371            }
34372        }
34373    },
34374
34375    
34376    getColumnCount : function(visibleOnly){
34377        if(visibleOnly === true){
34378            var c = 0;
34379            for(var i = 0, len = this.config.length; i < len; i++){
34380                if(!this.isHidden(i)){
34381                    c++;
34382                }
34383            }
34384            return c;
34385        }
34386        return this.config.length;
34387    },
34388
34389    
34390    getColumnsBy : function(fn, scope){
34391        var r = [];
34392        for(var i = 0, len = this.config.length; i < len; i++){
34393            var c = this.config[i];
34394            if(fn.call(scope||this, c, i) === true){
34395                r[r.length] = c;
34396            }
34397        }
34398        return r;
34399    },
34400
34401    
34402    isSortable : function(col){
34403        if(typeof this.config[col].sortable == "undefined"){
34404            return this.defaultSortable;
34405        }
34406        return this.config[col].sortable;
34407    },
34408
34409    
34410    isMenuDisabled : function(col){
34411        return !!this.config[col].menuDisabled;
34412    },
34413
34414    
34415    getRenderer : function(col){
34416        if(!this.config[col].renderer){
34417            return Ext.grid.ColumnModel.defaultRenderer;
34418        }
34419        return this.config[col].renderer;
34420    },
34421
34422    
34423    setRenderer : function(col, fn){
34424        this.config[col].renderer = fn;
34425    },
34426
34427    
34428    getColumnWidth : function(col){
34429        return this.config[col].width || this.defaultWidth;
34430    },
34431
34432    
34433    setColumnWidth : function(col, width, suppressEvent){
34434        this.config[col].width = width;
34435        this.totalWidth = null;
34436        if(!suppressEvent){
34437             this.fireEvent("widthchange", this, col, width);
34438        }
34439    },
34440
34441    
34442    getTotalWidth : function(includeHidden){
34443        if(!this.totalWidth){
34444            this.totalWidth = 0;
34445            for(var i = 0, len = this.config.length; i < len; i++){
34446                if(includeHidden || !this.isHidden(i)){
34447                    this.totalWidth += this.getColumnWidth(i);
34448                }
34449            }
34450        }
34451        return this.totalWidth;
34452    },
34453
34454    
34455    getColumnHeader : function(col){
34456        return this.config[col].header;
34457    },
34458
34459    
34460    setColumnHeader : function(col, header){
34461        this.config[col].header = header;
34462        this.fireEvent("headerchange", this, col, header);
34463    },
34464
34465    
34466    getColumnTooltip : function(col){
34467            return this.config[col].tooltip;
34468    },
34469    
34470    setColumnTooltip : function(col, tooltip){
34471            this.config[col].tooltip = tooltip;
34472    },
34473
34474    
34475    getDataIndex : function(col){
34476        return this.config[col].dataIndex;
34477    },
34478
34479    
34480    setDataIndex : function(col, dataIndex){
34481        this.config[col].dataIndex = dataIndex;
34482    },
34483
34484    
34485    findColumnIndex : function(dataIndex){
34486        var c = this.config;
34487        for(var i = 0, len = c.length; i < len; i++){
34488            if(c[i].dataIndex == dataIndex){
34489                return i;
34490            }
34491        }
34492        return -1;
34493    },
34494
34495    
34496    isCellEditable : function(colIndex, rowIndex){
34497        return (this.config[colIndex].editable || (typeof this.config[colIndex].editable == "undefined" && this.config[colIndex].editor)) ? true : false;
34498    },
34499
34500    
34501    getCellEditor : function(colIndex, rowIndex){
34502        return this.config[colIndex].editor;
34503    },
34504
34505    
34506    setEditable : function(col, editable){
34507        this.config[col].editable = editable;
34508    },
34509
34510
34511    
34512    isHidden : function(colIndex){
34513        return this.config[colIndex].hidden;
34514    },
34515
34516
34517    
34518    isFixed : function(colIndex){
34519        return this.config[colIndex].fixed;
34520    },
34521
34522    
34523    isResizable : function(colIndex){
34524        return colIndex >= 0 && this.config[colIndex].resizable !== false && this.config[colIndex].fixed !== true;
34525    },
34526    
34527    setHidden : function(colIndex, hidden){
34528        var c = this.config[colIndex];
34529        if(c.hidden !== hidden){
34530            c.hidden = hidden;
34531            this.totalWidth = null;
34532            this.fireEvent("hiddenchange", this, colIndex, hidden);
34533        }
34534    },
34535
34536    
34537    setEditor : function(col, editor){
34538        this.config[col].editor = editor;
34539    }
34540});
34541
34542// private
34543Ext.grid.ColumnModel.defaultRenderer = function(value){
34544    if(typeof value == "string" && value.length < 1){
34545        return "&#160;";
34546    }
34547    return value;
34548};
34549
34550// Alias for backwards compatibility
34551Ext.grid.DefaultColumnModel = Ext.grid.ColumnModel;
34552
34553Ext.grid.AbstractSelectionModel = function(){
34554    this.locked = false;
34555    Ext.grid.AbstractSelectionModel.superclass.constructor.call(this);
34556};
34557
34558Ext.extend(Ext.grid.AbstractSelectionModel, Ext.util.Observable,  {
34559    
34560    init : function(grid){
34561        this.grid = grid;
34562        this.initEvents();
34563    },
34564
34565    
34566    lock : function(){
34567        this.locked = true;
34568    },
34569
34570    
34571    unlock : function(){
34572        this.locked = false;
34573    },
34574
34575    
34576    isLocked : function(){
34577        return this.locked;
34578    }
34579});
34580
34581Ext.grid.RowSelectionModel = function(config){
34582    Ext.apply(this, config);
34583    this.selections = new Ext.util.MixedCollection(false, function(o){
34584        return o.id;
34585    });
34586
34587    this.last = false;
34588    this.lastActive = false;
34589
34590    this.addEvents(
34591        
34592	    "selectionchange",
34593        
34594	    "beforerowselect",
34595        
34596	    "rowselect",
34597        
34598	    "rowdeselect"
34599    );
34600
34601    Ext.grid.RowSelectionModel.superclass.constructor.call(this);
34602};
34603
34604Ext.extend(Ext.grid.RowSelectionModel, Ext.grid.AbstractSelectionModel,  {
34605    
34606    singleSelect : false,
34607
34608	
34609    // private
34610    initEvents : function(){
34611
34612        if(!this.grid.enableDragDrop && !this.grid.enableDrag){
34613            this.grid.on("rowmousedown", this.handleMouseDown, this);
34614        }else{ // allow click to work like normal
34615            this.grid.on("rowclick", function(grid, rowIndex, e) {
34616                if(e.button === 0 && !e.shiftKey && !e.ctrlKey) {
34617                    this.selectRow(rowIndex, false);
34618                    grid.view.focusRow(rowIndex);
34619                }
34620            }, this);
34621        }
34622
34623        this.rowNav = new Ext.KeyNav(this.grid.getGridEl(), {
34624            "up" : function(e){
34625                if(!e.shiftKey || this.singleSelect){
34626                    this.selectPrevious(false);
34627                }else if(this.last !== false && this.lastActive !== false){
34628                    var last = this.last;
34629                    this.selectRange(this.last,  this.lastActive-1);
34630                    this.grid.getView().focusRow(this.lastActive);
34631                    if(last !== false){
34632                        this.last = last;
34633                    }
34634                }else{
34635                    this.selectFirstRow();
34636                }
34637            },
34638            "down" : function(e){
34639                if(!e.shiftKey || this.singleSelect){
34640                    this.selectNext(false);
34641                }else if(this.last !== false && this.lastActive !== false){
34642                    var last = this.last;
34643                    this.selectRange(this.last,  this.lastActive+1);
34644                    this.grid.getView().focusRow(this.lastActive);
34645                    if(last !== false){
34646                        this.last = last;
34647                    }
34648                }else{
34649                    this.selectFirstRow();
34650                }
34651            },
34652            scope: this
34653        });
34654
34655        var view = this.grid.view;
34656        view.on("refresh", this.onRefresh, this);
34657        view.on("rowupdated", this.onRowUpdated, this);
34658        view.on("rowremoved", this.onRemove, this);
34659    },
34660
34661    // private
34662    onRefresh : function(){
34663        var ds = this.grid.store, index;
34664        var s = this.getSelections();
34665        this.clearSelections(true);
34666        for(var i = 0, len = s.length; i < len; i++){
34667            var r = s[i];
34668            if((index = ds.indexOfId(r.id)) != -1){
34669                this.selectRow(index, true);
34670            }
34671        }
34672        if(s.length != this.selections.getCount()){
34673            this.fireEvent("selectionchange", this);
34674        }
34675    },
34676
34677    // private
34678    onRemove : function(v, index, r){
34679        if(this.selections.remove(r) !== false){
34680            this.fireEvent('selectionchange', this);
34681        }
34682    },
34683
34684    // private
34685    onRowUpdated : function(v, index, r){
34686        if(this.isSelected(r)){
34687            v.onRowSelect(index);
34688        }
34689    },
34690
34691    
34692    selectRecords : function(records, keepExisting){
34693        if(!keepExisting){
34694            this.clearSelections();
34695        }
34696        var ds = this.grid.store;
34697        for(var i = 0, len = records.length; i < len; i++){
34698            this.selectRow(ds.indexOf(records[i]), true);
34699        }
34700    },
34701
34702    
34703    getCount : function(){
34704        return this.selections.length;
34705    },
34706
34707    
34708    selectFirstRow : function(){
34709        this.selectRow(0);
34710    },
34711
34712    
34713    selectLastRow : function(keepExisting){
34714        this.selectRow(this.grid.store.getCount() - 1, keepExisting);
34715    },
34716
34717    
34718    selectNext : function(keepExisting){
34719        if(this.hasNext()){
34720            this.selectRow(this.last+1, keepExisting);
34721            this.grid.getView().focusRow(this.last);
34722			return true;
34723        }
34724		return false;
34725    },
34726
34727    
34728    selectPrevious : function(keepExisting){
34729        if(this.hasPrevious()){
34730            this.selectRow(this.last-1, keepExisting);
34731            this.grid.getView().focusRow(this.last);
34732			return true;
34733        }
34734		return false;
34735    },
34736
34737    
34738    hasNext : function(){
34739        return this.last !== false && (this.last+1) < this.grid.store.getCount();
34740    },
34741
34742    
34743    hasPrevious : function(){
34744        return !!this.last;
34745    },
34746
34747
34748    
34749    getSelections : function(){
34750        return [].concat(this.selections.items);
34751    },
34752
34753    
34754    getSelected : function(){
34755        return this.selections.itemAt(0);
34756    },
34757
34758    
34759    each : function(fn, scope){
34760        var s = this.getSelections();
34761        for(var i = 0, len = s.length; i < len; i++){
34762            if(fn.call(scope || this, s[i], i) === false){
34763                return false;
34764            }
34765        }
34766        return true;
34767    },
34768
34769    
34770    clearSelections : function(fast){
34771        if(this.isLocked()) return;
34772        if(fast !== true){
34773            var ds = this.grid.store;
34774            var s = this.selections;
34775            s.each(function(r){
34776                this.deselectRow(ds.indexOfId(r.id));
34777            }, this);
34778            s.clear();
34779        }else{
34780            this.selections.clear();
34781        }
34782        this.last = false;
34783    },
34784
34785
34786    
34787    selectAll : function(){
34788        if(this.isLocked()) return;
34789        this.selections.clear();
34790        for(var i = 0, len = this.grid.store.getCount(); i < len; i++){
34791            this.selectRow(i, true);
34792        }
34793    },
34794
34795    
34796    hasSelection : function(){
34797        return this.selections.length > 0;
34798    },
34799
34800    
34801    isSelected : function(index){
34802        var r = typeof index == "number" ? this.grid.store.getAt(index) : index;
34803        return (r && this.selections.key(r.id) ? true : false);
34804    },
34805
34806    
34807    isIdSelected : function(id){
34808        return (this.selections.key(id) ? true : false);
34809    },
34810
34811    // private
34812    handleMouseDown : function(g, rowIndex, e){
34813        if(e.button !== 0 || this.isLocked()){
34814            return;
34815        };
34816        var view = this.grid.getView();
34817        if(e.shiftKey && !this.singleSelect && this.last !== false){
34818            var last = this.last;
34819            this.selectRange(last, rowIndex, e.ctrlKey);
34820            this.last = last; // reset the last
34821            view.focusRow(rowIndex);
34822        }else{
34823            var isSelected = this.isSelected(rowIndex);
34824            if(e.ctrlKey && isSelected){
34825                this.deselectRow(rowIndex);
34826            }else if(!isSelected || this.getCount() > 1){
34827                this.selectRow(rowIndex, e.ctrlKey || e.shiftKey);
34828                view.focusRow(rowIndex);
34829            }
34830        }
34831    },
34832
34833    
34834    selectRows : function(rows, keepExisting){
34835        if(!keepExisting){
34836            this.clearSelections();
34837        }
34838        for(var i = 0, len = rows.length; i < len; i++){
34839            this.selectRow(rows[i], true);
34840        }
34841    },
34842
34843    
34844    selectRange : function(startRow, endRow, keepExisting){
34845        if(this.isLocked()) return;
34846        if(!keepExisting){
34847            this.clearSelections();
34848        }
34849        if(startRow <= endRow){
34850            for(var i = startRow; i <= endRow; i++){
34851                this.selectRow(i, true);
34852            }
34853        }else{
34854            for(var i = startRow; i >= endRow; i--){
34855                this.selectRow(i, true);
34856            }
34857        }
34858    },
34859
34860    
34861    deselectRange : function(startRow, endRow, preventViewNotify){
34862        if(this.isLocked()) return;
34863        for(var i = startRow; i <= endRow; i++){
34864            this.deselectRow(i, preventViewNotify);
34865        }
34866    },
34867
34868    
34869    selectRow : function(index, keepExisting, preventViewNotify){
34870        if(this.isLocked() || (index < 0 || index >= this.grid.store.getCount()) || this.isSelected(index)) return;
34871        var r = this.grid.store.getAt(index);
34872        if(r && this.fireEvent("beforerowselect", this, index, keepExisting, r) !== false){
34873            if(!keepExisting || this.singleSelect){
34874                this.clearSelections();
34875            }
34876            this.selections.add(r);
34877            this.last = this.lastActive = index;
34878            if(!preventViewNotify){
34879                this.grid.getView().onRowSelect(index);
34880            }
34881            this.fireEvent("rowselect", this, index, r);
34882            this.fireEvent("selectionchange", this);
34883        }
34884    },
34885
34886    
34887    deselectRow : function(index, preventViewNotify){
34888        if(this.isLocked()) return;
34889        if(this.last == index){
34890            this.last = false;
34891        }
34892        if(this.lastActive == index){
34893            this.lastActive = false;
34894        }
34895        var r = this.grid.store.getAt(index);
34896        if(r){
34897            this.selections.remove(r);
34898            if(!preventViewNotify){
34899                this.grid.getView().onRowDeselect(index);
34900            }
34901            this.fireEvent("rowdeselect", this, index, r);
34902            this.fireEvent("selectionchange", this);
34903        }
34904    },
34905
34906    // private
34907    restoreLast : function(){
34908        if(this._last){
34909            this.last = this._last;
34910        }
34911    },
34912
34913    // private
34914    acceptsNav : function(row, col, cm){
34915        return !cm.isHidden(col) && cm.isCellEditable(col, row);
34916    },
34917
34918    // private
34919    onEditorKey : function(field, e){
34920        var k = e.getKey(), newCell, g = this.grid, ed = g.activeEditor;
34921        var shift = e.shiftKey;
34922        if(k == e.TAB){
34923            e.stopEvent();
34924            ed.completeEdit();
34925            if(shift){
34926                newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
34927            }else{
34928                newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
34929            }
34930        }else if(k == e.ENTER){
34931            e.stopEvent();
34932            ed.completeEdit();
34933			if(this.moveEditorOnEnter !== false){
34934				if(shift){
34935					newCell = g.walkCells(ed.row - 1, ed.col, -1, this.acceptsNav, this);
34936				}else{
34937					newCell = g.walkCells(ed.row + 1, ed.col, 1, this.acceptsNav, this);
34938				}
34939			}
34940        }else if(k == e.ESC){
34941            ed.cancelEdit();
34942        }
34943        if(newCell){
34944            g.startEditing(newCell[0], newCell[1]);
34945        }
34946    }
34947});
34948
34949Ext.grid.CellSelectionModel = function(config){
34950    Ext.apply(this, config);
34951
34952    this.selection = null;
34953
34954    this.addEvents(
34955        
34956	    "beforecellselect",
34957        
34958	    "cellselect",
34959        
34960	    "selectionchange"
34961    );
34962
34963    Ext.grid.CellSelectionModel.superclass.constructor.call(this);
34964};
34965
34966Ext.extend(Ext.grid.CellSelectionModel, Ext.grid.AbstractSelectionModel,  {
34967
34968    
34969    initEvents : function(){
34970        this.grid.on("cellmousedown", this.handleMouseDown, this);
34971        this.grid.getGridEl().on(Ext.isIE || Ext.isSafari3 ? "ke
34971ydown" : "keypress", this.handleKeyDown, this);
34972        var view = this.grid.view;
34973        view.on("refresh", this.onViewChange, this);
34974        view.on("rowupdated", this.onRowUpdated, this);
34975        view.on("beforerowremoved", this.clearSelections, this);
34976        view.on("beforerowsinserted", this.clearSelections, this);
34977        if(this.grid.isEditor){
34978            this.grid.on("beforeedit", this.beforeEdit,  this);
34979        }
34980    },
34981
34982	//private
34983    beforeEdit : function(e){
34984        this.select(e.row, e.column, false, true, e.record);
34985    },
34986
34987	//private
34988    onRowUpdated : function(v, index, r){
34989        if(this.selection && this.selection.record == r){
34990            v.onCellSelect(index, this.selection.cell[1]);
34991        }
34992    },
34993
34994	//private
34995    onViewChange : function(){
34996        this.clearSelections(true);
34997    },
34998
34999	
35000    getSelectedCell : function(){
35001        return this.selection ? this.selection.cell : null;
35002    },
35003
35004    
35005    clearSelections : function(preventNotify){
35006        var s = this.selection;
35007        if(s){
35008            if(preventNotify !== true){
35009                this.grid.view.onCellDeselect(s.cell[0], s.cell[1]);
35010            }
35011            this.selection = null;
35012            this.fireEvent("selectionchange", this, null);
35013        }
35014    },
35015
35016    
35017    hasSelection : function(){
35018        return this.selection ? true : false;
35019    },
35020
35021    
35022    handleMouseDown : function(g, row, cell, e){
35023        if(e.button !== 0 || this.isLocked()){
35024            return;
35025        };
35026        this.select(row, cell);
35027    },
35028
35029    
35030    select : function(rowIndex, colIndex, preventViewNotify, preventFocus,  r){
35031        if(this.fireEvent("beforecellselect", this, rowIndex, colIndex) !== false){
35032            this.clearSelections();
35033            r = r || this.grid.store.getAt(rowIndex);
35034            this.selection = {
35035                record : r,
35036                cell : [rowIndex, colIndex]
35037            };
35038            if(!preventViewNotify){
35039                var v = this.grid.getView();
35040                v.onCellSelect(rowIndex, colIndex);
35041                if(preventFocus !== true){
35042                    v.focusCell(rowIndex, colIndex);
35043                }
35044            }
35045            this.fireEvent("cellselect", this, rowIndex, colIndex);
35046            this.fireEvent("selectionchange", this, this.selection);
35047        }
35048    },
35049
35050	//private
35051    isSelectable : function(rowIndex, colIndex, cm){
35052        return !cm.isHidden(colIndex);
35053    },
35054
35055    
35056    handleKeyDown : function(e){
35057        if(!e.isNavKeyPress()){
35058            return;
35059        }
35060        var g = this.grid, s = this.selection;
35061        if(!s){
35062            e.stopEvent();
35063            var cell = g.walkCells(0, 0, 1, this.isSelectable,  this);
35064            if(cell){
35065                this.select(cell[0], cell[1]);
35066            }
35067            return;
35068        }
35069        var sm = this;
35070        var walk = function(row, col, step){
35071            return g.walkCells(row, col, step, sm.isSelectable,  sm);
35072        };
35073        var k = e.getKey(), r = s.cell[0], c = s.cell[1];
35074        var newCell;
35075
35076        switch(k){
35077             case e.TAB:
35078                 if(e.shiftKey){
35079                     newCell = walk(r, c-1, -1);
35080                 }else{
35081                     newCell = walk(r, c+1, 1);
35082                 }
35083             break;
35084             case e.DOWN:
35085                 newCell = walk(r+1, c, 1);
35086             break;
35087             case e.UP:
35088                 newCell = walk(r-1, c, -1);
35089             break;
35090             case e.RIGHT:
35091                 newCell = walk(r, c+1, 1);
35092             break;
35093             case e.LEFT:
35094                 newCell = walk(r, c-1, -1);
35095             break;
35096             case e.ENTER:
35097                 if(g.isEditor && !g.editing){
35098                    g.startEditing(r, c);
35099                    e.stopEvent();
35100                    return;
35101                }
35102             break;
35103        };
35104        if(newCell){
35105            this.select(newCell[0], newCell[1]);
35106            e.stopEvent();
35107        }
35108    },
35109
35110    acceptsNav : function(row, col, cm){
35111        return !cm.isHidden(col) && cm.isCellEditable(col, row);
35112    },
35113
35114    onEditorKey : function(field, e){
35115        var k = e.getKey(), newCell, g = this.grid, ed = g.activeEditor;
35116        if(k == e.TAB){
35117            if(e.shiftKey){
35118                newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
35119            }else{
35120                newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
35121            }
35122            e.stopEvent();
35123        }else if(k == e.ENTER){
35124            ed.completeEdit();
35125            e.stopEvent();
35126        }else if(k == e.ESC){
35127        	e.stopEvent();
35128            ed.cancelEdit();
35129        }
35130        if(newCell){
35131            g.startEditing(newCell[0], newCell[1]);
35132        }
35133    }
35134});
35135
35136Ext.grid.EditorGridPanel = Ext.extend(Ext.grid.GridPanel, {
35137    
35138    clicksToEdit: 2,
35139
35140    // private
35141    isEditor : true,
35142    // private
35143    detectEdit: false,
35144
35145	
35146	autoEncode : false,
35147
35148	
35149    // private
35150    trackMouseOver: false, // causes very odd FF errors
35151
35152    // private
35153    initComponent : function(){
35154        Ext.grid.EditorGridPanel.superclass.initComponent.call(this);
35155
35156        if(!this.selModel){
35157            
35158            this.selModel = new Ext.grid.CellSelectionModel();
35159        }
35160
35161        this.activeEditor = null;
35162
35163	    this.addEvents(
35164            
35165            "beforeedit",
35166            
35167            "afteredit",
35168            
35169            "validateedit"
35170        );
35171    },
35172
35173    // private
35174    initEvents : function(){
35175        Ext.grid.EditorGridPanel.superclass.initEvents.call(this);
35176
35177        this.on("bodyscroll", this.stopEditing, this, [true]);
35178        this.on("columnresize", this.stopEditing, this, [true]);
35179
35180        if(this.clicksToEdit == 1){
35181            this.on("cellclick", this.onCellDblClick, this);
35182        }else {
35183            if(this.clicksToEdit == 'auto' && this.view.mainBody){
35184                this.view.mainBody.on("mousedown", this.onAutoEditClick, this);
35185            }
35186            this.on("celldblclick", this.onCellDblClick, this);
35187        }
35188    },
35189
35190    // private
35191    onCellDblClick : function(g, row, col){
35192        this.startEditing(row, col);
35193    },
35194
35195    // private
35196    onAutoEditClick : function(e, t){
35197        if(e.button !== 0){
35198            return;
35199        }
35200        var row = this.view.findRowIndex(t);
35201        var col = this.view.findCellIndex(t);
35202        if(row !== false && col !== false){
35203            this.stopEditing();
35204            if(this.selModel.getSelectedCell){ // cell sm
35205                var sc = this.selModel.getSelectedCell();
35206                if(sc && sc.cell[0] === row && sc.cell[1] === col){
35207                    this.startEditing(row, col);
35208                }
35209            }else{
35210                if(this.selModel.isSelected(row)){
35211                    this.startEditing(row, col);
35212                }
35213            }
35214        }
35215    },
35216
35217    // private
35218    onEditComplete : function(ed, value, startValue){
35219        this.editing = false;
35220        this.activeEditor = null;
35221        ed.un("specialkey", this.selModel.onEditorKey, this.selModel);
35222		var r = ed.record;
35223        var field = this.colModel.getDataIndex(ed.col);
35224        value = this.postEditValue(value, startValue, r, field);
35225        if(String(value) !== String(startValue)){
35226            var e = {
35227                grid: this,
35228                record: r,
35229                field: field,
35230                originalValue: startValue,
35231                value: value,
35232                row: ed.row,
35233                column: ed.col,
35234                cancel:false
35235            };
35236            if(this.fireEvent("validateedit", e) !== false && !e.cancel){
35237                r.set(field, e.value);
35238                delete e.cancel;
35239                this.fireEvent("afteredit", e);
35240            }
35241        }
35242        this.view.focusCell(ed.row, ed.col);
35243    },
35244
35245    
35246    startEditing : function(row, col){
35247        this.stopEditing();
35248        if(this.colModel.isCellEditable(col, row)){
35249            this.view.ensureVisible(row, col, true);
35250            var r = this.store.getAt(row);
35251            var field = this.colModel.getDataIndex(col);
35252            var e = {
35253                grid: this,
35254                record: r,
35255                field: field,
35256                value: r.data[field],
35257                row: row,
35258                column: col,
35259                cancel:false
35260            };
35261            if(this.fireEvent("beforeedit", e) !== false && !e.cancel){
35262                this.editing = true;
35263                var ed = this.colModel.getCellEditor(col, row);
35264                if(!ed.rendered){
35265                    ed.render(this.view.getEditorParent(ed));
35266                }
35267                (function(){ // complex but required for focus issues in safari, ie and opera
35268                    ed.row = row;
35269                    ed.col = col;
35270                    ed.record = r;
35271                    ed.on("complete", this.onEditComplete, this, {single: true});
35272                    ed.on("specialkey", this.selModel.onEditorKey, this.selModel);
35273                    
35274                    this.activeEditor = ed;
35275                    var v = this.preEditValue(r, field);
35276                    ed.startEdit(this.view.getCell(row, col).firstChild, v === undefined ? '' : v);
35277                }).defer(50, this);
35278            }
35279        }
35280    },
35281
35282    // private
35283	preEditValue : function(r, field){
35284        var value = r.data[field];
35285		return this.autoEncode && typeof value == 'string' ? Ext.util.Format.htmlDecode(value) : value;
35286	},
35287
35288    // private
35289	postEditValue : function(value, originalValue, r, field){
35290		return this.autoEncode && typeof value == 'string' ? Ext.util.Format.htmlEncode(value) : value;
35291	},
35292
35293    
35294    stopEditing : function(cancel){
35295        if(this.activeEditor){
35296            this.activeEditor[cancel === true ? 'cancelEdit' : 'completeEdit']();
35297        }
35298        this.activeEditor = null;
35299    },
35300
35301    // private
35302    onDestroy: function() {
35303        if(this.rendered){
35304            var cols = this.colModel.config;
35305            for(var i = 0, len = cols.length; i < len; i++){
35306                var c = cols[i];
35307                Ext.destroy(c.editor);
35308            }
35309        }
35310        Ext.grid.EditorGridPanel.superclass.onDestroy.call(this);
35311    }
35312});
35313Ext.reg('editorgrid', Ext.grid.EditorGridPanel);
35314// private
35315// This is a support class used internally by the Grid components
35316Ext.grid.GridEditor = function(field, config){
35317    Ext.grid.GridEditor.superclass.constructor.call(this, field, config);
35318    field.monitorTab = false;
35319};
35320
35321Ext.extend(Ext.grid.GridEditor, Ext.Editor, {
35322    alignment: "tl-tl",
35323    autoSize: "width",
35324    hideEl : false,
35325    cls: "x-small-editor x-grid-editor",
35326    shim:false,
35327    shadow:false
35328});
35329
35330Ext.grid.PropertyRecord = Ext.data.Record.create([
35331    {name:'name',type:'string'}, 'value'
35332]);
35333
35334
35335Ext.grid.PropertyStore = function(grid, source){
35336    this.grid = grid;
35337    this.store = new Ext.data.Store({
35338        recordType : Ext.grid.PropertyRecord
35339    });
35340    this.store.on('update', this.onUpdate,  this);
35341    if(source){
35342        this.setSource(source);
35343    }
35344    Ext.grid.PropertyStore.superclass.constructor.call(this);
35345};
35346Ext.extend(Ext.grid.PropertyStore, Ext.util.Observable, {
35347    // protected - should only be called by the grid.  Use grid.setSource instead.
35348    setSource : function(o){
35349        this.source = o;
35350        this.store.removeAll();
35351        var data = [];
35352        for(var k in o){
35353            if(this.isEditableValue(o[k])){
35354                data.push(new Ext.grid.PropertyRecord({name: k, value: o[k]}, k));
35355            }
35356        }
35357        this.store.loadRecords({records: data}, {}, true);
35358    },
35359
35360    // private
35361    onUpdate : function(ds, record, type){
35362        if(type == Ext.data.Record.EDIT){
35363            var v = record.data['value'];
35364            var oldValue = record.modified['value'];
35365            if(this.grid.fireEvent('beforepropertychange', this.source, record.id, v, oldValue) !== false){
35366                this.source[record.id] = v;
35367                record.commit();
35368                this.grid.fireEvent('propertychange', this.source, record.id, v, oldValue);
35369            }else{
35370                record.reject();
35371            }
35372        }
35373    },
35374
35375    // private
35376    getProperty : function(row){
35377       return this.store.getAt(row);
35378    },
35379
35380    // private
35381    isEditableValue: function(val){
35382        if(Ext.isDate(val)){
35383            return true;
35384        }else if(typeof val == 'object' || typeof val == 'function'){
35385            return false;
35386        }
35387        return true;
35388    },
35389
35390    // private
35391    setValue : function(prop, value){
35392        this.source[prop] = value;
35393        this.store.getById(prop).set('value', value);
35394    },
35395
35396    // protected - should only be called by the grid.  Use grid.getSource instead.
35397    getSource : function(){
35398        return this.source;
35399    }
35400});
35401
35402
35403Ext.grid.PropertyColumnModel = function(grid, store){
35404    this.grid = grid;
35405    var g = Ext.grid;
35406    g.PropertyColumnModel.superclass.constructor.call(this, [
35407        {header: this.nameText, width:50, sortable: true, dataIndex:'name', id: 'name', menuDisabled:true},
35408        {header: this.valueText, width:50, resizable:false, dataIndex: 'value', id: 'value', menuDisabled:true}
35409    ]);
35410    this.store = store;
35411    this.bselect = Ext.DomHelper.append(document.body, {
35412        tag: 'select', cls: 'x-grid-editor x-hide-display', children: [
35413            {tag: 'option', value: 'true', html: 'true'},
35414            {tag: 'option', value: 'false', html: 'false'}
35415        ]
35416    });
35417    var f = Ext.form;
35418
35419    var bfield = new f.Field({
35420        el:this.bselect,
35421        bselect : this.bselect,
35422        autoShow: true,
35423        getValue : function(){
35424            return this.bselect.value == 'true';
35425        }
35426    });
35427    this.editors = {
35428        'date' : new g.GridEditor(new f.DateField({selectOnFocus:true})),
35429        'string' : new g.GridEditor(new f.TextField({selectOnFocus:true})),
35430        'number' : new g.GridEditor(new f.NumberField({selectOnFocus:true, style:'text-align:left;'})),
35431        'boolean' : new g.GridEditor(bfield)
35432    };
35433    this.renderCellDelegate = this.renderCell.createDelegate(this);
35434    this.renderPropDelegate = this.renderProp.createDelegate(this);
35435};
35436
35437Ext.extend(Ext.grid.PropertyColumnModel, Ext.grid.ColumnModel, {
35438    // private - strings used for locale support
35439    nameText : 'Name',
35440    valueText : 'Value',
35441    dateFormat : 'm/j/Y',
35442
35443    // private
35444    renderDate : function(dateVal){
35445        return dateVal.dateFormat(this.dateFormat);
35446    },
35447
35448    // private
35449    renderBool : function(bVal){
35450        return bVal ? 'true' : 'false';
35451    },
35452
35453    // private
35454    isCellEditable : function(colIndex, rowIndex){
35455        return colIndex == 1;
35456    },
35457
35458    // private
35459    getRenderer : function(col){
35460        return col == 1 ?
35461            this.renderCellDelegate : this.renderPropDelegate;
35462    },
35463
35464    // private
35465    renderProp : function(v){
35466        return this.getPropertyName(v);
35467    },
35468
35469    // private
35470    renderCell : function(val){
35471        var rv = val;
35472        if(Ext.isDate(val)){
35473            rv = this.renderDate(val);
35474        }else if(typeof val == 'boolean'){
35475            rv = this.renderBool(val);
35476        }
35477        return Ext.util.Format.htmlEncode(rv);
35478    },
35479
35480    // private
35481    getPropertyName : function(name){
35482        var pn = this.grid.propertyNames;
35483        return pn && pn[name] ? pn[name] : name;
35484    },
35485
35486    // private
35487    getCellEditor : function(colIndex, rowIndex){
35488        var p = this.store.getProperty(rowIndex);
35489        var n = p.data['name'], val = p.data['value'];
35490        if(this.grid.customEditors[n]){
35491            return this.grid.customEditors[n];
35492        }
35493        if(Ext.isDate(val)){
35494            return this.editors['date'];
35495        }else if(typeof val == 'number'){
35496            return this.editors['number'];
35497        }else if(typeof val == 'boolean'){
35498            return this.editors['boolean'];
35499        }else{
35500            return this.editors['string'];
35501        }
35502    }
35503});
35504
35505
35506Ext.grid.PropertyGrid = Ext.extend(Ext.grid.EditorGridPanel, {
35507    
35508    
35509    
35510
35511    // private config overrides
35512    enableColumnMove:false,
35513    stripeRows:false,
35514    trackMouseOver: false,
35515    clicksToEdit:1,
35516    enableHdMenu : false,
35517    viewConfig : {
35518        forceFit:true
35519    },
35520
35521    // private
35522    initComponent : function(){
35523        this.customEditors = this.customEditors || {};
35524        this.lastEditRow = null;
35525        var store = new Ext.grid.PropertyStore(this);
35526        this.propStore = store;
35527        var cm = new Ext.grid.PropertyColumnModel(this, store);
35528        store.store.sort('name', 'ASC');
35529        this.addEvents(
35530            
35531            'beforepropertychange',
35532            
35533            'propertychange'
35534        );
35535        this.cm = cm;
35536        this.ds = store.store;
35537        Ext.grid.PropertyGrid.superclass.initComponent.call(this);
35538
35539        this.selModel.on('beforecellselect', function(sm, rowIndex, colIndex){
35540            if(colIndex === 0){
35541                this.startEditing.defer(200, this, [rowIndex, 1]);
35542                return false;
35543            }
35544        }, this);
35545    },
35546
35547    // private
35548    onRender : function(){
35549        Ext.grid.PropertyGrid.superclass.onRender.apply(this, arguments);
35550
35551        this.getGridEl().addClass('x-props-grid');
35552    },
35553
35554    // private
35555    afterRender: function(){
35556        Ext.grid.PropertyGrid.superclass.afterRender.apply(this, arguments);
35557        if(this.source){
35558            this.setSource(this.source);
35559        }
35560    },
35561
35562    
35563    setSource : function(source){
35564        this.propStore.setSource(source);
35565    },
35566
35567    
35568    getSource : function(){
35569        return this.propStore.getSource();
35570    }
35571});
35572Ext.reg("propertygrid", Ext.grid.PropertyGrid);
35573
35574
35575Ext.grid.RowNumberer = function(config){
35576    Ext.apply(this, config);
35577    if(this.rowspan){
35578        this.renderer = this.renderer.createDelegate(this);
35579    }
35580};
35581
35582Ext.grid.RowNumberer.prototype = {
35583    
35584    header: "",
35585    
35586    width: 23,
35587    
35588    sortable: false,
35589
35590    // private
35591    fixed:true,
35592    menuDisabled:true,
35593    dataIndex: '',
35594    id: 'numberer',
35595    rowspan: undefined,
35596
35597    // private
35598    renderer : function(v, p, record, rowIndex){
35599        if(this.rowspan){
35600            p.cellAttr = 'rowspan="'+this.rowspan+'"';
35601        }
35602        return rowIndex+1;
35603    }
35604};
35605
35606Ext.grid.CheckboxSelectionModel = Ext.extend(Ext.grid.RowSelectionModel, {
35607    
35608    header: '<div class="x-grid3-hd-checker">&#160;</div>',
35609    
35610    width: 20,
35611    
35612    sortable: false,
35613
35614    // private
35615    menuDisabled:true,
35616    fixed:true,
35617    dataIndex: '',
35618    id: 'checker',
35619
35620    // private
35621    initEvents : function(){
35622        Ext.grid.CheckboxSelectionModel.superclass.initEvents.call(this);
35623        this.grid.on('render', function(){
35624            var view = this.grid.getView();
35625            view.mainBody.on('mousedown', this.onMouseDown, this);
35626            Ext.fly(view.innerHd).on('mousedown', this.onHdMouseDown, this);
35627
35628        }, this);
35629    },
35630
35631    // private
35632    onMouseDown : function(e, t){
35633        if(e.button === 0 && t.className == 'x-grid3-row-checker'){ // Only fire if left-click
35634            e.stopEvent();
35635            var row = e.getTarget('.x-grid3-row');
35636            if(row){
35637                var index = row.rowIndex;
35638                if(this.isSelected(index)){
35639                    this.deselectRow(index);
35640                }else{
35641                    this.selectRow(index, true);
35642                }
35643            }
35644        }
35645    },
35646
35647    // private
35648    onHdMouseDown : function(e, t){
35649        if(t.className == 'x-grid3-hd-checker'){
35650            e.stopEvent();
35651            var hd = Ext.fly(t.parentNode);
35652            var isChecked = hd.hasClass('x-grid3-hd-checker-on');
35653            if(isChecked){
35654                hd.removeClass('x-grid3-hd-checker-on');
35655                this.clearSelections();
35656            }else{
35657                hd.addClass('x-grid3-hd-checker-on');
35658                this.selectAll();
35659            }
35660        }
35661    },
35662
35663    // private
35664    renderer : function(v, p, record){
35665        return '<div class="x-grid3-row-checker">&#160;</div>';
35666    }
35667});
35668
35669Ext.LoadMask = function(el, config){
35670    this.el = Ext.get(el);
35671    Ext.apply(this, config);
35672    if(this.store){
35673        this.store.on('beforeload', this.onBeforeLoad, this);
35674        this.store.on('load', this.onLoad, this);
35675        this.store.on('loadexception', this.onLoad, this);
35676        this.removeMask = Ext.value(this.removeMask, false);
35677    }else{
35678        var um = this.el.getUpdater();
35679        um.showLoadIndicator = false; // disable the default indicator
35680        um.on('beforeupdate', this.onBeforeLoad, this);
35681        um.on('update', this.onLoad, this);
35682        um.on('failure', this.onLoad, this);
35683        this.removeMask = Ext.value(this.removeMask, true);
35684    }
35685};
35686
35687Ext.LoadMask.prototype = {
35688    
35689    
35690    
35691    msg : 'Loading...',
35692    
35693    msgCls : 'x-mask-loading',
35694
35695    
35696    disabled: false,
35697
35698    
35699    disable : function(){
35700       this.disabled = true;
35701    },
35702
35703    
35704    enable : function(){
35705        this.disabled = false;
35706    },
35707
35708    // private
35709    onLoad : function(){
35710        this.el.unmask(this.removeMask);
35711    },
35712
35713    // private
35714    onBeforeLoad : function(){
35715        if(!this.disabled){
35716            this.el.mask(this.msg, this.msgCls);
35717        }
35718    },
35719
35720    
35721    show: function(){
35722        this.onBeforeLoad();
35723    },
35724
35725    
35726    hide: function(){
35727        this.onLoad();    
35728    },
35729
35730    // private
35731    destroy : function(){
35732        if(this.store){
35733            this.store.un('beforeload', this.onBeforeLoad, this);
35734            this.store.un('load', this.onLoad, this);
35735            this.store.un('loadexception', this.onLoad, this);
35736        }else{
35737            var um = this.el.getUpdater();
35738            um.un('beforeupdate', this.onBeforeLoad, this);
35739            um.un('update', this.onLoad, this);
35740            um.un('failure', this.onLoad, this);
35741        }
35742    }
35743};
35744
35745Ext.ProgressBar = Ext.extend(Ext.BoxComponent, {
35746   
35747    baseCls : 'x-progress',
35748    
35749    
35750    animate : false,
35751
35752    // private
35753    waitTimer : null,
35754
35755    // private
35756    initComponent : function(){
35757        Ext.ProgressBar.superclass.initComponent.call(this);
35758        this.addEvents(
35759            
35760            "update"
35761        );
35762    },
35763
35764    // private
35765    onRender : function(ct, position){
35766        Ext.ProgressBar.superclass.onRender.call(this, ct, position);
35767
35768        var tpl = new Ext.Template(
35769            '<div class="{cls}-wrap">',
35770                '<div class="{cls}-inner">',
35771                    '<div class="{cls}-bar">',
35772                        '<div class="{cls}-text">',
35773                            '<div>&#160;</div>',
35774                        '</div>',
35775                    '</div>',
35776                    '<div class="{cls}-text {cls}-text-back">',
35777                        '<div>&#160;</div>',
35778                    '</div>',
35779                '</div>',
35780            '</div>'
35781        );
35782
35783        if(position){
35784            this.el = tpl.insertBefore(position, {cls: this.baseCls}, true);
35785        }else{
35786            this.el = tpl.append(ct, {cls: this.baseCls}, true);
35787        }
35788        if(this.id){
35789            this.el.dom.id = this.id;
35790        }
35791        var inner = this.el.dom.firstChild;
35792        this.progressBar = Ext.get(inner.firstChild);
35793
35794        if(this.textEl){
35795            //use an external text el
35796            this.textEl = Ext.get(this.textEl);
35797            delete this.textTopEl;
35798        }else{
35799            //setup our internal layered text els
35800            this.textTopEl = Ext.get(this.progressBar.dom.firstChild);
35801            var textBackEl = Ext.get(inner.childNodes[1]);
35802            this.textTopEl.setStyle("z-index", 99).addClass('x-hidden');
35803            this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, textBackEl.dom.firstChild]);
35804            this.textEl.setWidth(inner.offsetWidth);
35805        }
35806        this.progressBar.setHeight(inner.offsetHeight);
35807    },
35808    
35809    // private
35810	afterRender : function(){
35811		Ext.ProgressBar.superclass.afterRender.call(this);
35812		if(this.value){
35813			this.updateProgress(this.value, this.text);
35814		}else{
35815			this.updateText(this.text);
35816		}
35817	},
35818
35819    
35820    updateProgress : function(value, text, animate){
35821        this.value = value || 0;
35822        if(text){
35823            this.updateText(text);
35824        }
35825        if(this.rendered){
35826	        var w = Math.floor(value*this.el.dom.firstChild.offsetWidth);
35827	        this.progressBar.setWidth(w, animate === true || (animate !== false && this.animate));
35828	        if(this.textTopEl){
35829	            //textTopEl should be the same width as the bar so overflow will clip as the bar moves
35830	            this.textTopEl.removeClass('x-hidden').setWidth(w);
35831	        }
35832        }
35833        this.fireEvent('update', this, value, text);
35834        return this;
35835    },
35836
35837    
35838    wait : function(o){
35839        if(!this.waitTimer){
35840            var scope = this;
35841            o = o || {};
35842            this.updateText(o.text);
35843            this.waitTimer = Ext.TaskMgr.start({
35844                run: function(i){
35845                    var inc = o.increment || 10;
35846                    this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*.01, null, o.animate);
35847                },
35848                interval: o.interval || 1000,
35849                duration: o.duration,
35850                onStop: function(){
35851                    if(o.fn){
35852                        o.fn.apply(o.scope || this);
35853                    }
35854                    this.reset();
35855                },
35856                scope: scope
35857            });
35858        }
35859        return this;
35860    },
35861
35862    
35863    isWaiting : function(){
35864        return this.waitTimer != null;
35865    },
35866
35867    
35868    updateText : function(text){
35869        this.text = text || '&#160;';
35870        if(this.rendered){
35871            this.textEl.update(this.text);
35872        }
35873        return this;
35874    },
35875    
35876    
35877    syncProgressBar : function(){
35878        if(this.value){
35879            this.updateProgress(this.value, this.text);
35880        }
35881        return this;
35882    },
35883
35884    
35885    setSize : function(w, h){
35886        Ext.ProgressBar.superclass.setSize.call(this, w, h);
35887        if(this.textTopEl){
35888            var inner = this.el.dom.firstChild;
35889            this.textEl.setSize(inner.offsetWidth, inner.offsetHeight);
35890        }
35891        this.syncProgressBar();
35892        return this;
35893    },
35894
35895    
35896    reset : function(hide){
35897        this.updateProgress(0);
35898        if(this.textTopEl){
35899            this.textTopEl.addClass('x-hidden');
35900        }
35901        if(this.waitTimer){
35902            this.waitTimer.onStop = null; //prevent recursion
35903            Ext.TaskMgr.stop(this.waitTimer);
35904            this.waitTimer = null;
35905        }
35906        if(hide === true){
35907            this.hide();
35908        }
35909        return this;
35910    }
35911});
35912Ext.reg('progress', Ext.ProgressBar);
35913
35914Ext.Slider = Ext.extend(Ext.BoxComponent, {
35915	
35916	
35917    vertical: false,
35918	
35919    minValue: 0,
35920		
35921    maxValue: 100,
35922	
35923    keyIncrement: 1,
35924	
35925    increment: 0,
35926	// private
35927    clickRange: [5,15],
35928	
35929    clickToChange : true,
35930	
35931    animate: true,
35932
35933    
35934    dragging: false,
35935
35936    // private override
35937    initComponent : function(){
35938        if(this.value === undefined){
35939            this.value = this.minValue;
35940        }
35941        Ext.Slider.superclass.initComponent.call(this);
35942        this.keyIncrement = Math.max(this.increment, this.keyIncrement); 
35943        this.addEvents(
35944            		
35945			'beforechange', 
35946			
35947			'change',
35948			
35949			'changecomplete',
35950			
35951			'dragstart', 
35952			
35953			'drag', 
35954			
35955			'dragend'
35956		);
35957
35958        if(this.vertical){
35959            Ext.apply(this, Ext.Slider.Vertical);
35960        }
35961    },
35962
35963	// private override
35964    onRender : function(){
35965        this.autoEl = {
35966            cls: 'x-slider ' + (this.vertical ? 'x-slider-vert' : 'x-slider-horz'),
35967            cn:{cls:'x-slider-end',cn:{cls:'x-slider-inner',cn:[{cls:'x-slider-thumb'},{tag:'a', cls:'x-slider-focus', href:"#", tabIndex: '-1', hidefocus:'on'}]}}
35968        };
35969        Ext.Slider.superclass.onRender.apply(this, arguments);
35970        this.endEl = this.el.first();
35971        this.innerEl = this.endEl.first();
35972        this.thumb = this.innerEl.first();
35973        this.halfThumb = (this.vertical ? this.thumb.getHeight() : this.thumb.getWidth())/2;
35974        this.focusEl = this.thumb.next();
35975        this.initEvents();
35976    },
35977
35978	// private override
35979    initEvents : function(){
35980        this.thumb.addClassOnOver('x-slider-thumb-over');
35981        this.mon(this.el, 'mousedown', this.onMouseDown, this);
35982        this.mon(this.el, 'keydown', this.onKeyDown, this);
35983
35984        this.focusEl.swallowEvent("click", true);
35985
35986        this.tracker = new Ext.dd.DragTracker({
35987            onBeforeStart: this.onBeforeDragStart.createDelegate(this),
35988            onStart: this.onDragStart.createDelegate(this),
35989            onDrag: this.onDrag.createDelegate(this),
35990            onEnd: this.onDragEnd.createDelegate(this),
35991            tolerance: 3,
35992            autoStart: 300
35993        });
35994        this.tracker.initEl(this.thumb);
35995        this.on('beforedestroy', this.tracker.destroy, this.tracker);
35996    },
35997
35998	// private override
35999    onMouseDown : function(e){
36000        if(this.disabled) {return;}
36001        if(this.clickToChange && e.target != this.thumb.dom){
36002            var local = this.innerEl.translatePoints(e.getXY());
36003            this.onClickChange(local);
36004        }
36005        this.focus();
36006    },
36007
36008	// private
36009    onClickChange : function(local){
36010        if(local.top > this.clickRange[0] && local.top < this.clickRange[1]){
36011            this.setValue(Math.round(this.reverseValue(local.left)), undefined, true);
36012        }
36013    },
36014	
36015	// private
36016    onKeyDown : function(e){
36017        if(this.disabled){e.preventDefault();return;}
36018        var k = e.getKey();
36019        switch(k){
36020            case e.UP:
36021            case e.RIGHT:
36022                e.stopEvent();
36023                if(e.ctrlKey){
36024                    this.setValue(this.maxValue, undefined, true);
36025                }else{
36026                    this.setValue(this.value+this.keyIncrement, undefined, true);
36027                }
36028            break;
36029            case e.DOWN:
36030            case e.LEFT:
36031                e.stopEvent();
36032                if(e.ctrlKey){
36033                    this.setValue(this.minValue, undefined, true);
36034                }else{
36035                    this.setValue(this.value-this.keyIncrement, undefined, true);
36036                }
36037            break;
36038            default:
36039                e.preventDefault();
36040        }
36041    },
36042	
36043	// private
36044    doSnap : function(value){
36045        if(!this.increment || this.increment == 1 || !value) {
36046            return value;
36047        }
36048        var newValue = value, inc = this.increment;
36049        var m = value % inc;
36050        if(m > 0){
36051            if(m > (inc/2)){
36052                newValue = value + (inc-m);
36053            }else{
36054                newValue = value - m;
36055            }
36056        }
36057        return newValue.constrain(this.minValue,  this.maxValue);
36058    },
36059	
36060	// private
36061    afterRender : function(){
36062        Ext.Slider.superclass.afterRender.apply(this, arguments);
36063        if(this.value !== undefined){
36064            var v = this.normalizeValue(this.value);
36065            if(v !== this.value){
36066                delete this.value;
36067                this.setValue(v, false);
36068            }else{
36069                this.moveThumb(this.translateValue(v), false);
36070            }
36071        }
36072    },
36073
36074	// private
36075    getRatio : function(){
36076        var w = this.innerEl.getWidth();
36077        var v = this.maxValue - this.minValue;
36078        return v == 0 ? w : (w/v);
36079    },
36080
36081	// private
36082    normalizeValue : function(v){
36083       if(typeof v != 'number'){
36084            v = parseInt(v);
36085        }
36086        v = Math.round(v);
36087        v = this.doSnap(v);
36088        v = v.constrain(this.minValue, this.maxValue);
36089        return v;
36090    },
36091
36092	
36093    setValue : function(v, animate, changeComplete){
36094        v = this.normalizeValue(v);
36095        if(v !== this.value && this.fireEvent('beforechange', this, v, this.value) !== false){
36096            this.value = v;
36097            this.moveThumb(this.translateValue(v), animate !== false);
36098            this.fireEvent('change', this, v);
36099            if(changeComplete){
36100                this.fireEvent('changecomplete', this, v);
36101            }
36102        }
36103    },
36104
36105	// private
36106    translateValue : function(v){
36107        var ratio = this.getRatio();
36108        return (v * ratio)-(this.minValue * ratio)-this.halfThumb;
36109    },
36110
36111	reverseValue : function(pos){
36112        var ratio = this.getRatio();
36113        return (pos+this.halfThumb+(this.minValue * ratio))/ratio;
36114    },
36115
36116	// private
36117    moveThumb: function(v, animate){
36118        if(!animate || this.animate === false){
36119            this.thumb.setLeft(v);
36120        }else{
36121            this.thumb.shift({left: v, stopFx: true, duration:.35});
36122        }
36123    },
36124
36125	// private
36126    focus : function(){
36127        this.focusEl.focus(10);
36128    },
36129
36130	// private
36131    onBeforeDragStart : function(e){
36132        return !this.disabled;
36133    },
36134
36135	// private
36136    onDragStart: function(e){
36137        this.thumb.addClass('x-slider-thumb-drag');
36138        this.dragging = true;
36139        this.dragStartValue = this.value;
36140        this.fireEvent('dragstart', this, e);
36141    },
36142
36143	// private
36144    onDrag: function(e){
36145        var pos = this.innerEl.translatePoints(this.tracker.getXY());
36146        this.setValue(Math.round(this.reverseValue(pos.left)), false);
36147        this.fireEvent('drag', this, e);
36148    },
36149	
36150	// private
36151    onDragEnd: function(e){
36152        this.thumb.removeClass('x-slider-thumb-drag');
36153        this.dragging = false;
36154        this.fireEvent('dragend', this, e);
36155        if(this.dragStartValue != this.value){
36156            this.fireEvent('changecomplete', this, this.value);
36157        }
36158    },
36159    
36160    //private
36161    onDisable: function(){
36162        Ext.Slider.superclass.onDisable.call(this);
36163        this.thumb.addClass(this.disabledClass);
36164        if(Ext.isIE){
36165            //IE breaks when using overflow visible and opacity other than 1.
36166            //Create a place holder for the thumb and display it.
36167            var xy = this.thumb.getXY();
36168            this.thumb.hide();
36169            this.innerEl.addClass(this.disabledClass).dom.disabled = true;
36170            if (!this.thumbHolder){
36171                this.thumbHolder = this.endEl.createChild({cls: 'x-slider-thumb ' + this.disabledClass});    
36172            }
36173            this.thumbHolder.show().setXY(xy);
36174        }
36175    },
36176    
36177    //private
36178    onEnable: function(){
36179        Ext.Slider.superclass.onEnable.call(this);
36180        this.thumb.removeClass(this.disabledClass);
36181        if(Ext.isIE){
36182            this.innerEl.removeClass(this.disabledClass).dom.disabled = false;
36183            if (this.thumbHolder){
36184                this.thumbHolder.hide();
36185            }
36186            this.thumb.show();
36187            this.syncThumb();
36188        }
36189    },
36190
36191    // private
36192    onResize : function(w, h){
36193        this.innerEl.setWidth(w - (this.el.getPadding('l') + this.endEl.getPadding('r')));
36194        this.syncThumb();
36195    },
36196    
36197    
36198    syncThumb : function(){
36199        if(this.rendered){
36200            this.moveThumb(this.translateValue(this.value));
36201        }
36202    },
36203	
36204	
36205    getValue : function(){
36206        return this.value;
36207    }
36208});
36209Ext.reg('slider', Ext.Slider);
36210
36211// private class to support vertical sliders
36212Ext.Slider.Vertical = {
36213    onResize : function(w, h){
36214        this.innerEl.setHeight(h - (this.el.getPadding('t') + this.endEl.getPadding('b')));
36215        this.syncThumb();
36216    },
36217
36218    getRatio : function(){
36219        var h = this.innerEl.getHeight();
36220        var v = this.maxValue - this.minValue;
36221        return h/v;
36222    },
36223
36224    moveThumb: function(v, animate){
36225        if(!animate || this.animate === false){
36226            this.thumb.setBottom(v);
36227        }else{
36228            this.thumb.shift({bottom: v, stopFx: true, duration:.35});
36229        }
36230    },
36231
36232    onDrag: function(e){
36233        var pos = this.innerEl.translatePoints(this.tracker.getXY());
36234        var bottom = this.innerEl.getHeight()-pos.top;
36235        this.setValue(this.minValue + Math.round(bottom/this.getRatio()), false);
36236        this.fireEvent('drag', this, e);
36237    },
36238
36239    onClickChange : function(local){
36240        if(local.left > this.clickRange[0] && local.left < this.clickRange[1]){
36241            var bottom = this.innerEl.getHeight()-local.top;
36242            this.setValue(this.minValue + Math.round(bottom/this.getRatio()), undefined, true);
36243        }
36244    }
36245};
36246
36247Ext.StatusBar = Ext.extend(Ext.Toolbar, {
36248    
36249    
36250    
36251    
36252    
36253    
36254    
36255    cls : 'x-statusbar',
36256    
36257    busyIconCls : 'x-status-busy',
36258    
36259    busyText : 'Loading...',
36260    
36261    autoClear : 5000,
36262    
36263    // private
36264    activeThreadId : 0,
36265    
36266    // private
36267    initComponent : function(){
36268        if(this.statusAlign=='right'){
36269            this.cls += ' x-status-right';
36270        }
36271        Ext.StatusBar.superclass.initComponent.call(this);
36272    },
36273    
36274    // private
36275    afterRender : function(){
36276        Ext.StatusBar.superclass.afterRender.call(this);
36277        
36278        var right = this.statusAlign=='right',
36279            td = Ext.get(this.nextBlock());
36280        
36281        if(right){
36282            this.tr.appendChild(td.dom);
36283        }else{
36284            td.insertBefore(this.tr.firstChild);
36285        }
36286        
36287        this.statusEl = td.createChild({
36288            cls: 'x-status-text ' + (this.iconCls || this.defaultIconCls || ''),
36289            html: this.text || this.defaultText || ''
36290        });
36291        this.statusEl.unselectable();
36292        
36293        this.spacerEl = td.insertSibling({
36294            tag: 'td',
36295            style: 'width:100%',
36296            cn: [{cls:'ytb-spacer'}]
36297        }, right ? 'before' : 'after');
36298    },
36299
36300    
36301    setStatus : function(o){
36302        o = o || {};
36303        
36304        if(typeof o == 'string'){
36305            o = {text:o};
36306        }
36307        if(o.text !== undefined){
36308            this.setText(o.text);
36309        }
36310        if(o.iconCls !== undefined){
36311            this.setIcon(o.iconCls);
36312        }
36313        
36314        if(o.clear){
36315            var c = o.clear,
36316                wait = this.autoClear,
36317                defaults = {useDefaults: true, anim: true};
36318            
36319            if(typeof c == 'object'){
36320                c = Ext.applyIf(c, defaults);
36321                if(c.wait){
36322                    wait = c.wait;
36323                }
36324            }else if(typeof c == 'number'){
36325                wait = c;
36326                c = defaults;
36327            }else if(typeof c == 'boolean'){
36328                c = defaults;
36329            }
36330            
36331            c.threadId = this.activeThreadId;
36332            this.clearStatus.defer(wait, this, [c]);
36333        }
36334        return this;
36335    },
36336     
36337    
36338    clearStatus : function(o){
36339        o = o || {};
36340        
36341        if(o.threadId && o.threadId !== this.activeThreadId){
36342            // this means the current call was made internally, but a newer
36343            // thread has set a message since this call was deferred.  Since
36344            // we don't want to overwrite a newer message just ignore.
36345            return this;
36346        }
36347        
36348        var text = o.useDefaults ? this.defaultText : '',
36349            iconCls = o.useDefaults ? (this.defaultIconCls ? this.defaultIconCls : '') : '';
36350            
36351        if(o.anim){
36352            this.statusEl.fadeOut({
36353                remove: false,
36354                useDisplay: true,
36355                scope: this,
36356                callback: function(){
36357                    this.setStatus({
36358	                    text: text, 
36359	                    iconCls: iconCls
36360	                });
36361                    this.statusEl.show();
36362                }
36363            });
36364        }else{
36365            // hide/show the el to avoid jumpy text or icon
36366            this.statusEl.hide();
36367	        this.setStatus({
36368	            text: text,
36369	            iconCls: iconCls
36370	        });
36371            this.statusEl.show();
36372        }
36373        return this;
36374    },
36375    
36376    
36377    setText : function(text){
36378        this.activeThreadId++;
36379        this.text = text || '';
36380        if(this.rendered){
36381            this.statusEl.update(this.text);
36382        }
36383        return this;
36384    },
36385    
36386    
36387    getText : function(){
36388        return this.text;
36389    },
36390
36391    
36392    setIcon : function(cls){
36393        this.activeThreadId++;
36394        cls = cls || '';
36395        
36396        if(this.rendered){
36397	        if(this.currIconCls){
36398	            this.statusEl.removeClass(this.currIconCls);
36399	            this.currIconCls = null;
36400	        }
36401	        if(cls.length > 0){
36402	            this.statusEl.addClass(cls);
36403	            this.currIconCls = cls;
36404	        }
36405        }else{
36406            this.currIconCls = cls;
36407        }
36408        return this;
36409    },
36410    
36411    
36412    showBusy : function(o){
36413        if(typeof o == 'string'){
36414            o = {text:o};
36415        }
36416        o = Ext.applyIf(o || {}, {
36417            text: this.busyText,
36418            iconCls: this.busyIconCls
36419        });
36420        return this.setStatus(o);
36421    }
36422});
36423Ext.reg('statusbar', Ext.StatusBar);
36424
36425
36426Ext.History = (function () {
36427    var iframe, hiddenField;
36428    var ready = false;
36429    var currentToken;
36430
36431    function getHash() {
36432        var href = top.location.href, i = href.indexOf("#");
36433        return i >= 0 ? href.substr(i + 1) : null;
36434    }
36435
36436    function doSave() {
36437        hiddenField.value = currentToken;
36438    }
36439
36440    function handleStateChange(token) {
36441        currentToken = token;
36442        Ext.History.fireEvent('change', token);
36443    }
36444
36445    function updateIFrame (token) {
36446        var html = ['<html><body><div id="state">',token,'</div></body></html>'].join('');
36447        try {
36448            var doc = iframe.contentWindow.document;
36449            doc.open();
36450            doc.write(html);
36451            doc.close();
36452            return true;
36453        } catch (e) {
36454            return false;
36455        }
36456    }
36457
36458    function checkIFrame() {
36459        if (!iframe.contentWindow || !iframe.contentWindow.document) {
36460            setTimeout(checkIFrame, 10);
36461            return;
36462        }
36463
36464        var doc = iframe.contentWindow.document;
36465        var elem = doc.getElementById("state");
36466        var token = elem ? elem.innerText : null;
36467
36468        var hash = getHash();
36469
36470        setInterval(function () {
36471
36472            doc = iframe.contentWindow.document;
36473            elem = doc.getElementById("state");
36474
36475            var newtoken = elem ? elem.innerText : null;
36476
36477            var newHash = getHash();
36478
36479            if (newtoken !== token) {
36480                token = newtoken;
36481                handleStateChange(token);
36482                top.location.hash = token;
36483                hash = token;
36484                doSave();
36485            } else if (newHash !== hash) {
36486                hash = newHash;
36487                updateIFrame(newHash);
36488            }
36489
36490        }, 50);
36491
36492        ready = true;
36493
36494        Ext.History.fireEvent('ready', Ext.History);
36495    }
36496
36497    function startUp() {
36498        currentToken = hiddenField.value ? hiddenField.value : getHash();
36499        
36500        if (Ext.isIE) {
36501            checkIFrame();
36502        } else {
36503            var hash = getHash();
36504            setInterval(function () {
36505                var newHash = getHash();
36506                if (newHash !== hash) {
36507                    hash = newHash;
36508                    handleStateChange(hash);
36509                    doSave();
36510                }
36511            }, 50);
36512            ready = true;
36513            Ext.History.fireEvent('ready', Ext.History);
36514        }
36515    }
36516
36517    return {
36518        
36519        fieldId: 'x-history-field',
36520        
36521        iframeId: 'x-history-frame',
36522        
36523        events:{},
36524
36525        
36526        init: function (onReady, scope) {
36527            if(ready) {
36528                Ext.callback(onReady, scope, [this]);
36529                return;
36530            }
36531            if(!Ext.isReady){
36532                Ext.onReady(function(){
36533                    Ext.History.init(onReady, scope);
36534                });
36535                return;
36536            }
36537            hiddenField = Ext.getDom(Ext.History.fieldId);
36538			if (Ext.isIE) {
36539                iframe = Ext.getDom(Ext.History.iframeId);
36540            }
36541            this.addEvents('ready', 'change');
36542            if(onReady){
36543                this.on('ready', onReady, scope, {single:true});
36544            }
36545            startUp();
36546        },
36547
36548        
36549        add: function (token, preventDup) {
36550            if(preventDup !== false){
36551                if(this.getToken() == token){
36552                    return true;
36553                }
36554            }
36555            if (Ext.isIE) {
36556                return updateIFrame(token);
36557            } else {
36558                top.location.hash = token;
36559                return true;
36560            }
36561        },
36562
36563        
36564        back: function(){
36565            history.go(-1);
36566        },
36567
36568        
36569        forward: function(){
36570            history.go(1);
36571        },
36572
36573        
36574        getToken: function() {
36575            return ready ? currentToken : getHash();
36576        }
36577    };
36578})();
36579Ext.apply(Ext.History, new Ext.util.Observable());
36580Ext.debug = {};
36581
36582(function(){
36583
36584var cp;
36585
36586function createConsole(){
36587
36588    var scriptPanel = new Ext.debug.ScriptsPanel();
36589    var logView = new Ext.debug.LogPanel();
36590    var tree = new Ext.debug.DomTree();
36591
36592    var tabs = new Ext.TabPanel({
36593        activeTab: 0,
36594        border: false,
36595        tabPosition: 'bottom',
36596        items: [{
36597            title: 'Debug Console',
36598            layout:'border',
36599            items: [logView, scriptPanel]
36600        },{
36601            title: 'DOM Inspector',
36602            layout:'border',
36603            items: [tree]
36604        }]
36605    });
36606
36607    cp = new Ext.Panel({
36608        id: 'x-debug-browser',
36609        title: 'Console',
36610        collapsible: true,
36611        animCollapse: false,
36612        style: 'position:absolute;left:0;bottom:0;',
36613        height:200,
36614        logView: logView,
36615        layout: 'fit',
36616        
36617        tools:[{
36618            id: 'close',
36619            handler: function(){
36620                cp.destroy();
36621                cp = null;
36622                Ext.EventManager.removeResizeListener(handleResize);
36623            }
36624        }],
36625
36626        items: tabs
36627    });
36628
36629    cp.render(document.body);
36630
36631    cp.resizer = new Ext.Resizable(cp.el, {
36632        minHeight:50,
36633        handles: "n",
36634        pinned: true,
36635        transparent:true,
36636        resizeElement : function(){
36637            var box = this.proxy.getBox();
36638            this.proxy.hide();
36639            cp.setHeight(box.height);
36640            return box;
36641        }
36642    });
36643
36644    function handleResize(){
36645        cp.setWidth(Ext.getBody().getViewSize().width);
36646    }
36647    Ext.EventManager.onWindowResize(handleResize);
36648
36649    handleResize();
36650}
36651
36652
36653Ext.apply(Ext, {
36654    log : function(){
36655        if(!cp){
36656            createConsole();
36657        }
36658        cp.logView.log.apply(cp.logView, arguments);
36659    },
36660
36661    logf : function(format, arg1, arg2, etc){
36662        Ext.log(String.format.apply(String, arguments));
36663    },
36664
36665    dump : function(o){
36666        if(typeof o == 'string' || typeof o == 'number' || typeof o == 'undefined' || Ext.isDate(o)){
36667            Ext.log(o);
36668        }else if(!o){
36669            Ext.log("null");
36670        }else if(typeof o != "object"){
36671            Ext.log('Unknown return type');
36672        }else if(Ext.isArray(o)){
36673            Ext.log('['+o.join(',')+']');
36674        }else{
36675            var b = ["{\n"];
36676            for(var key in o){
36677                var to = typeof o[key];
36678                if(to != "function" && to != "object"){
36679                    b.push(String.format("  {0}: {1},\n", key, o[key]));
36680                }
36681            }
36682            var s = b.join("");
36683            if(s.length > 3){
36684                s = s.substr(0, s.length-2);
36685            }
36686            Ext.log(s + "\n}");
36687        }
36688    },
36689
36690    _timers : {},
36691
36692    time : function(name){
36693        name = name || "def";
36694        Ext._timers[name] = new Date().getTime();
36695    },
36696
36697    timeEnd : function(name, printResults){
36698        var t = new Date().getTime();
36699        name = name || "def";
36700        var v = String.format("{0} ms", t-Ext._timers[name]);
36701        Ext._timers[name] = new Date().getTime();
36702        if(printResults !== false){
36703            Ext.log('Timer ' + (name == "def" ? v : name + ": " + v));
36704        }
36705        return v;
36706    }
36707});
36708
36709})();
36710
36711
36712Ext.debug.ScriptsPanel = Ext.extend(Ext.Panel, {
36713    id:'x-debug-scripts',
36714    region: 'east',
36715    minWidth: 200,
36716    split: true,
36717    width: 350,
36718    border: false,
36719    layout:'anchor',
36720    style:'border-width:0 0 0 1px;',
36721
36722    initComponent : function(){
36723
36724        this.scriptField = new Ext.form.TextArea({
36725            anchor: '100% -26',
36726            style:'border-width:0;'
36727        });
36728
36729        this.trapBox = new Ext.form.Checkbox({
36730            id: 'console-trap',
36731            boxLabel: 'Trap Errors',
36732            checked: true
36733        });
36734
36735        this.toolbar = new Ext.Toolbar([{
36736                text: 'Run',
36737                scope: this,
36738                handler: this.evalScript
36739            },{
36740                text: 'Clear',
36741                scope: this,
36742                handler: this.clear
36743            },
36744            '->',
36745            this.trapBox,
36746            ' ', ' '
36747        ]);
36748
36749        this.items = [this.toolbar, this.scriptField];
36750
36751        Ext.debug.ScriptsPanel.superclass.initComponent.call(this);
36752    },
36753
36754    evalScript : function(){
36755        var s = this.scriptField.getValue();
36756        if(this.trapBox.getValue()){
36757            try{
36758                var rt = eval(s);
36759                Ext.dump(rt === undefined? '(no return)' : rt);
36760            }catch(e){
36761                Ext.log(e.message || e.descript);
36762            }
36763        }else{
36764            var rt = eval(s);
36765            Ext.dump(rt === undefined? '(no return)' : rt);
36766        }
36767    },
36768
36769    clear : function(){
36770        this.scriptField.setValue('');
36771        this.scriptField.focus();
36772    }
36773
36774});
36775
36776Ext.debug.LogPanel = Ext.extend(Ext.Panel, {
36777    autoScroll: true,
36778    region: 'center',
36779    border: false,
36780    style:'border-width:0 1px 0 0',
36781
36782    log : function(){
36783        var markup = [  '<div style="padding:5px !important;border-bottom:1px solid #ccc;">',
36784                    Ext.util.Format.htmlEncode(Array.prototype.join.call(arguments, ', ')).replace(/\n/g, '<br />').replace(/\s/g, '&#160;'),
36785                    '</div>'].join('');
36786
36787        this.body.insertHtml('beforeend', markup);
36788        this.body.scrollTo('top', 100000);
36789    },
36790
36791    clear : function(){
36792        this.body.update('');
36793        this.body.dom.scrollTop = 0;
36794    }
36795});
36796
36797Ext.debug.DomTree = Ext.extend(Ext.tree.TreePanel, {
36798    enableDD:false ,
36799    lines:false,
36800    rootVisible:false,
36801    animate:false,
36802    hlColor:'ffff9c',
36803    autoScroll: true,
36804    region:'center',
36805    border:false,
36806
36807    initComponent : function(){
36808
36809
36810        Ext.debug.DomTree.superclass.initComponent.call(this);
36811        
36812        // tree related stuff
36813        var styles = false, hnode;
36814        var nonSpace = /^\s*$/;
36815        var html = Ext.util.Format.htmlEncode;
36816        var ellipsis = Ext.util.Format.ellipsis;
36817        var styleRe = /\s?([a-z\-]*)\:([^;]*)(?:[;\s\n\r]*)/gi;
36818
36819        function findNode(n){
36820            if(!n || n.nodeType != 1 || n == document.body || n == document){
36821                return false;
36822            }
36823            var pn = [n], p = n;
36824            while((p = p.parentNode) && p.nodeType == 1 && p.tagName.toUpperCase() != 'HTML'){
36825                pn.unshift(p);
36826            }
36827            var cn = hnode;
36828            for(var i = 0, len = pn.length; i < len; i++){
36829                cn.expand();
36830                cn = cn.findChild('htmlNode', pn[i]);
36831                if(!cn){ // in this dialog?
36832                    return false;
36833                }
36834            }
36835            cn.select();
36836            var a = cn.ui.anchor;
36837            treeEl.dom.scrollTop = Math.max(0 ,a.offsetTop-10);
36838            //treeEl.dom.scrollLeft = Math.max(0 ,a.offsetLeft-10); no likey
36839            cn.highlight();
36840            return true;
36841        }
36842
36843        function nodeTitle(n){
36844            var s = n.tagName;
36845            if(n.id){
36846                s += '#'+n.id;
36847            }else if(n.className){
36848                s += '.'+n.className;
36849            }
36850            return s;
36851        }
36852
36853        function onNodeSelect(t, n, last){
36854            return;
36855            if(last && last.unframe){
36856                last.unframe();
36857            }
36858            var props = {};
36859            if(n && n.htmlNode){
36860                if(frameEl.pressed){
36861                    n.frame();
36862                }
36863                if(inspecting){
36864                    return;
36865                }
36866                addStyle.enable();
36867                reload.setDisabled(n.leaf);
36868                var dom = n.htmlNode;
36869                stylePanel.setTitle(nodeTitle(dom));
36870                if(styles && !showAll.pressed){
36871                    var s = dom.style ? dom.style.cssText : '';
36872                    if(s){
36873                        var m;
36874                        while ((m = styleRe.exec(s)) != null){
36875                            props[m[1].toLowerCase()] = m[2];
36876                        }
36877                    }
36878                }else if(styles){
36879                    var cl = Ext.debug.cssList;
36880                    var s = dom.style, fly = Ext.fly(dom);
36881                    if(s){
36882                        for(var i = 0, len = cl.length; i<len; i++){
36883                            var st = cl[i];
36884                            var v = s[st] || fly.getStyle(st);
36885                            if(v != undefined && v !== null && v !== ''){
36886                                props[st] = v;
36887                            }
36888                        }
36889                    }
36890                }else{
36891                    for(var a in dom){
36892                        var v = dom[a];
36893                        if((isNaN(a+10)) && v != undefined && v !== null && v !== '' && !(Ext.isGecko && a[0] == a[0].toUpperCase())){
36894                            props[a] = v;
36895                        }
36896                    }
36897                }
36898            }else{
36899                if(inspecting){
36900                    return;
36901                }
36902                addStyle.disable();
36903                reload.disabled();
36904            }
36905            stylesGrid.setSource(props);
36906            stylesGrid.treeNode = n;
36907            stylesGrid.view.fitColumns();
36908        }
36909
36910        this.loader = new Ext.tree.TreeLoader();
36911        this.loader.load = function(n, cb){
36912            var isBody = n.htmlNode == document.body;
36913            var cn = n.htmlNode.childNodes;
36914            for(var i = 0, c; c = cn[i]; i++){
36915                if(isBody && c.id == 'x-debug-browser'){
36916                    continue;
36917                }
36918                if(c.nodeType == 1){
36919                    n.appendChild(new Ext.debug.HtmlNode(c));
36920                }else if(c.nodeType == 3 && !nonSpace.test(c.nodeValue)){
36921                    n.appendChild(new Ext.tree.TreeNode({
36922                        text:'<em>' + ellipsis(html(String(c.nodeValue)), 35) + '</em>',
36923                        cls: 'x-tree-noicon'
36924                    }));
36925                }
36926            }
36927            cb();
36928        };
36929
36930        //tree.getSelectionModel().on('selectionchange', onNodeSelect, null, {buffer:250});
36931
36932        this.root = this.setRootNode(new Ext.tree.TreeNode('Ext'));
36933
36934        hnode = this.root.appendChild(new Ext.debug.HtmlNode(
36935                document.getElementsByTagName('html')[0]
36936        ));
36937
36938    }
36939});
36940
36941
36942// highly unusual class declaration
36943Ext.debug.HtmlNode = function(){
36944    var html = Ext.util.Format.htmlEncode;
36945    var ellipsis = Ext.util.Format.ellipsis;
36946    var nonSpace = /^\s*$/;
36947
36948    var attrs = [
36949        {n: 'id', v: 'id'},
36950        {n: 'className', v: 'class'},
36951        {n: 'name', v: 'name'},
36952        {n: 'type', v: 'type'},
36953        {n: 'src', v: 'src'},
36954        {n: 'href', v: 'href'}
36955    ];
36956
36957    function hasChild(n){
36958        for(var i = 0, c; c = n.childNodes[i]; i++){
36959            if(c.nodeType == 1){
36960                return true;
36961            }
36962        }
36963        return false;
36964    }
36965
36966    function renderNode(n, leaf){
36967        var tag = n.tagName.toLowerCase();
36968        var s = '&lt;' + tag;
36969        for(var i = 0, len = attrs.length; i < len; i++){
36970            var a = attrs[i];
36971            var v = n[a.n];
36972            if(v && !nonSpace.test(v)){
36973                s += ' ' + a.v + '=&quot;<i>' + html(v) +'</i>&quot;';
36974            }
36975        }
36976        var style = n.style ? n.style.cssText : '';
36977        if(style){
36978            s += ' style=&quot;<i>' + html(style.toLowerCase()) +'</i>&quot;';
36979        }
36980        if(leaf && n.childNodes.length > 0){
36981            s+='&gt;<em>' + ellipsis(html(String(n.innerHTML)), 35) + '</em>&lt;/'+tag+'&gt;';
36982        }else if(leaf){
36983            s += ' /&gt;';
36984        }else{
36985            s += '&gt;';
36986        }
36987        return s;
36988    }
36989
36990    var HtmlNode = function(n){
36991        var leaf = !hasChild(n);
36992        this.htmlNode = n;
36993        this.tagName = n.tagName.toLowerCase();
36994        var attr = {
36995            text : renderNode(n, leaf),
36996            leaf : leaf,
36997            cls: 'x-tree-noicon'
36998        };
36999        HtmlNode.superclass.constructor.call(this, attr);
37000        this.attributes.htmlNode = n; // for searching
37001        if(!leaf){
37002            this.on('expand', this.onExpand,  this);
37003            this.on('collapse', this.onCollapse,  this);
37004        }
37005    };
37006
37007
37008    Ext.extend(HtmlNode, Ext.tree.AsyncTreeNode, {
37009        cls: 'x-tree-noicon',
37010        preventHScroll: true,
37011        refresh : function(highlight){
37012            var leaf = !hasChild(this.htmlNode);
37013            this.setText(renderNode(this.htmlNode, leaf));
37014            if(highlight){
37015                Ext.fly(this.ui.textNode).highlight();
37016            }
37017        },
37018
37019        onExpand : function(){
37020            if(!this.closeNode && this.parentNode){
37021                this.closeNode = this.parentNode.insertBefore(new Ext.tree.TreeNode({
37022                    text:'&lt;/' + this.tagName + '&gt;',
37023                    cls: 'x-tree-noicon'
37024                }), this.nextSibling);
37025            }else if(this.closeNode){
37026                this.closeNode.ui.show();
37027            }
37028        },
37029
37030        onCollapse : function(){
37031            if(this.closeNode){
37032                this.closeNode.ui.hide();
37033            }
37034        },
37035
37036        render : function(bulkRender){
37037            HtmlNode.superclass.render.call(this, bulkRender);
37038        },
37039
37040        highlightNode : function(){
37041            //Ext.fly(this.htmlNode).highlight();
37042        },
37043
37044        highlight : function(){
37045            //Ext.fly(this.ui.textNode).highlight();
37046        },
37047
37048        frame : function(){
37049            this.htmlNode.style.border = '1px solid #0000ff';
37050            //this.highlightNode();
37051        },
37052
37053        unframe : function(){
37054            //Ext.fly(this.htmlNode).removeClass('x-debug-frame');
37055            this.htmlNode.style.border = '';
37056        }
37057    });
37058
37059    return HtmlNode;
37060}();
37061
37062
37063

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.