The source code

    /*
     * Ext JS Library 2.0.2
     * Copyright(c) 2006-2008, Ext JS, LLC.
     * licensing@extjs.com
     *
     * http://extjs.com/license
     */

    Ext.DomHelper = function(){
        var tempTableEl = null;
        var emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;
        var tableRe = /^table|tbody|tr|td$/i;

        var createHtml = function(o){
            if(typeof o == 'string'){
                return o;
            }
            var b = "";
            if (Ext.isArray(o)) {
                for (var i = 0, l = o.length; i < l; i++) {
                    b += createHtml(o[i]);
                }
                return b;
            }
            if(!o.tag){
                o.tag = "div";
            }
            b += "<" + o.tag;
            for(var attr in o){
                if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || typeof o[attr] == "function") continue;
                if(attr == "style"){
                    var s = o["style"];
                    if(typeof s == "function"){
                        s = s.call();
                    }
                    if(typeof s == "string"){
                        b += ' style="' + s + '"';
                    }else if(typeof s == "object"){
                        b += ' style="';
                        for(var key in s){
                            if(typeof s[key] != "function"){
                                b += key + ":" + s[key] + ";";
                            }
                        }
                        b += '"';
                    }
                }else{
                    if(attr == "cls"){
                        b += ' class="' + o["cls"] + '"';
                    }else if(attr == "htmlFor"){
                        b += ' for="' + o["htmlFor"] + '"';
                    }else{
                        b += " " + attr + '="' + o[attr] + '"';
                    }
                }
            }
            if(emptyTags.test(o.tag)){
                b += "/>";
            }else{
                b += ">";
                var cn = o.children || o.cn;
                if(cn){
                    b += createHtml(cn);
                } else if(o.html){
                    b += o.html;
                }
                b += "";
            }
            return b;
        };

        var createDom = function(o, parentNode){
            var el;
            if (Ext.isArray(o)) {
                el = document.createDocumentFragment();
                for(var i = 0, l = o.length; i < l; i++) {
                    createDom(o[i], el);
                }
            } else if (typeof o == "string)") {
                el = document.createTextNode(o);
            } else {
                el = document.createElement(o.tag||'div');
                var useSet = !!el.setAttribute;
                for(var attr in o){
                    if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || attr == "style" || typeof o[attr] == "function") continue;
                    if(attr=="cls"){
                        el.className = o["cls"];
                    }else{
                        if(useSet) el.setAttribute(attr, o[attr]);
                        else el[attr] = o[attr];
                    }
                }
                Ext.DomHelper.applyStyles(el, o.style);
                var cn = o.children || o.cn;
                if(cn){
                    createDom(cn, el);
                } else if(o.html){
                    el.innerHTML = o.html;
                }
            }
            if(parentNode){
               parentNode.appendChild(el);
            }
            return el;
        };

        var ieTable = function(depth, s, h, e){
            tempTableEl.innerHTML = [s, h, e].join('');
            var i = -1, el = tempTableEl;
            while(++i < depth){
                el = el.firstChild;
            }
            return el;
        };

        var ts = '',
            te = '',
            tbs = ts+'',
            tbe = ''+te,
            trs = tbs + '',
            tre = ''+tbe;

        var insertIntoTable = function(tag, where, el, html){
            if(!tempTableEl){
                tempTableEl = document.createElement('div');
            }
            var node;
            var before = null;
            if(tag == 'td'){
                if(where == 'afterbegin' || where == 'beforeend'){
                    return;
                }
                if(where == 'beforebegin'){
                    before = el;
                    el = el.parentNode;
                } else{
                    before = el.nextSibling;
                    el = el.parentNode;
                }
                node = ieTable(4, trs, html, tre);
            }
            else if(tag == 'tr'){
                if(where == 'beforebegin'){
                    before = el;
                    el = el.parentNode;
                    node = ieTable(3, tbs, html, tbe);
                } else if(where == 'afterend'){
                    before = el.nextSibling;
                    el = el.parentNode;
                    node = ieTable(3, tbs, html, tbe);
                } else{
                    if(where == 'afterbegin'){
                        before = el.firstChild;
                    }
                    node = ieTable(4, trs, html, tre);
                }
            } else if(tag == 'tbody'){
                if(where == 'beforebegin'){
                    before = el;
                    el = el.parentNode;
                    node = ieTable(2, ts, html, te);
                } else if(where == 'afterend'){
                    before = el.nextSibling;
                    el = el.parentNode;
                    node = ieTable(2, ts, html, te);
                } else{
                    if(where == 'afterbegin'){
                        before = el.firstChild;
                    }
                    node = ieTable(3, tbs, html, tbe);
                }
            } else{
                if(where == 'beforebegin' || where == 'afterend'){
                    return;
                }
                if(where == 'afterbegin'){
                    before = el.firstChild;
                }
                node = ieTable(2, ts, html, te);
            }
            el.insertBefore(node, before);
            return node;
        };

        return {

        useDom : false,

        markup : function(o){
            return createHtml(o);
        },

        applyStyles : function(el, styles){
            if(styles){
               el = Ext.fly(el);
               if(typeof styles == "string"){
                   var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
                   var matches;
                   while ((matches = re.exec(styles)) != null){
                       el.setStyle(matches[1], matches[2]);
                   }
               }else if (typeof styles == "object"){
                   for (var style in styles){
                      el.setStyle(style, styles[style]);
                   }
               }else if (typeof styles == "function"){
                    Ext.DomHelper.applyStyles(el, styles.call());
               }
            }
        },

        insertHtml : function(where, el, html){
            where = where.toLowerCase();
            if(el.insertAdjacentHTML){
                if(tableRe.test(el.tagName)){
                    var rs;
                    if(rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)){
                        return rs;
                    }
                }
                switch(where){
                    case "beforebegin":
                        el.insertAdjacentHTML('BeforeBegin', html);
                        return el.previousSibling;
                    case "afterbegin":
                        el.insertAdjacentHTML('AfterBegin', html);
                        return el.firstChild;
                    case "beforeend":
                        el.insertAdjacentHTML('BeforeEnd', html);
                        return el.lastChild;
                    case "afterend":
                        el.insertAdjacentHTML('AfterEnd', html);
                        return el.nextSibling;
                }
                throw 'Illegal insertion point -> "' + where + '"';
            }
            var range = el.ownerDocument.createRange();
            var frag;
            switch(where){
                 case "beforebegin":
                    range.setStartBefore(el);
                    frag = range.createContextualFragment(html);
                    el.parentNode.insertBefore(frag, el);
                    return el.previousSibling;
                 case "afterbegin":
                    if(el.firstChild){
                        range.setStartBefore(el.firstChild);
                        frag = range.createContextualFragment(html);
                        el.insertBefore(frag, el.firstChild);
                        return el.firstChild;
                    }else{
                        el.innerHTML = html;
                        return el.firstChild;
                    }
                case "beforeend":
                    if(el.lastChild){
                        range.setStartAfter(el.lastChild);
                        frag = range.createContextualFragment(html);
                        el.appendChild(frag);
                        return el.lastChild;
                    }else{
                        el.innerHTML = html;
                        return el.lastChild;
                    }
                case "afterend":
                    range.setStartAfter(el);
                    frag = range.createContextualFragment(html);
                    el.parentNode.insertBefore(frag, el.nextSibling);
                    return el.nextSibling;
                }
                throw 'Illegal insertion point -> "' + where + '"';
        },

        insertBefore : function(el, o, returnElement){
            return this.doInsert(el, o, returnElement, "beforeBegin");
        },

        insertAfter : function(el, o, returnElement){
            return this.doInsert(el, o, returnElement, "afterEnd", "nextSibling");
        },

        insertFirst : function(el, o, returnElement){
            return this.doInsert(el, o, returnElement, "afterBegin", "firstChild");
        },

        doInsert : function(el, o, returnElement, pos, sibling){
            el = Ext.getDom(el);
            var newNode;
            if(this.useDom){
                newNode = createDom(o, null);
                (sibling === "firstChild" ? el : el.parentNode).insertBefore(newNode, sibling ? el[sibling] : el);
            }else{
                var html = createHtml(o);
                newNode = this.insertHtml(pos, el, html);
            }
            return returnElement ? Ext.get(newNode, true) : newNode;
        },

        append : function(el, o, returnElement){
            el = Ext.getDom(el);
            var newNode;
            if(this.useDom){
                newNode = createDom(o, null);
                el.appendChild(newNode);
            }else{
                var html = createHtml(o);
                newNode = this.insertHtml("beforeEnd", el, html);
            }
            return returnElement ? Ext.get(newNode, true) : newNode;
        },

        overwrite : function(el, o, returnElement){
            el = Ext.getDom(el);
            el.innerHTML = createHtml(o);
            return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;
        },

        createTemplate : function(o){
            var html = createHtml(o);
            return new Ext.Template(html);
        }
        };
    }();

    Ext.Template = function(html){
        var a = arguments;
        if(Ext.isArray(html)){
            html = html.join("");
        }else if(a.length > 1){
            var buf = [];
            for(var i = 0, len = a.length; i < len; i++){
                if(typeof a[i] == 'object'){
                    Ext.apply(this, a[i]);
                }else{
                    buf[buf.length] = a[i];
                }
            }
            html = buf.join('');
        }

        this.html = html;
        if(this.compiled){
            this.compile();
        }
    };
    Ext.Template.prototype = {

        applyTemplate : function(values){
            if(this.compiled){
                return this.compiled(values);
            }
            var useF = this.disableFormats !== true;
            var fm = Ext.util.Format, tpl = this;
            var fn = function(m, name, format, args){
                if(format && useF){
                    if(format.substr(0, 5) == "this."){
                        return tpl.call(format.substr(5), values[name], values);
                    }else{
                        if(args){

                            var re = /^\s*['"](.*)["']\s*$/;
                            args = args.split(',');
                            for(var i = 0, len = args.length; i < len; i++){
                                args[i] = args[i].replace(re, "$1");
                            }
                            args = [values[name]].concat(args);
                        }else{
                            args = [values[name]];
                        }
                        return fm[format].apply(fm, args);
                    }
                }else{
                    return values[name] !== undefined ? values[name] : "";
                }
            };
            return this.html.replace(this.re, fn);
        },

        set : function(html, compile){
            this.html = html;
            this.compiled = null;
            if(compile){
                this.compile();
            }
            return this;
        },

        disableFormats : false,

        re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,

        compile : function(){
            var fm = Ext.util.Format;
            var useF = this.disableFormats !== true;
            var sep = Ext.isGecko ? "+" : ",";
            var fn = function(m, name, format, args){
                if(format && useF){
                    args = args ? ',' + args : "";
                    if(format.substr(0, 5) != "this."){
                        format = "fm." + format + '(';
                    }else{
                        format = 'this.call("'+ format.substr(5) + '", ';
                        args = ", values";
                    }
                }else{
                    args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
                }
                return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
            };
            var body;

            if(Ext.isGecko){
                body = "this.compiled = function(values){ return '" +
                       this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
                        "';};";
            }else{
                body = ["this.compiled = function(values){ return ['"];
                body.push(this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn));
                body.push("'].join('');};");
                body = body.join('');
            }
            eval(body);
            return this;
        },

        call : function(fnName, value, allValues){
            return this[fnName](value, allValues);
        },

        insertFirst: function(el, values, returnElement){
            return this.doInsert('afterBegin', el, values, returnElement);
        },

        insertBefore: function(el, values, returnElement){
            return this.doInsert('beforeBegin', el, values, returnElement);
        },

        insertAfter : function(el, values, returnElement){
            return this.doInsert('afterEnd', el, values, returnElement);
        },

        append : function(el, values, returnElement){
            return this.doInsert('beforeEnd', el, values, returnElement);
        },

        doInsert : function(where, el, values, returnEl){
            el = Ext.getDom(el);
            var newNode = Ext.DomHelper.insertHtml(where, el, this.applyTemplate(values));
            return returnEl ? Ext.get(newNode, true) : newNode;
        },

        overwrite : function(el, values, returnElement){
            el = Ext.getDom(el);
            el.innerHTML = this.applyTemplate(values);
            return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;
        }
    };

    Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate;

    Ext.DomHelper.Template = Ext.Template;

    Ext.Template.from = function(el, config){
        el = Ext.getDom(el);
        return new Ext.Template(el.value || el.innerHTML, config || '');
    };

    Ext.DomQuery = function(){
        var cache = {}, simpleCache = {}, valueCache = {};
        var nonSpace = /\S/;
        var trimRe = /^\s+|\s+$/g;
        var tplRe = /\{(\d+)\}/g;
        var modeRe = /^(\s?[\/>+~]\s?|\s|$)/;
        var tagTokenRe = /^(#)?([\w-\*]+)/;
        var nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/;

        function child(p, index){
            var i = 0;
            var n = p.firstChild;
            while(n){
                if(n.nodeType == 1){
                   if(++i == index){
                       return n;
                   }
                }
                n = n.nextSibling;
            }
            return null;
        };

        function next(n){
            while((n = n.nextSibling) && n.nodeType != 1);
            return n;
        };

        function prev(n){
            while((n = n.previousSibling) && n.nodeType != 1);
            return n;
        };

        function children(d){
            var n = d.firstChild, ni = -1;
     	    while(n){
     	        var nx = n.nextSibling;
     	        if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
     	            d.removeChild(n);
     	        }else{
     	            n.nodeIndex = ++ni;
     	        }
     	        n = nx;
     	    }
     	    return this;
     	};

        function byClassName(c, a, v){
            if(!v){
                return c;
            }
            var r = [], ri = -1, cn;
            for(var i = 0, ci; ci = c[i]; i++){
                if((' '+ci.className+' ').indexOf(v) != -1){
                    r[++ri] = ci;
                }
            }
            return r;
        };

        function attrValue(n, attr){
            if(!n.tagName && typeof n.length != "undefined"){
                n = n[0];
            }
            if(!n){
                return null;
            }
            if(attr == "for"){
                return n.htmlFor;
            }
            if(attr == "class" || attr == "className"){
                return n.className;
            }
            return n.getAttribute(attr) || n[attr];

        };

        function getNodes(ns, mode, tagName){
            var result = [], ri = -1, cs;
            if(!ns){
                return result;
            }
            tagName = tagName || "*";
            if(typeof ns.getElementsByTagName != "undefined"){
                ns = [ns];
            }
            if(!mode){
                for(var i = 0, ni; ni = ns[i]; i++){
                    cs = ni.getElementsByTagName(tagName);
                    for(var j = 0, ci; ci = cs[j]; j++){
                        result[++ri] = ci;
                    }
                }
            }else if(mode == "/" || mode == ">"){
                var utag = tagName.toUpperCase();
                for(var i = 0, ni, cn; ni = ns[i]; i++){
                    cn = ni.children || ni.childNodes;
                    for(var j = 0, cj; cj = cn[j]; j++){
                        if(cj.nodeName == utag || cj.nodeName == tagName  || tagName == '*'){
                            result[++ri] = cj;
                        }
                    }
                }
            }else if(mode == "+"){
                var utag = tagName.toUpperCase();
                for(var i = 0, n; n = ns[i]; i++){
                    while((n = n.nextSibling) && n.nodeType != 1);
                    if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
                        result[++ri] = n;
                    }
                }
            }else if(mode == "~"){
                for(var i = 0, n; n = ns[i]; i++){
                    while((n = n.nextSibling) && (n.nodeType != 1 || (tagName == '*' || n.tagName.toLowerCase()!=tagName)));
                    if(n){
                        result[++ri] = n;
                    }
                }
            }
            return result;
        };

        function concat(a, b){
            if(b.slice){
                return a.concat(b);
            }
            for(var i = 0, l = b.length; i < l; i++){
                a[a.length] = b[i];
            }
            return a;
        }

        function byTag(cs, tagName){
            if(cs.tagName || cs == document){
                cs = [cs];
            }
            if(!tagName){
                return cs;
            }
            var r = [], ri = -1;
            tagName = tagName.toLowerCase();
            for(var i = 0, ci; ci = cs[i]; i++){
                if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
                    r[++ri] = ci;
                }
            }
            return r;
        };

        function byId(cs, attr, id){
            if(cs.tagName || cs == document){
                cs = [cs];
            }
            if(!id){
                return cs;
            }
            var r = [], ri = -1;
            for(var i = 0,ci; ci = cs[i]; i++){
                if(ci && ci.id == id){
                    r[++ri] = ci;
                    return r;
                }
            }
            return r;
        };

        function byAttribute(cs, attr, value, op, custom){
            var r = [], ri = -1, st = custom=="{";
            var f = Ext.DomQuery.operators[op];
            for(var i = 0, ci; ci = cs[i]; i++){
                var a;
                if(st){
                    a = Ext.DomQuery.getStyle(ci, attr);
                }
                else if(attr == "class" || attr == "className"){
                    a = ci.className;
                }else if(attr == "for"){
                    a = ci.htmlFor;
                }else if(attr == "href"){
                    a = ci.getAttribute("href", 2);
                }else{
                    a = ci.getAttribute(attr);
                }
                if((f && f(a, value)) || (!f && a)){
                    r[++ri] = ci;
                }
            }
            return r;
        };

        function byPseudo(cs, name, value){
            return Ext.DomQuery.pseudos[name](cs, value);
        };

        var isIE = window.ActiveXObject ? true : false;

        eval("var batch = 30803;");

        var key = 30803;

        function nodupIEXml(cs){
            var d = ++key;
            cs[0].setAttribute("_nodup", d);
            var r = [cs[0]];
            for(var i = 1, len = cs.length; i < len; i++){
                var c = cs[i];
                if(!c.getAttribute("_nodup") != d){
                    c.setAttribute("_nodup", d);
                    r[r.length] = c;
                }
            }
            for(var i = 0, len = cs.length; i < len; i++){
                cs[i].removeAttribute("_nodup");
            }
            return r;
        }

        function nodup(cs){
            if(!cs){
                return [];
            }
            var len = cs.length, c, i, r = cs, cj, ri = -1;
            if(!len || typeof cs.nodeType != "undefined" || len == 1){
                return cs;
            }
            if(isIE && typeof cs[0].selectSingleNode != "undefined"){
                return nodupIEXml(cs);
            }
            var d = ++key;
            cs[0]._nodup = d;
            for(i = 1; c = cs[i]; i++){
                if(c._nodup != d){
                    c._nodup = d;
                }else{
                    r = [];
                    for(var j = 0; j < i; j++){
                        r[++ri] = cs[j];
                    }
                    for(j = i+1; cj = cs[j]; j++){
                        if(cj._nodup != d){
                            cj._nodup = d;
                            r[++ri] = cj;
                        }
                    }
                    return r;
                }
            }
            return r;
        }

        function quickDiffIEXml(c1, c2){
            var d = ++key;
            for(var i = 0, len = c1.length; i < len; i++){
                c1[i].setAttribute("_qdiff", d);
            }
            var r = [];
            for(var i = 0, len = c2.length; i < len; i++){
                if(c2[i].getAttribute("_qdiff") != d){
                    r[r.length] = c2[i];
                }
            }
            for(var i = 0, len = c1.length; i < len; i++){
               c1[i].removeAttribute("_qdiff");
            }
            return r;
        }

        function quickDiff(c1, c2){
            var len1 = c1.length;
            if(!len1){
                return c2;
            }
            if(isIE && c1[0].selectSingleNode){
                return quickDiffIEXml(c1, c2);
            }
            var d = ++key;
            for(var i = 0; i < len1; i++){
                c1[i]._qdiff = d;
            }
            var r = [];
            for(var i = 0, len = c2.length; i < len; i++){
                if(c2[i]._qdiff != d){
                    r[r.length] = c2[i];
                }
            }
            return r;
        }

        function quickId(ns, mode, root, id){
            if(ns == root){
               var d = root.ownerDocument || root;
               return d.getElementById(id);
            }
            ns = getNodes(ns, mode, "*");
            return byId(ns, null, id);
        }

        return {
            getStyle : function(el, name){
                return Ext.fly(el).getStyle(name);
            },

            compile : function(path, type){
                type = type || "select";

                var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"];
                var q = path, mode, lq;
                var tk = Ext.DomQuery.matchers;
                var tklen = tk.length;
                var mm;

                var lmode = q.match(modeRe);
                if(lmode && lmode[1]){
                    fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
                    q = q.replace(lmode[1], "");
                }

                while(path.substr(0, 1)=="/"){
                    path = path.substr(1);
                }

                while(q && lq != q){
                    lq = q;
                    var tm = q.match(tagTokenRe);
                    if(type == "select"){
                        if(tm){
                            if(tm[1] == "#"){
                                fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
                            }else{
                                fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
                            }
                            q = q.replace(tm[0], "");
                        }else if(q.substr(0, 1) != '@'){
                            fn[fn.length] = 'n = getNodes(n, mode, "*");';
                        }
                    }else{
                        if(tm){
                            if(tm[1] == "#"){
                                fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
                            }else{
                                fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
                            }
                            q = q.replace(tm[0], "");
                        }
                    }
                    while(!(mm = q.match(modeRe))){
                        var matched = false;
                        for(var j = 0; j < tklen; j++){
                            var t = tk[j];
                            var m = q.match(t.re);
                            if(m){
                                fn[fn.length] = t.select.replace(tplRe, function(x, i){
                                                        return m[i];
                                                    });
                                q = q.replace(m[0], "");
                                matched = true;
                                break;
                            }
                        }

                        if(!matched){
                            throw 'Error parsing selector, parsing failed at "' + q + '"';
                        }
                    }
                    if(mm[1]){
                        fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';
                        q = q.replace(mm[1], "");
                    }
                }
                fn[fn.length] = "return nodup(n);\n}";
                eval(fn.join(""));
                return f;
            },

            select : function(path, root, type){
                if(!root || root == document){
                    root = document;
                }
                if(typeof root == "string"){
                    root = document.getElementById(root);
                }
                var paths = path.split(",");
                var results = [];
                for(var i = 0, len = paths.length; i < len; i++){
                    var p = paths[i].replace(trimRe, "");
                    if(!cache[p]){
                        cache[p] = Ext.DomQuery.compile(p);
                        if(!cache[p]){
                            throw p + " is not a valid selector";
                        }
                    }
                    var result = cache[p](root);
                    if(result && result != document){
                        results = results.concat(result);
                    }
                }
                if(paths.length > 1){
                    return nodup(results);
                }
                return results;
            },

            selectNode : function(path, root){
                return Ext.DomQuery.select(path, root)[0];
            },

            selectValue : function(path, root, defaultValue){
                path = path.replace(trimRe, "");
                if(!valueCache[path]){
                    valueCache[path] = Ext.DomQuery.compile(path, "select");
                }
                var n = valueCache[path](root);
                n = n[0] ? n[0] : n;
                var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
                return ((v === null||v === undefined||v==='') ? defaultValue : v);
            },

            selectNumber : function(path, root, defaultValue){
                var v = Ext.DomQuery.selectValue(path, root, defaultValue || 0);
                return parseFloat(v);
            },

            is : function(el, ss){
                if(typeof el == "string"){
                    el = document.getElementById(el);
                }
                var isArray = Ext.isArray(el);
                var result = Ext.DomQuery.filter(isArray ? el : [el], ss);
                return isArray ? (result.length == el.length) : (result.length > 0);
            },

            filter : function(els, ss, nonMatches){
                ss = ss.replace(trimRe, "");
                if(!simpleCache[ss]){
                    simpleCache[ss] = Ext.DomQuery.compile(ss, "simple");
                }
                var result = simpleCache[ss](els);
                return nonMatches ? quickDiff(result, els) : result;
            },

            matchers : [{
                    re: /^\.([\w-]+)/,
                    select: 'n = byClassName(n, null, " {1} ");'
                }, {
                    re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
                    select: 'n = byPseudo(n, "{1}", "{2}");'
                },{
                    re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
                    select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
                }, {
                    re: /^#([\w-]+)/,
                    select: 'n = byId(n, null, "{1}");'
                },{
                    re: /^@([\w-]+)/,
                    select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
                }
            ],

            operators : {
                "=" : function(a, v){
                    return a == v;
                },
                "!=" : function(a, v){
                    return a != v;
                },
                "^=" : function(a, v){
                    return a && a.substr(0, v.length) == v;
                },
                "$=" : function(a, v){
                    return a && a.substr(a.length-v.length) == v;
                },
                "*=" : function(a, v){
                    return a && a.indexOf(v) !== -1;
                },
                "%=" : function(a, v){
                    return (a % v) == 0;
                },
                "|=" : function(a, v){
                    return a && (a == v || a.substr(0, v.length+1) == v+'-');
                },
                "~=" : function(a, v){
                    return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
                }
            },

            pseudos : {
                "first-child" : function(c){
                    var r = [], ri = -1, n;
                    for(var i = 0, ci; ci = n = c[i]; i++){
                        while((n = n.previousSibling) && n.nodeType != 1);
                        if(!n){
                            r[++ri] = ci;
                        }
                    }
                    return r;
                },

                "last-child" : function(c){
                    var r = [], ri = -1, n;
                    for(var i = 0, ci; ci = n = c[i]; i++){
                        while((n = n.nextSibling) && n.nodeType != 1);
                        if(!n){
                            r[++ri] = ci;
                        }
                    }
                    return r;
                },

                "nth-child" : function(c, a) {
                    var r = [], ri = -1;
                    var m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a);
                    var f = (m[1] || 1) - 0, l = m[2] - 0;
                    for(var i = 0, n; n = c[i]; i++){
                        var pn = n.parentNode;
                        if (batch != pn._batch) {
                            var j = 0;
                            for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
                                if(cn.nodeType == 1){
                                   cn.nodeIndex = ++j;
                                }
                            }
                            pn._batch = batch;
                        }
                        if (f == 1) {
                            if (l == 0 || n.nodeIndex == l){
                                r[++ri] = n;
                            }
                        } else if ((n.nodeIndex + l) % f == 0){
                            r[++ri] = n;
                        }
                    }

                    return r;
                },

                "only-child" : function(c){
                    var r = [], ri = -1;;
                    for(var i = 0, ci; ci = c[i]; i++){
                        if(!prev(ci) && !next(ci)){
                            r[++ri] = ci;
                        }
                    }
                    return r;
                },

                "empty" : function(c){
                    var r = [], ri = -1;
                    for(var i = 0, ci; ci = c[i]; i++){
                        var cns = ci.childNodes, j = 0, cn, empty = true;
                        while(cn = cns[j]){
                            ++j;
                            if(cn.nodeType == 1 || cn.nodeType == 3){
                                empty = false;
                                break;
                            }
                        }
                        if(empty){
                            r[++ri] = ci;
                        }
                    }
                    return r;
                },

                "contains" : function(c, v){
                    var r = [], ri = -1;
                    for(var i = 0, ci; ci = c[i]; i++){
                        if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
                            r[++ri] = ci;
                        }
                    }
                    return r;
                },

                "nodeValue" : function(c, v){
                    var r = [], ri = -1;
                    for(var i = 0, ci; ci = c[i]; i++){
                        if(ci.firstChild && ci.firstChild.nodeValue == v){
                            r[++ri] = ci;
                        }
                    }
                    return r;
                },

                "checked" : function(c){
                    var r = [], ri = -1;
                    for(var i = 0, ci; ci = c[i]; i++){
                        if(ci.checked == true){
                            r[++ri] = ci;
                        }
                    }
                    return r;
                },

                "not" : function(c, ss){
                    return Ext.DomQuery.filter(c, ss, true);
                },

                "any" : function(c, selectors){
                    var ss = selectors.split('|');
                    var r = [], ri = -1, s;
                    for(var i = 0, ci; ci = c[i]; i++){
                        for(var j = 0; s = ss[j]; j++){
                            if(Ext.DomQuery.is(ci, s)){
                                r[++ri] = ci;
                                break;
                            }
                        }
                    }
                    return r;
                },

                "odd" : function(c){
                    return this["nth-child"](c, "odd");
                },

                "even" : function(c){
                    return this["nth-child"](c, "even");
                },

                "nth" : function(c, a){
                    return c[a-1] || [];
                },

                "first" : function(c){
                    return c[0] || [];
                },

                "last" : function(c){
                    return c[c.length-1] || [];
                },

                "has" : function(c, ss){
                    var s = Ext.DomQuery.select;
                    var r = [], ri = -1;
                    for(var i = 0, ci; ci = c[i]; i++){
                        if(s(ss, ci).length > 0){
                            r[++ri] = ci;
                        }
                    }
                    return r;
                },

                "next" : function(c, ss){
                    var is = Ext.DomQuery.is;
                    var r = [], ri = -1;
                    for(var i = 0, ci; ci = c[i]; i++){
                        var n = next(ci);
                        if(n && is(n, ss)){
                            r[++ri] = ci;
                        }
                    }
                    return r;
                },

                "prev" : function(c, ss){
                    var is = Ext.DomQuery.is;
                    var r = [], ri = -1;
                    for(var i = 0, ci; ci = c[i]; i++){
                        var n = prev(ci);
                        if(n && is(n, ss)){
                            r[++ri] = ci;
                        }
                    }
                    return r;
                }
            }
        };
    }();

    Ext.query = Ext.DomQuery.select;

    Ext.util.Observable = function(){

        if(this.listeners){
            this.on(this.listeners);
            delete this.listeners;
        }
    };
    Ext.util.Observable.prototype = {

        fireEvent : function(){
            if(this.eventsSuspended !== true){
                var ce = this.events[arguments[0].toLowerCase()];
                if(typeof ce == "object"){
                    return ce.fire.apply(ce, Array.prototype.slice.call(arguments, 1));
                }
            }
            return true;
        },

            filterOptRe : /^(?:scope|delay|buffer|single)$/,

        addListener : function(eventName, fn, scope, o){
            if(typeof eventName == "object"){
                o = eventName;
                for(var e in o){
                    if(this.filterOptRe.test(e)){
                        continue;
                    }
                    if(typeof o[e] == "function"){
                                            this.addListener(e, o[e], o.scope,  o);
                    }else{
                                            this.addListener(e, o[e].fn, o[e].scope, o[e]);
                    }
                }
                return;
            }
            o = (!o || typeof o == "boolean") ? {} : o;
            eventName = eventName.toLowerCase();
            var ce = this.events[eventName] || true;
            if(typeof ce == "boolean"){
                ce = new Ext.util.Event(this, eventName);
                this.events[eventName] = ce;
            }
            ce.addListener(fn, scope, o);
        },

        removeListener : function(eventName, fn, scope){
            var ce = this.events[eventName.toLowerCase()];
            if(typeof ce == "object"){
                ce.removeListener(fn, scope);
            }
        },

        purgeListeners : function(){
            for(var evt in this.events){
                if(typeof this.events[evt] == "object"){
                     this.events[evt].clearListeners();
                }
            }
        },

        relayEvents : function(o, events){
            var createHandler = function(ename){
                return function(){
                    return this.fireEvent.apply(this, Ext.combine(ename, Array.prototype.slice.call(arguments, 0)));
                };
            };
            for(var i = 0, len = events.length; i < len; i++){
                var ename = events[i];
                if(!this.events[ename]){ this.events[ename] = true; };
                o.on(ename, createHandler(ename), this);
            }
        },

        addEvents : function(o){
            if(!this.events){
                this.events = {};
            }
            if(typeof o == 'string'){
                for(var i = 0, a = arguments, v; v = a[i]; i++){
                    if(!this.events[a[i]]){
                        o[a[i]] = true;
                    }
                }
            }else{
                Ext.applyIf(this.events, o);
            }
        },

        hasListener : function(eventName){
            var e = this.events[eventName];
            return typeof e == "object" && e.listeners.length > 0;
        },

        suspendEvents : function(){
            this.eventsSuspended = true;
        },

        resumeEvents : function(){
            this.eventsSuspended = false;
        },

                    getMethodEvent : function(method){
            if(!this.methodEvents){
                this.methodEvents = {};
            }
            var e = this.methodEvents[method];
            if(!e){
                e = {};
                this.methodEvents[method] = e;

                e.originalFn = this[method];
                e.methodName = method;
                e.before = [];
                e.after = [];

                var returnValue, v, cancel;
                var obj = this;

                var makeCall = function(fn, scope, args){
                    if((v = fn.apply(scope || obj, args)) !== undefined){
                        if(typeof v === 'object'){
                            if(v.returnValue !== undefined){
                                returnValue = v.returnValue;
                            }else{
                                returnValue = v;
                            }
                            if(v.cancel === true){
                                cancel = true;
                            }
                        }else if(v === false){
                            cancel = true;
                        }else {
                            returnValue = v;
                        }
                    }
                }

                this[method] = function(){
                    returnValue = v = undefined; cancel = false;
                    var args = Array.prototype.slice.call(arguments, 0);
                    for(var i = 0, len = e.before.length; i < len; i++){
                        makeCall(e.before[i].fn, e.before[i].scope, args);
                        if(cancel){
                            return returnValue;
                        }
                    }

                    if((v = e.originalFn.apply(obj, args)) !== undefined){
                        returnValue = v;
                    }

                    for(var i = 0, len = e.after.length; i < len; i++){
                        makeCall(e.after[i].fn, e.after[i].scope, args);
                        if(cancel){
                            return returnValue;
                        }
                    }
                    return returnValue;
                };
            }
            return e;
        },

            beforeMethod : function(method, fn, scope){
            var e = this.getMethodEvent(method);
            e.before.push({fn: fn, scope: scope});
        },

            afterMethod : function(method, fn, scope){
            var e = this.getMethodEvent(method);
            e.after.push({fn: fn, scope: scope});
        },

        removeMethodListener : function(method, fn, scope){
            var e = this.getMethodEvent(method);
            for(var i = 0, len = e.before.length; i < len; i++){
                if(e.before[i].fn == fn && e.before[i].scope == scope){
                    e.before.splice(i, 1);
                    return;
                }
            }
            for(var i = 0, len = e.after.length; i < len; i++){
                if(e.after[i].fn == fn && e.after[i].scope == scope){
                    e.after.splice(i, 1);
                    return;
                }
            }
        }
    };

    Ext.util.Observable.prototype.on = Ext.util.Observable.prototype.addListener;

    Ext.util.Observable.prototype.un = Ext.util.Observable.prototype.removeListener;

    Ext.util.Observable.capture = function(o, fn, scope){
        o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
    };

    Ext.util.Observable.releaseCapture = function(o){
        o.fireEvent = Ext.util.Observable.prototype.fireEvent;
    };

    (function(){

        var createBuffered = function(h, o, scope){
            var task = new Ext.util.DelayedTask();
            return function(){
                task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
            };
        };

        var createSingle = function(h, e, fn, scope){
            return function(){
                e.removeListener(fn, scope);
                return h.apply(scope, arguments);
            };
        };

        var createDelayed = function(h, o, scope){
            return function(){
                var args = Array.prototype.slice.call(arguments, 0);
                setTimeout(function(){
                    h.apply(scope, args);
                }, o.delay || 10);
            };
        };

        Ext.util.Event = function(obj, name){
            this.name = name;
            this.obj = obj;
            this.listeners = [];
        };

        Ext.util.Event.prototype = {
            addListener : function(fn, scope, options){
                scope = scope || this.obj;
                if(!this.isListening(fn, scope)){
                    var l = this.createListener(fn, scope, options);
                    if(!this.firing){
                        this.listeners.push(l);
                    }else{                     this.listeners = this.listeners.slice(0);
                        this.listeners.push(l);
                    }
                }
            },

            createListener : function(fn, scope, o){
                o = o || {};
                scope = scope || this.obj;
                var l = {fn: fn, scope: scope, options: o};
                var h = fn;
                if(o.delay){
                    h = createDelayed(h, o, scope);
                }
                if(o.single){
                    h = createSingle(h, this, fn, scope);
                }
                if(o.buffer){
                    h = createBuffered(h, o, scope);
                }
                l.fireFn = h;
                return l;
            },

            findListener : function(fn, scope){
                scope = scope || this.obj;
                var ls = this.listeners;
                for(var i = 0, len = ls.length; i < len; i++){
                    var l = ls[i];
                    if(l.fn == fn && l.scope == scope){
                        return i;
                    }
                }
                return -1;
            },

            isListening : function(fn, scope){
                return this.findListener(fn, scope) != -1;
            },

            removeListener : function(fn, scope){
                var index;
                if((index = this.findListener(fn, scope)) != -1){
                    if(!this.firing){
                        this.listeners.splice(index, 1);
                    }else{
                        this.listeners = this.listeners.slice(0);
                        this.listeners.splice(index, 1);
                    }
                    return true;
                }
                return false;
            },

            clearListeners : function(){
                this.listeners = [];
            },

            fire : function(){
                var ls = this.listeners, scope, len = ls.length;
                if(len > 0){
                    this.firing = true;
                    var args = Array.prototype.slice.call(arguments, 0);
                    for(var i = 0; i < len; i++){
                        var l = ls[i];
                        if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){
                            this.firing = false;
                            return false;
                        }
                    }
                    this.firing = false;
                }
                return true;
            }
        };
    })();

    Ext.EventManager = function(){
        var docReadyEvent, docReadyProcId, docReadyState = false;
        var resizeEvent, resizeTask, textEvent, textSize;
        var E = Ext.lib.Event;
        var D = Ext.lib.Dom;

        var fireDocReady = function(){
            if(!docReadyState){
                docReadyState = true;
                Ext.isReady = true;
                if(docReadyProcId){
                    clearInterval(docReadyProcId);
                }
                if(Ext.isGecko || Ext.isOpera) {
                    document.removeEventListener("DOMContentLoaded", fireDocReady, false);
                }
                if(Ext.isIE){
                    var defer = document.getElementById("ie-deferred-loader");
                    if(defer){
                        defer.onreadystatechange = null;
                        defer.parentNode.removeChild(defer);
                    }
                }
                if(docReadyEvent){
                    docReadyEvent.fire();
                    docReadyEvent.clearListeners();
                }
            }
        };

        var initDocReady = function(){
            docReadyEvent = new Ext.util.Event();
            if(Ext.isGecko || Ext.isOpera) {
                document.addEventListener("DOMContentLoaded", fireDocReady, false);
            }else if(Ext.isIE){
                document.write("");
                var defer = document.getElementById("ie-deferred-loader");
                defer.onreadystatechange = function(){
                    if(this.readyState == "complete"){
                        fireDocReady();
                    }
                };
            }else if(Ext.isSafari){
                docReadyProcId = setInterval(function(){
                    var rs = document.readyState;
                    if(rs == "complete") {
                        fireDocReady();
                     }
                }, 10);
            }

            E.on(window, "load", fireDocReady);
        };

        var createBuffered = function(h, o){
            var task = new Ext.util.DelayedTask(h);
            return function(e){

                e = new Ext.EventObjectImpl(e);
                task.delay(o.buffer, h, null, [e]);
            };
        };

        var createSingle = function(h, el, ename, fn){
            return function(e){
                Ext.EventManager.removeListener(el, ename, fn);
                h(e);
            };
        };

        var createDelayed = function(h, o){
            return function(e){

                e = new Ext.EventObjectImpl(e);
                setTimeout(function(){
                    h(e);
                }, o.delay || 10);
            };
        };

        var listen = function(element, ename, opt, fn, scope){
            var o = (!opt || typeof opt == "boolean") ? {} : opt;
            fn = fn || o.fn; scope = scope || o.scope;
            var el = Ext.getDom(element);
            if(!el){
                throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
            }
            var h = function(e){
                e = Ext.EventObject.setEvent(e);
                var t;
                if(o.delegate){
                    t = e.getTarget(o.delegate, el);
                    if(!t){
                        return;
                    }
                }else{
                    t = e.target;
                }
                if(o.stopEvent === true){
                    e.stopEvent();
                }
                if(o.preventDefault === true){
                   e.preventDefault();
                }
                if(o.stopPropagation === true){
                    e.stopPropagation();
                }

                if(o.normalized === false){
                    e = e.browserEvent;
                }

                fn.call(scope || el, e, t, o);
            };
            if(o.delay){
                h = createDelayed(h, o);
            }
            if(o.single){
                h = createSingle(h, el, ename, fn);
            }
            if(o.buffer){
                h = createBuffered(h, o);
            }
            fn._handlers = fn._handlers || [];
            fn._handlers.push([Ext.id(el), ename, h]);

            E.on(el, ename, h);
            if(ename == "mousewheel" && el.addEventListener){
                el.addEventListener("DOMMouseScroll", h, false);
                E.on(window, 'unload', function(){
                    el.removeEventListener("DOMMouseScroll", h, false);
                });
            }
            if(ename == "mousedown" && el == document){
                Ext.EventManager.stoppedMouseDownEvent.addListener(h);
            }
            return h;
        };

        var stopListening = function(el, ename, fn){
            var id = Ext.id(el), hds = fn._handlers, hd = fn;
            if(hds){
                for(var i = 0, len = hds.length; i < len; i++){
                    var h = hds[i];
                    if(h[0] == id && h[1] == ename){
                        hd = h[2];
                        hds.splice(i, 1);
                        break;
                    }
                }
            }
            E.un(el, ename, hd);
            el = Ext.getDom(el);
            if(ename == "mousewheel" && el.addEventListener){
                el.removeEventListener("DOMMouseScroll", hd, false);
            }
            if(ename == "mousedown" && el == document){
                Ext.EventManager.stoppedMouseDownEvent.removeListener(hd);
            }
        };

        var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
        var pub = {

            addListener : function(element, eventName, fn, scope, options){
                if(typeof eventName == "object"){
                    var o = eventName;
                    for(var e in o){
                        if(propRe.test(e)){
                            continue;
                        }
                        if(typeof o[e] == "function"){

                            listen(element, e, o, o[e], o.scope);
                        }else{

                            listen(element, e, o[e]);
                        }
                    }
                    return;
                }
                return listen(element, eventName, options, fn, scope);
            },

            removeListener : function(element, eventName, fn){
                return stopListening(element, eventName, fn);
            },

            onDocumentReady : function(fn, scope, options){
                if(docReadyState){
                    docReadyEvent.addListener(fn, scope, options);
                    docReadyEvent.fire();
                    docReadyEvent.clearListeners();
                    return;
                }
                if(!docReadyEvent){
                    initDocReady();
                }
                docReadyEvent.addListener(fn, scope, options);
            },

            onWindowResize : function(fn, scope, options){
                if(!resizeEvent){
                    resizeEvent = new Ext.util.Event();
                    resizeTask = new Ext.util.DelayedTask(function(){
                        resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
                    });
                    E.on(window, "resize", this.fireWindowResize, this);
                }
                resizeEvent.addListener(fn, scope, options);
            },

            fireWindowResize : function(){
                if(resizeEvent){
                    if((Ext.isIE||Ext.isAir) && resizeTask){
                        resizeTask.delay(50);
                    }else{
                        resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
                    }
                }
            },

            onTextResize : function(fn, scope, options){
                if(!textEvent){
                    textEvent = new Ext.util.Event();
                    var textEl = new Ext.Element(document.createElement('div'));
                    textEl.dom.className = 'x-text-resize';
                    textEl.dom.innerHTML = 'X';
                    textEl.appendTo(document.body);
                    textSize = textEl.dom.offsetHeight;
                    setInterval(function(){
                        if(textEl.dom.offsetHeight != textSize){
                            textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
                        }
                    }, this.textResizeInterval);
                }
                textEvent.addListener(fn, scope, options);
            },

            removeResizeListener : function(fn, scope){
                if(resizeEvent){
                    resizeEvent.removeListener(fn, scope);
                }
            },

            fireResize : function(){
                if(resizeEvent){
                    resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
                }
            },

            ieDeferSrc : false,

            textResizeInterval : 50
        };

        pub.on = pub.addListener;

        pub.un = pub.removeListener;

        pub.stoppedMouseDownEvent = new Ext.util.Event();
        return pub;
    }();

    Ext.onReady = Ext.EventManager.onDocumentReady;

    Ext.onReady(function(){
        var bd = Ext.getBody();
        if(!bd){ return; }

        var cls = [
                Ext.isIE ? "ext-ie " + (Ext.isIE6 ? 'ext-ie6' : 'ext-ie7')
                : Ext.isGecko ? "ext-gecko"
                : Ext.isOpera ? "ext-opera"
                : Ext.isSafari ? "ext-safari" : ""];

        if(Ext.isMac){
            cls.push("ext-mac");
        }
        if(Ext.isLinux){
            cls.push("ext-linux");
        }
        if(Ext.isBorderBox){
            cls.push('ext-border-box');
        }
        if(Ext.isStrict){
            var p = bd.dom.parentNode;
            if(p){
                p.className += ' ext-strict';
            }
        }
        bd.addClass(cls.join(' '));
    });

    Ext.EventObject = function(){

        var E = Ext.lib.Event;

        var safariKeys = {
            63234 : 37,
            63235 : 39,
            63232 : 38,
            63233 : 40,
            63276 : 33,
            63277 : 34,
            63272 : 46,
            63273 : 36,
            63275 : 35
        };

        var btnMap = Ext.isIE ? {1:0,4:1,2:2} :
                    (Ext.isSafari ? {1:0,2:1,3:2} : {0:0,1:1,2:2});

        Ext.EventObjectImpl = function(e){
            if(e){
                this.setEvent(e.browserEvent || e);
            }
        };
        Ext.EventObjectImpl.prototype = {

            browserEvent : null,

            button : -1,

            shiftKey : false,

            ctrlKey : false,

            altKey : false,

            BACKSPACE : 8,

            TAB : 9,

            RETURN : 13,

            ENTER : 13,

            SHIFT : 16,

            CONTROL : 17,

            ESC : 27,

            SPACE : 32,

            PAGEUP : 33,

            PAGEDOWN : 34,

            END : 35,

            HOME : 36,

            LEFT : 37,

            UP : 38,

            RIGHT : 39,

            DOWN : 40,

            DELETE : 46,

            F5 : 116,

            setEvent : function(e){
                if(e == this || (e && e.browserEvent)){
                    return e;
                }
                this.browserEvent = e;
                if(e){

                    this.button = e.button ? btnMap[e.button] : (e.which ? e.which-1 : -1);
                    if(e.type == 'click' && this.button == -1){
                        this.button = 0;
                    }
                    this.type = e.type;
                    this.shiftKey = e.shiftKey;

                    this.ctrlKey = e.ctrlKey || e.metaKey;
                    this.altKey = e.altKey;

                    this.keyCode = e.keyCode;
                    this.charCode = e.charCode;

                    this.target = E.getTarget(e);

                    this.xy = E.getXY(e);
                }else{
                    this.button = -1;
                    this.shiftKey = false;
                    this.ctrlKey = false;
                    this.altKey = false;
                    this.keyCode = 0;
                    this.charCode =0;
                    this.target = null;
                    this.xy = [0, 0];
                }
                return this;
            },

            stopEvent : function(){
                if(this.browserEvent){
                    if(this.browserEvent.type == 'mousedown'){
                        Ext.EventManager.stoppedMouseDownEvent.fire(this);
                    }
                    E.stopEvent(this.browserEvent);
                }
            },

            preventDefault : function(){
                if(this.browserEvent){
                    E.preventDefault(this.browserEvent);
                }
            },

            isNavKeyPress : function(){
                var k = this.keyCode;
                k = Ext.isSafari ? (safariKeys[k] || k) : k;
                return (k >= 33 && k <= 40) || k == this.RETURN || k == this.TAB || k == this.ESC;
            },

            isSpecialKey : function(){
                var k = this.keyCode;
                return (this.type == 'keypress' && this.ctrlKey) || k == 9 || k == 13  || k == 40 || k == 27 ||
                (k == 16) || (k == 17) ||
                (k >= 18 && k <= 20) ||
                (k >= 33 && k <= 35) ||
                (k >= 36 && k <= 39) ||
                (k >= 44 && k <= 45);
            },

            stopPropagation : function(){
                if(this.browserEvent){
                    if(this.browserEvent.type == 'mousedown'){
                        Ext.EventManager.stoppedMouseDownEvent.fire(this);
                    }
                    E.stopPropagation(this.browserEvent);
                }
            },

            getCharCode : function(){
                return this.charCode || this.keyCode;
            },

            getKey : function(){
                var k = this.keyCode || this.charCode;
                return Ext.isSafari ? (safariKeys[k] || k) : k;
            },

            getPageX : function(){
                return this.xy[0];
            },

            getPageY : function(){
                return this.xy[1];
            },

            getTime : function(){
                if(this.browserEvent){
                    return E.getTime(this.browserEvent);
                }
                return null;
            },

            getXY : function(){
                return this.xy;
            },

            getTarget : function(selector, maxDepth, returnEl){
            	var t = Ext.get(this.target);
                return selector ? t.findParent(selector, maxDepth, returnEl) : (returnEl ? t : this.target);
            },

            getRelatedTarget : function(){
                if(this.browserEvent){
                    return E.getRelatedTarget(this.browserEvent);
                }
                return null;
            },

            getWheelDelta : function(){
                var e = this.browserEvent;
                var delta = 0;
                if(e.wheelDelta){
                    delta = e.wheelDelta/120;
                }else if(e.detail){
                    delta = -e.detail/3;
                }
                return delta;
            },

            hasModifier : function(){
                return ((this.ctrlKey || this.altKey) || this.shiftKey) ? true : false;
            },

            within : function(el, related){
                var t = this[related ? "getRelatedTarget" : "getTarget"]();
                return t && Ext.fly(el).contains(t);
            },

            getPoint : function(){
                return new Ext.lib.Point(this.xy[0], this.xy[1]);
            }
        };

        return new Ext.EventObjectImpl();
    }();

    (function(){
    var D = Ext.lib.Dom;
    var E = Ext.lib.Event;
    var A = Ext.lib.Anim;

    var propCache = {};
    var camelRe = /(-[a-z])/gi;
    var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
    var view = document.defaultView;

    Ext.Element = function(element, forceNew){
        var dom = typeof element == "string" ?
                document.getElementById(element) : element;
        if(!dom){         return null;
        }
        var id = dom.id;
        if(forceNew !== true && id && Ext.Element.cache[id]){         return Ext.Element.cache[id];
        }

        this.dom = dom;

        this.id = id || Ext.id(dom);
    };

    var El = Ext.Element;

    El.prototype = {

        originalDisplay : "",

        visibilityMode : 1,

        defaultUnit : "px",

        setVisibilityMode : function(visMode){
            this.visibilityMode = visMode;
            return this;
        },

        enableDisplayMode : function(display){
            this.setVisibilityMode(El.DISPLAY);
            if(typeof display != "undefined") this.originalDisplay = display;
            return this;
        },

        findParent : function(simpleSelector, maxDepth, returnEl){
            var p = this.dom, b = document.body, depth = 0, dq = Ext.DomQuery, stopEl;
            maxDepth = maxDepth || 50;
            if(typeof maxDepth != "number"){
                stopEl = Ext.getDom(maxDepth);
                maxDepth = 10;
            }
            while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
                if(dq.is(p, simpleSelector)){
                    return returnEl ? Ext.get(p) : p;
                }
                depth++;
                p = p.parentNode;
            }
            return null;
        },

        findParentNode : function(simpleSelector, maxDepth, returnEl){
            var p = Ext.fly(this.dom.parentNode, '_internal');
            return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
        },

        up : function(simpleSelector, maxDepth){
            return this.findParentNode(simpleSelector, maxDepth, true);
        },

        is : function(simpleSelector){
            return Ext.DomQuery.is(this.dom, simpleSelector);
        },

        animate : function(args, duration, onComplete, easing, animType){
            this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
            return this;
        },

        anim : function(args, opt, animType, defaultDur, defaultEase, cb){
            animType = animType || 'run';
            opt = opt || {};
            var anim = Ext.lib.Anim[animType](
                this.dom, args,
                (opt.duration || defaultDur) || .35,
                (opt.easing || defaultEase) || 'easeOut',
                function(){
                    Ext.callback(cb, this);
                    Ext.callback(opt.callback, opt.scope || this, [this, opt]);
                },
                this
            );
            opt.anim = anim;
            return anim;
        },

            preanim : function(a, i){
            return !a[i] ? false : (typeof a[i] == "object" ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
        },

        clean : function(forceReclean){
            if(this.isCleaned && forceReclean !== true){
                return this;
            }
            var ns = /\S/;
            var d = this.dom, n = d.firstChild, ni = -1;
     	    while(n){
     	        var nx = n.nextSibling;
     	        if(n.nodeType == 3 && !ns.test(n.nodeValue)){
     	            d.removeChild(n);
     	        }else{
     	            n.nodeIndex = ++ni;
     	        }
     	        n = nx;
     	    }
     	    this.isCleaned = true;
     	    return this;
     	},

        scrollIntoView : function(container, hscroll){
            var c = Ext.getDom(container) || Ext.getBody().dom;
            var el = this.dom;

            var o = this.getOffsetsTo(c),
                l = o[0] + c.scrollLeft,
                t = o[1] + c.scrollTop,
                b = t+el.offsetHeight,
                r = l+el.offsetWidth;

            var ch = c.clientHeight;
            var ct = parseInt(c.scrollTop, 10);
            var cl = parseInt(c.scrollLeft, 10);
            var cb = ct + ch;
            var cr = cl + c.clientWidth;

            if(el.offsetHeight > ch || t < ct){
            	c.scrollTop = t;
            }else if(b > cb){
                c.scrollTop = b-ch;
            }
            c.scrollTop = c.scrollTop;
            if(hscroll !== false){
    			if(el.offsetWidth > c.clientWidth || l < cl){
                    c.scrollLeft = l;
                }else if(r > cr){
                    c.scrollLeft = r-c.clientWidth;
                }
                c.scrollLeft = c.scrollLeft;
            }
            return this;
        },

            scrollChildIntoView : function(child, hscroll){
            Ext.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
        },

        autoHeight : function(animate, duration, onComplete, easing){
            var oldHeight = this.getHeight();
            this.clip();
            this.setHeight(1);         setTimeout(function(){
                var height = parseInt(this.dom.scrollHeight, 10);             if(!animate){
                    this.setHeight(height);
                    this.unclip();
                    if(typeof onComplete == "function"){
                        onComplete();
                    }
                }else{
                    this.setHeight(oldHeight);                 this.setHeight(height, animate, duration, function(){
                        this.unclip();
                        if(typeof onComplete == "function") onComplete();
                    }.createDelegate(this), easing);
                }
            }.createDelegate(this), 0);
            return this;
        },

        contains : function(el){
            if(!el){return false;}
            return D.isAncestor(this.dom, el.dom ? el.dom : el);
        },

        isVisible : function(deep) {
            var vis = !(this.getStyle("visibility") == "hidden" || this.getStyle("display") == "none");
            if(deep !== true || !vis){
                return vis;
            }
            var p = this.dom.parentNode;
            while(p && p.tagName.toLowerCase() != "body"){
                if(!Ext.fly(p, '_isVisible').isVisible()){
                    return false;
                }
                p = p.parentNode;
            }
            return true;
        },

        select : function(selector, unique){
            return El.select(selector, unique, this.dom);
        },

        query : function(selector, unique){
            return Ext.DomQuery.select(selector, this.dom);
        },

        child : function(selector, returnDom){
            var n = Ext.DomQuery.selectNode(selector, this.dom);
            return returnDom ? n : Ext.get(n);
        },

        down : function(selector, returnDom){
            var n = Ext.DomQuery.selectNode(" > " + selector, this.dom);
            return returnDom ? n : Ext.get(n);
        },

        initDD : function(group, config, overrides){
            var dd = new Ext.dd.DD(Ext.id(this.dom), group, config);
            return Ext.apply(dd, overrides);
        },

        initDDProxy : function(group, config, overrides){
            var dd = new Ext.dd.DDProxy(Ext.id(this.dom), group, config);
            return Ext.apply(dd, overrides);
        },

        initDDTarget : function(group, config, overrides){
            var dd = new Ext.dd.DDTarget(Ext.id(this.dom), group, config);
            return Ext.apply(dd, overrides);
        },

         setVisible : function(visible, animate){
            if(!animate || !A){
                if(this.visibilityMode == El.DISPLAY){
                    this.setDisplayed(visible);
                }else{
                    this.fixDisplay();
                    this.dom.style.visibility = visible ? "visible" : "hidden";
                }
            }else{
                            var dom = this.dom;
                var visMode = this.visibilityMode;
                if(visible){
                    this.setOpacity(.01);
                    this.setVisible(true);
                }
                this.anim({opacity: { to: (visible?1:0) }},
                      this.preanim(arguments, 1),
                      null, .35, 'easeIn', function(){
                         if(!visible){
                             if(visMode == El.DISPLAY){
                                 dom.style.display = "none";
                             }else{
                                 dom.style.visibility = "hidden";
                             }
                             Ext.get(dom).setOpacity(1);
                         }
                     });
            }
            return this;
        },

        isDisplayed : function() {
            return this.getStyle("display") != "none";
        },

        toggle : function(animate){
            this.setVisible(!this.isVisible(), this.preanim(arguments, 0));
            return this;
        },

        setDisplayed : function(value) {
            if(typeof value == "boolean"){
               value = value ? this.originalDisplay : "none";
            }
            this.setStyle("display", value);
            return this;
        },

        focus : function() {
            try{
                this.dom.focus();
            }catch(e){}
            return this;
        },

        blur : function() {
            try{
                this.dom.blur();
            }catch(e){}
            return this;
        },

        addClass : function(className){
            if(Ext.isArray(className)){
                for(var i = 0, len = className.length; i < len; i++) {
                	this.addClass(className[i]);
                }
            }else{
                if(className && !this.hasClass(className)){
                    this.dom.className = this.dom.className + " " + className;
                }
            }
            return this;
        },

        radioClass : function(className){
            var siblings = this.dom.parentNode.childNodes;
            for(var i = 0; i < siblings.length; i++) {
            	var s = siblings[i];
            	if(s.nodeType == 1){
            	    Ext.get(s).removeClass(className);
            	}
            }
            this.addClass(className);
            return this;
        },

        removeClass : function(className){
            if(!className || !this.dom.className){
                return this;
            }
            if(Ext.isArray(className)){
                for(var i = 0, len = className.length; i < len; i++) {
                	this.removeClass(className[i]);
                }
            }else{
                if(this.hasClass(className)){
                    var re = this.classReCache[className];
                    if (!re) {
                       re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");
                       this.classReCache[className] = re;
                    }
                    this.dom.className =
                        this.dom.className.replace(re, " ");
                }
            }
            return this;
        },

            classReCache: {},

        toggleClass : function(className){
            if(this.hasClass(className)){
                this.removeClass(className);
            }else{
                this.addClass(className);
            }
            return this;
        },

        hasClass : function(className){
            return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
        },

        replaceClass : function(oldClassName, newClassName){
            this.removeClass(oldClassName);
            this.addClass(newClassName);
            return this;
        },

        getStyles : function(){
            var a = arguments, len = a.length, r = {};
            for(var i = 0; i < len; i++){
                r[a[i]] = this.getStyle(a[i]);
            }
            return r;
        },

        getStyle : function(){
            return view && view.getComputedStyle ?
                function(prop){
                    var el = this.dom, v, cs, camel;
                    if(prop == 'float'){
                        prop = "cssFloat";
                    }
                    if(v = el.style[prop]){
                        return v;
                    }
                    if(cs = view.getComputedStyle(el, "")){
                        if(!(camel = propCache[prop])){
                            camel = propCache[prop] = prop.replace(camelRe, camelFn);
                        }
                        return cs[camel];
                    }
                    return null;
                } :
                function(prop){
                    var el = this.dom, v, cs, camel;
                    if(prop == 'opacity'){
                        if(typeof el.style.filter == 'string'){
                            var m = el.style.filter.match(/alpha\(opacity=(.*)\)/i);
                            if(m){
                                var fv = parseFloat(m[1]);
                                if(!isNaN(fv)){
                                    return fv ? fv / 100 : 0;
                                }
                            }
                        }
                        return 1;
                    }else if(prop == 'float'){
                        prop = "styleFloat";
                    }
                    if(!(camel = propCache[prop])){
                        camel = propCache[prop] = prop.replace(camelRe, camelFn);
                    }
                    if(v = el.style[camel]){
                        return v;
                    }
                    if(cs = el.currentStyle){
                        return cs[camel];
                    }
                    return null;
                };
        }(),

        setStyle : function(prop, value){
            if(typeof prop == "string"){
                var camel;
                if(!(camel = propCache[prop])){
                    camel = propCache[prop] = prop.replace(camelRe, camelFn);
                }
                if(camel == 'opacity') {
                    this.setOpacity(value);
                }else{
                    this.dom.style[camel] = value;
                }
            }else{
                for(var style in prop){
                    if(typeof prop[style] != "function"){
                       this.setStyle(style, prop[style]);
                    }
                }
            }
            return this;
        },

        applyStyles : function(style){
            Ext.DomHelper.applyStyles(this.dom, style);
            return this;
        },

        getX : function(){
            return D.getX(this.dom);
        },

        getY : function(){
            return D.getY(this.dom);
        },

        getXY : function(){
            return D.getXY(this.dom);
        },

        getOffsetsTo : function(el){
            var o = this.getXY();
            var e = Ext.fly(el, '_internal').getXY();
            return [o[0]-e[0],o[1]-e[1]];
        },

        setX : function(x, animate){
            if(!animate || !A){
                D.setX(this.dom, x);
            }else{
                this.setXY([x, this.getY()], this.preanim(arguments, 1));
            }
            return this;
        },

        setY : function(y, animate){
            if(!animate || !A){
                D.setY(this.dom, y);
            }else{
                this.setXY([this.getX(), y], this.preanim(arguments, 1));
            }
            return this;
        },

        setLeft : function(left){
            this.setStyle("left", this.addUnits(left));
            return this;
        },

        setTop : function(top){
            this.setStyle("top", this.addUnits(top));
            return this;
        },

        setRight : function(right){
            this.setStyle("right", this.addUnits(right));
            return this;
        },

        setBottom : function(bottom){
            this.setStyle("bottom", this.addUnits(bottom));
            return this;
        },

        setXY : function(pos, animate){
            if(!animate || !A){
                D.setXY(this.dom, pos);
            }else{
                this.anim({points: {to: pos}}, this.preanim(arguments, 1), 'motion');
            }
            return this;
        },

        setLocation : function(x, y, animate){
            this.setXY([x, y], this.preanim(arguments, 2));
            return this;
        },

        moveTo : function(x, y, animate){
            this.setXY([x, y], this.preanim(arguments, 2));
            return this;
        },

        getRegion : function(){
            return D.getRegion(this.dom);
        },

        getHeight : function(contentHeight){
            var h = this.dom.offsetHeight || 0;
            h = contentHeight !== true ? h : h-this.getBorderWidth("tb")-this.getPadding("tb");
            return h < 0 ? 0 : h;
        },

        getWidth : function(contentWidth){
            var w = this.dom.offsetWidth || 0;
            w = contentWidth !== true ? w : w-this.getBorderWidth("lr")-this.getPadding("lr");
            return w < 0 ? 0 : w;
        },

        getComputedHeight : function(){
            var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);
            if(!h){
                h = parseInt(this.getStyle('height'), 10) || 0;
                if(!this.isBorderBox()){
                    h += this.getFrameWidth('tb');
                }
            }
            return h;
        },

        getComputedWidth : function(){
            var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
            if(!w){
                w = parseInt(this.getStyle('width'), 10) || 0;
                if(!this.isBorderBox()){
                    w += this.getFrameWidth('lr');
                }
            }
            return w;
        },

        getSize : function(contentSize){
            return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
        },

        getStyleSize : function(){
            var w, h, d = this.dom, s = d.style;
            if(s.width && s.width != 'auto'){
                w = parseInt(s.width, 10);
                if(Ext.isBorderBox){
                   w -= this.getFrameWidth('lr');
                }
            }
            if(s.height && s.height != 'auto'){
                h = parseInt(s.height, 10);
                if(Ext.isBorderBox){
                   h -= this.getFrameWidth('tb');
                }
            }
            return {width: w || this.getWidth(true), height: h || this.getHeight(true)};

        },

        getViewSize : function(){
            var d = this.dom, doc = document, aw = 0, ah = 0;
            if(d == doc || d == doc.body){
                return {width : D.getViewWidth(), height: D.getViewHeight()};
            }else{
                return {
                    width : d.clientWidth,
                    height: d.clientHeight
                };
            }
        },

        getValue : function(asNumber){
            return asNumber ? parseInt(this.dom.value, 10) : this.dom.value;
        },

            adjustWidth : function(width){
            if(typeof width == "number"){
                if(this.autoBoxAdjust && !this.isBorderBox()){
                   width -= (this.getBorderWidth("lr") + this.getPadding("lr"));
                }
                if(width < 0){
                    width = 0;
                }
            }
            return width;
        },

            adjustHeight : function(height){
            if(typeof height == "number"){
               if(this.autoBoxAdjust && !this.isBorderBox()){
                   height -= (this.getBorderWidth("tb") + this.getPadding("tb"));
               }
               if(height < 0){
                   height = 0;
               }
            }
            return height;
        },

        setWidth : function(width, animate){
            width = this.adjustWidth(width);
            if(!animate || !A){
                this.dom.style.width = this.addUnits(width);
            }else{
                this.anim({width: {to: width}}, this.preanim(arguments, 1));
            }
            return this;
        },

         setHeight : function(height, animate){
            height = this.adjustHeight(height);
            if(!animate || !A){
                this.dom.style.height = this.addUnits(height);
            }else{
                this.anim({height: {to: height}}, this.preanim(arguments, 1));
            }
            return this;
        },

         setSize : function(width, height, animate){
            if(typeof width == "object"){             height = width.height; width = width.width;
            }
            width = this.adjustWidth(width); height = this.adjustHeight(height);
            if(!animate || !A){
                this.dom.style.width = this.addUnits(width);
                this.dom.style.height = this.addUnits(height);
            }else{
                this.anim({width: {to: width}, height: {to: height}}, this.preanim(arguments, 2));
            }
            return this;
        },

        setBounds : function(x, y, width, height, animate){
            if(!animate || !A){
                this.setSize(width, height);
                this.setLocation(x, y);
            }else{
                width = this.adjustWidth(width); height = this.adjustHeight(height);
                this.anim({points: {to: [x, y]}, width: {to: width}, height: {to: height}},
                              this.preanim(arguments, 4), 'motion');
            }
            return this;
        },

        setRegion : function(region, animate){
            this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.preanim(arguments, 1));
            return this;
        },

        addListener : function(eventName, fn, scope, options){
            Ext.EventManager.on(this.dom,  eventName, fn, scope || this, options);
        },

        removeListener : function(eventName, fn){
            Ext.EventManager.removeListener(this.dom,  eventName, fn);
            return this;
        },

        removeAllListeners : function(){
            E.purgeElement(this.dom);
            return this;
        },

        relayEvent : function(eventName, observable){
            this.on(eventName, function(e){
                observable.fireEvent(eventName, e);
            });
        },

         setOpacity : function(opacity, animate){
            if(!animate || !A){
                var s = this.dom.style;
                if(Ext.isIE){
                    s.zoom = 1;
                    s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +
                               (opacity == 1 ? "" : " alpha(opacity=" + opacity * 100 + ")");
                }else{
                    s.opacity = opacity;
                }
            }else{
                this.anim({opacity: {to: opacity}}, this.preanim(arguments, 1), null, .35, 'easeIn');
            }
            return this;
        },

        getLeft : function(local){
            if(!local){
                return this.getX();
            }else{
                return parseInt(this.getStyle("left"), 10) || 0;
            }
        },

        getRight : function(local){
            if(!local){
                return this.getX() + this.getWidth();
            }else{
                return (this.getLeft(true) + this.getWidth()) || 0;
            }
        },

        getTop : function(local) {
            if(!local){
                return this.getY();
            }else{
                return parseInt(this.getStyle("top"), 10) || 0;
            }
        },

        getBottom : function(local){
            if(!local){
                return this.getY() + this.getHeight();
            }else{
                return (this.getTop(true) + this.getHeight()) || 0;
            }
        },

        position : function(pos, zIndex, x, y){
            if(!pos){
               if(this.getStyle('position') == 'static'){
                   this.setStyle('position', 'relative');
               }
            }else{
                this.setStyle("position", pos);
            }
            if(zIndex){
                this.setStyle("z-index", zIndex);
            }
            if(x !== undefined && y !== undefined){
                this.setXY([x, y]);
            }else if(x !== undefined){
                this.setX(x);
            }else if(y !== undefined){
                this.setY(y);
            }
        },

        clearPositioning : function(value){
            value = value ||'';
            this.setStyle({
                "left": value,
                "right": value,
                "top": value,
                "bottom": value,
                "z-index": "",
                "position" : "static"
            });
            return this;
        },

        getPositioning : function(){
            var l = this.getStyle("left");
            var t = this.getStyle("top");
            return {
                "position" : this.getStyle("position"),
                "left" : l,
                "right" : l ? "" : this.getStyle("right"),
                "top" : t,
                "bottom" : t ? "" : this.getStyle("bottom"),
                "z-index" : this.getStyle("z-index")
            };
        },

        getBorderWidth : function(side){
            return this.addStyles(side, El.borders);
        },

        getPadding : function(side){
            return this.addStyles(side, El.paddings);
        },

        setPositioning : function(pc){
            this.applyStyles(pc);
            if(pc.right == "auto"){
                this.dom.style.right = "";
            }
            if(pc.bottom == "auto"){
                this.dom.style.bottom = "";
            }
            return this;
        },

            fixDisplay : function(){
            if(this.getStyle("display") == "none"){
                this.setStyle("visibility", "hidden");
                this.setStyle("display", this.originalDisplay);             if(this.getStyle("display") == "none"){                 this.setStyle("display", "block");
                }
            }
        },

        	setOverflow : function(v){
        	if(v=='auto' && Ext.isMac && Ext.isGecko){     		this.dom.style.overflow = 'hidden';
            	(function(){this.dom.style.overflow = 'auto';}).defer(1, this);
        	}else{
        		this.dom.style.overflow = v;
        	}
    	},

         setLeftTop : function(left, top){
            this.dom.style.left = this.addUnits(left);
            this.dom.style.top = this.addUnits(top);
            return this;
        },

         move : function(direction, distance, animate){
            var xy = this.getXY();
            direction = direction.toLowerCase();
            switch(direction){
                case "l":
                case "left":
                    this.moveTo(xy[0]-distance, xy[1], this.preanim(arguments, 2));
                    break;
               case "r":
               case "right":
                    this.moveTo(xy[0]+distance, xy[1], this.preanim(arguments, 2));
                    break;
               case "t":
               case "top":
               case "up":
                    this.moveTo(xy[0], xy[1]-distance, this.preanim(arguments, 2));
                    break;
               case "b":
               case "bottom":
               case "down":
                    this.moveTo(xy[0], xy[1]+distance, this.preanim(arguments, 2));
                    break;
            }
            return this;
        },

        clip : function(){
            if(!this.isClipped){
               this.isClipped = true;
               this.originalClip = {
                   "o": this.getStyle("overflow"),
                   "x": this.getStyle("overflow-x"),
                   "y": this.getStyle("overflow-y")
               };
               this.setStyle("overflow", "hidden");
               this.setStyle("overflow-x", "hidden");
               this.setStyle("overflow-y", "hidden");
            }
            return this;
        },

        unclip : function(){
            if(this.isClipped){
                this.isClipped = false;
                var o = this.originalClip;
                if(o.o){this.setStyle("overflow", o.o);}
                if(o.x){this.setStyle("overflow-x", o.x);}
                if(o.y){this.setStyle("overflow-y", o.y);}
            }
            return this;
        },

        getAnchorXY : function(anchor, local, s){

            var w, h, vp = false;
            if(!s){
                var d = this.dom;
                if(d == document.body || d == document){
                    vp = true;
                    w = D.getViewWidth(); h = D.getViewHeight();
                }else{
                    w = this.getWidth(); h = this.getHeight();
                }
            }else{
                w = s.width;  h = s.height;
            }
            var x = 0, y = 0, r = Math.round;
            switch((anchor || "tl").toLowerCase()){
                case "c":
                    x = r(w*.5);
                    y = r(h*.5);
                break;
                case "t":
                    x = r(w*.5);
                    y = 0;
                break;
                case "l":
                    x = 0;
                    y = r(h*.5);
                break;
                case "r":
                    x = w;
                    y = r(h*.5);
                break;
                case "b":
                    x = r(w*.5);
                    y = h;
                break;
                case "tl":
                    x = 0;
                    y = 0;
                break;
                case "bl":
                    x = 0;
                    y = h;
                break;
                case "br":
                    x = w;
                    y = h;
                break;
                case "tr":
                    x = w;
                    y = 0;
                break;
            }
            if(local === true){
                return [x, y];
            }
            if(vp){
                var sc = this.getScroll();
                return [x + sc.left, y + sc.top];
            }
                    var o = this.getXY();
            return [x+o[0], y+o[1]];
        },

        getAlignToXY : function(el, p, o){
            el = Ext.get(el);
            if(!el || !el.dom){
                throw "Element.alignToXY with an element that doesn't exist";
            }
            var d = this.dom;
            var c = false;         var p1 = "", p2 = "";
            o = o || [0,0];

            if(!p){
                p = "tl-bl";
            }else if(p == "?"){
                p = "tl-bl?";
            }else if(p.indexOf("-") == -1){
                p = "tl-" + p;
            }
            p = p.toLowerCase();
            var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
            if(!m){
               throw "Element.alignTo with an invalid alignment " + p;
            }
            p1 = m[1]; p2 = m[2]; c = !!m[3];

                            var a1 = this.getAnchorXY(p1, true);
            var a2 = el.getAnchorXY(p2, false);

            var x = a2[0] - a1[0] + o[0];
            var y = a2[1] - a1[1] + o[1];

            if(c){
                            var w = this.getWidth(), h = this.getHeight(), r = el.getRegion();
                            var dw = D.getViewWidth()-5, dh = D.getViewHeight()-5;

                                                    var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);
               var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);
               var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
               var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));

               var doc = document;
               var scrollX = (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0)+5;
               var scrollY = (doc.documentElement.scrollTop || doc.body.scrollTop || 0)+5;

               if((x+w) > dw + scrollX){
                    x = swapX ? r.left-w : dw+scrollX-w;
                }
               if(x < scrollX){
                   x = swapX ? r.right : scrollX;
               }
               if((y+h) > dh + scrollY){
                    y = swapY ? r.top-h : dh+scrollY-h;
                }
               if (y < scrollY){
                   y = swapY ? r.bottom : scrollY;
               }
            }
            return [x,y];
        },

            getConstrainToXY : function(){
            var os = {top:0, left:0, bottom:0, right: 0};

            return function(el, local, offsets, proposedXY){
                el = Ext.get(el);
                offsets = offsets ? Ext.applyIf(offsets, os) : os;

                var vw, vh, vx = 0, vy = 0;
                if(el.dom == document.body || el.dom == document){
                    vw = Ext.lib.Dom.getViewWidth();
                    vh = Ext.lib.Dom.getViewHeight();
                }else{
                    vw = el.dom.clientWidth;
                    vh = el.dom.clientHeight;
                    if(!local){
                        var vxy = el.getXY();
                        vx = vxy[0];
                        vy = vxy[1];
                    }
                }

                var s = el.getScroll();

                vx += offsets.left + s.left;
                vy += offsets.top + s.top;

                vw -= offsets.right;
                vh -= offsets.bottom;

                var vr = vx+vw;
                var vb = vy+vh;

                var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
                var x = xy[0], y = xy[1];
                var w = this.dom.offsetWidth, h = this.dom.offsetHeight;

                            var moved = false;

                            if((x + w) > vr){
                    x = vr - w;
                    moved = true;
                }
                if((y + h) > vb){
                    y = vb - h;
                    moved = true;
                }
                            if(x < vx){
                    x = vx;
                    moved = true;
                }
                if(y < vy){
                    y = vy;
                    moved = true;
                }
                return moved ? [x, y] : false;
            };
        }(),

            adjustForConstraints : function(xy, parent, offsets){
            return this.getConstrainToXY(parent || document, false, offsets, xy) ||  xy;
        },

        alignTo : function(element, position, offsets, animate){
            var xy = this.getAlignToXY(element, position, offsets);
            this.setXY(xy, this.preanim(arguments, 3));
            return this;
        },

        anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
            var action = function(){
                this.alignTo(el, alignment, offsets, animate);
                Ext.callback(callback, this);
            };
            Ext.EventManager.onWindowResize(action, this);
            var tm = typeof monitorScroll;
            if(tm != 'undefined'){
                Ext.EventManager.on(window, 'scroll', action, this,
                    {buffer: tm == 'number' ? monitorScroll : 50});
            }
            action.call(this);         return this;
        },

        clearOpacity : function(){
            if (window.ActiveXObject) {
                if(typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)){
                    this.dom.style.filter = "";
                }
            } else {
                this.dom.style.opacity = "";
                this.dom.style["-moz-opacity"] = "";
                this.dom.style["-khtml-opacity"] = "";
            }
            return this;
        },

        hide : function(animate){
            this.setVisible(false, this.preanim(arguments, 0));
            return this;
        },

        show : function(animate){
            this.setVisible(true, this.preanim(arguments, 0));
            return this;
        },

        addUnits : function(size){
            return Ext.Element.addUnits(size, this.defaultUnit);
        },

        update : function(html, loadScripts, callback){
            if(typeof html == "undefined"){
                html = "";
            }
            if(loadScripts !== true){
                this.dom.innerHTML = html;
                if(typeof callback == "function"){
                    callback();
                }
                return this;
            }
            var id = Ext.id();
            var dom = this.dom;

            html += '';

            E.onAvailable(id, function(){
                var hd = document.getElementsByTagName("head")[0];
                var re = /(?:]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
                var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
                var typeRe = /\stype=([\'\"])(.*?)\1/i;

                var match;
                while(match = re.exec(html)){
                    var attrs = match[1];
                    var srcMatch = attrs ? attrs.match(srcRe) : false;
                    if(srcMatch && srcMatch[2]){
                       var s = document.createElement("script");
                       s.src = srcMatch[2];
                       var typeMatch = attrs.match(typeRe);
                       if(typeMatch && typeMatch[2]){
                           s.type = typeMatch[2];
                       }
                       hd.appendChild(s);
                    }else if(match[2] && match[2].length > 0){
                        if(window.execScript) {
                           window.execScript(match[2]);
                        } else {
                           window.eval(match[2]);
                        }
                    }
                }
                var el = document.getElementById(id);
                if(el){Ext.removeNode(el);}
                if(typeof callback == "function"){
                    callback();
                }
            });
            dom.innerHTML = html.replace(/(?:)((\n|\r|.)*?)(?:<\/script>)/ig, "");
            return this;
        },

        load : function(){
            var um = this.getUpdater();
            um.update.apply(um, arguments);
            return this;
        },

        getUpdater : function(){
            if(!this.updateManager){
                this.updateManager = new Ext.Updater(this);
            }
            return this.updateManager;
        },

        unselectable : function(){
            this.dom.unselectable = "on";
            this.swallowEvent("selectstart", true);
            this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
            this.addClass("x-unselectable");
            return this;
        },

        getCenterXY : function(){
            return this.getAlignToXY(document, 'c-c');
        },

        center : function(centerIn){
            this.alignTo(centerIn || document, 'c-c');
            return this;
        },

        isBorderBox : function(){
            return noBoxAdjust[this.dom.tagName.toLowerCase()] || Ext.isBorderBox;
        },

        getBox : function(contentBox, local){
            var xy;
            if(!local){
                xy = this.getXY();
            }else{
                var left = parseInt(this.getStyle("left"), 10) || 0;
                var top = parseInt(this.getStyle("top"), 10) || 0;
                xy = [left, top];
            }
            var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
            if(!contentBox){
                bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
            }else{
                var l = this.getBorderWidth("l")+this.getPadding("l");
                var r = this.getBorderWidth("r")+this.getPadding("r");
                var t = this.getBorderWidth("t")+this.getPadding("t");
                var b = this.getBorderWidth("b")+this.getPadding("b");
                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)};
            }
            bx.right = bx.x + bx.width;
            bx.bottom = bx.y + bx.height;
            return bx;
        },

        getFrameWidth : function(sides, onlyContentBox){
            return onlyContentBox && Ext.isBorderBox ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
        },

        setBox : function(box, adjust, animate){
            var w = box.width, h = box.height;
            if((adjust && !this.autoBoxAdjust) && !this.isBorderBox()){
               w -= (this.getBorderWidth("lr") + this.getPadding("lr"));
               h -= (this.getBorderWidth("tb") + this.getPadding("tb"));
            }
            this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));
            return this;
        },

         repaint : function(){
            var dom = this.dom;
            this.addClass("x-repaint");
            setTimeout(function(){
                Ext.get(dom).removeClass("x-repaint");
            }, 1);
            return this;
        },

        getMargins : function(side){
            if(!side){
                return {
                    top: parseInt(this.getStyle("margin-top"), 10) || 0,
                    left: parseInt(this.getStyle("margin-left"), 10) || 0,
                    bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,
                    right: parseInt(this.getStyle("margin-right"), 10) || 0
                };
            }else{
                return this.addStyles(side, El.margins);
             }
        },

            addStyles : function(sides, styles){
            var val = 0, v, w;
            for(var i = 0, len = sides.length; i < len; i++){
                v = this.getStyle(styles[sides.charAt(i)]);
                if(v){
                     w = parseInt(v, 10);
                     if(w){ val += (w >= 0 ? w : -1 * w); }
                }
            }
            return val;
        },

        createProxy : function(config, renderTo, matchBox){
            config = typeof config == "object" ?
                config : {tag : "div", cls: config};

            var proxy;
            if(renderTo){
                proxy = Ext.DomHelper.append(renderTo, config, true);
            }else {
                proxy = Ext.DomHelper.insertBefore(this.dom, config, true);
            }
            if(matchBox){
               proxy.setBox(this.getBox());
            }
            return proxy;
        },

        mask : function(msg, msgCls){
            if(this.getStyle("position") == "static"){
                this.setStyle("position", "relative");
            }
            if(this._maskMsg){
                this._maskMsg.remove();
            }
            if(this._mask){
                this._mask.remove();
            }

            this._mask = Ext.DomHelper.append(this.dom, {cls:"ext-el-mask"}, true);

            this.addClass("x-masked");
            this._mask.setDisplayed(true);
            if(typeof msg == 'string'){
                this._maskMsg = Ext.DomHelper.append(this.dom, {cls:"ext-el-mask-msg", cn:{tag:'div'}}, true);
                var mm = this._maskMsg;
                mm.dom.className = msgCls ? "ext-el-mask-msg " + msgCls : "ext-el-mask-msg";
                mm.dom.firstChild.innerHTML = msg;
                mm.setDisplayed(true);
                mm.center(this);
            }
            if(Ext.isIE && !(Ext.isIE7 && Ext.isStrict) && this.getStyle('height') == 'auto'){             this._mask.setSize(this.dom.clientWidth, this.getHeight());
            }
            return this._mask;
        },

        unmask : function(){
            if(this._mask){
                if(this._maskMsg){
                    this._maskMsg.remove();
                    delete this._maskMsg;
                }
                this._mask.remove();
                delete this._mask;
            }
            this.removeClass("x-masked");
        },

        isMasked : function(){
            return this._mask && this._mask.isVisible();
        },

        createShim : function(){
            var el = document.createElement('iframe');
            el.frameBorder = 'no';
            el.className = 'ext-shim';
            if(Ext.isIE && Ext.isSecure){
                el.src = Ext.SSL_SECURE_URL;
            }
            var shim = Ext.get(this.dom.parentNode.insertBefore(el, this.dom));
            shim.autoBoxAdjust = false;
            return shim;
        },

        remove : function(){
            Ext.removeNode(this.dom);
            delete El.cache[this.dom.id];
        },

        hover : function(overFn, outFn, scope){
            var preOverFn = function(e){
                if(!e.within(this, true)){
                    overFn.apply(scope || this, arguments);
                }
            };
            var preOutFn = function(e){
                if(!e.within(this, true)){
                    outFn.apply(scope || this, arguments);
                }
            };
            this.on("mouseover", preOverFn, this.dom);
            this.on("mouseout", preOutFn, this.dom);
            return this;
        },

        addClassOnOver : function(className, preventFlicker){
            this.hover(
                function(){
                    Ext.fly(this, '_internal').addClass(className);
                },
                function(){
                    Ext.fly(this, '_internal').removeClass(className);
                }
            );
            return this;
        },

        addClassOnFocus : function(className){
            this.on("focus", function(){
                Ext.fly(this, '_internal').addClass(className);
            }, this.dom);
            this.on("blur", function(){
                Ext.fly(this, '_internal').removeClass(className);
            }, this.dom);
            return this;
        },

        addClassOnClick : function(className){
            var dom = this.dom;
            this.on("mousedown", function(){
                Ext.fly(dom, '_internal').addClass(className);
                var d = Ext.getDoc();
                var fn = function(){
                    Ext.fly(dom, '_internal').removeClass(className);
                    d.removeListener("mouseup", fn);
                };
                d.on("mouseup", fn);
            });
            return this;
        },

        swallowEvent : function(eventName, preventDefault){
            var fn = function(e){
                e.stopPropagation();
                if(preventDefault){
                    e.preventDefault();
                }
            };
            if(Ext.isArray(eventName)){
                for(var i = 0, len = eventName.length; i < len; i++){
                     this.on(eventName[i], fn);
                }
                return this;
            }
            this.on(eventName, fn);
            return this;
        },

        parent : function(selector, returnDom){
            return this.matchNode('parentNode', 'parentNode', selector, returnDom);
        },

        next : function(selector, returnDom){
            return this.matchNode('nextSibling', 'nextSibling', selector, returnDom);
        },

        prev : function(selector, returnDom){
            return this.matchNode('previousSibling', 'previousSibling', selector, returnDom);
        },

        first : function(selector, returnDom){
            return this.matchNode('nextSibling', 'firstChild', selector, returnDom);
        },

        last : function(selector, returnDom){
            return this.matchNode('previousSibling', 'lastChild', selector, returnDom);
        },

        matchNode : function(dir, start, selector, returnDom){
            var n = this.dom[start];
            while(n){
                if(n.nodeType == 1 && (!selector || Ext.DomQuery.is(n, selector))){
                    return !returnDom ? Ext.get(n) : n;
                }
                n = n[dir];
            }
            return null;
        },

        appendChild: function(el){
            el = Ext.get(el);
            el.appendTo(this);
            return this;
        },

        createChild: function(config, insertBefore, returnDom){
            config = config || {tag:'div'};
            if(insertBefore){
                return Ext.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
            }
            return Ext.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config,  returnDom !== true);
        },

        appendTo: function(el){
            el = Ext.getDom(el);
            el.appendChild(this.dom);
            return this;
        },

        insertBefore: function(el){
            el = Ext.getDom(el);
            el.parentNode.insertBefore(this.dom, el);
            return this;
        },

        insertAfter: function(el){
            el = Ext.getDom(el);
            el.parentNode.insertBefore(this.dom, el.nextSibling);
            return this;
        },

        insertFirst: function(el, returnDom){
            el = el || {};
            if(typeof el == 'object' && !el.nodeType && !el.dom){             return this.createChild(el, this.dom.firstChild, returnDom);
            }else{
                el = Ext.getDom(el);
                this.dom.insertBefore(el, this.dom.firstChild);
                return !returnDom ? Ext.get(el) : el;
            }
        },

        insertSibling: function(el, where, returnDom){
            var rt;
            if(Ext.isArray(el)){
                for(var i = 0, len = el.length; i < len; i++){
                    rt = this.insertSibling(el[i], where, returnDom);
                }
                return rt;
            }
            where = where ? where.toLowerCase() : 'before';
            el = el || {};
            var refNode = where == 'before' ? this.dom : this.dom.nextSibling;

            if(typeof el == 'object' && !el.nodeType && !el.dom){             if(where == 'after' && !this.dom.nextSibling){
                    rt = Ext.DomHelper.append(this.dom.parentNode, el, !returnDom);
                }else{
                    rt = Ext.DomHelper[where == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !returnDom);
                }

            }else{
                rt = this.dom.parentNode.insertBefore(Ext.getDom(el), refNode);
                if(!returnDom){
                    rt = Ext.get(rt);
                }
            }
            return rt;
        },

        wrap: function(config, returnDom){
            if(!config){
                config = {tag: "div"};
            }
            var newEl = Ext.DomHelper.insertBefore(this.dom, config, !returnDom);
            newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
            return newEl;
        },

        replace: function(el){
            el = Ext.get(el);
            this.insertBefore(el);
            el.remove();
            return this;
        },

        replaceWith: function(el){
            if(typeof el == 'object' && !el.nodeType && !el.dom){             el = this.insertSibling(el, 'before');
            }else{
                el = Ext.getDom(el);
                this.dom.parentNode.insertBefore(el, this.dom);
            }
            El.uncache(this.id);
            this.dom.parentNode.removeChild(this.dom);
            this.dom = el;
            this.id = Ext.id(el);
            El.cache[this.id] = this;
            return this;
        },

        insertHtml : function(where, html, returnEl){
            var el = Ext.DomHelper.insertHtml(where, this.dom, html);
            return returnEl ? Ext.get(el) : el;
        },

        set : function(o, useSet){
            var el = this.dom;
            useSet = typeof useSet == 'undefined' ? (el.setAttribute ? true : false) : useSet;
            for(var attr in o){
                if(attr == "style" || typeof o[attr] == "function") continue;
                if(attr=="cls"){
                    el.className = o["cls"];
                }else if(o.hasOwnProperty(attr)){
                    if(useSet) el.setAttribute(attr, o[attr]);
                    else el[attr] = o[attr];
                }
            }
            if(o.style){
                Ext.DomHelper.applyStyles(el, o.style);
            }
            return this;
        },

        addKeyListener : function(key, fn, scope){
            var config;
            if(typeof key != "object" || Ext.isArray(key)){
                config = {
                    key: key,
                    fn: fn,
                    scope: scope
                };
            }else{
                config = {
                    key : key.key,
                    shift : key.shift,
                    ctrl : key.ctrl,
                    alt : key.alt,
                    fn: fn,
                    scope: scope
                };
            }
            return new Ext.KeyMap(this, config);
        },

        addKeyMap : function(config){
            return new Ext.KeyMap(this, config);
        },

         isScrollable : function(){
            var dom = this.dom;
            return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
        },

        scrollTo : function(side, value, animate){
            var prop = side.toLowerCase() == "left" ? "scrollLeft" : "scrollTop";
            if(!animate || !A){
                this.dom[prop] = value;
            }else{
                var to = prop == "scrollLeft" ? [value, this.dom.scrollTop] : [this.dom.scrollLeft, value];
                this.anim({scroll: {"to": to}}, this.preanim(arguments, 2), 'scroll');
            }
            return this;
        },

         scroll : function(direction, distance, animate){
             if(!this.isScrollable()){
                 return;
             }
             var el = this.dom;
             var l = el.scrollLeft, t = el.scrollTop;
             var w = el.scrollWidth, h = el.scrollHeight;
             var cw = el.clientWidth, ch = el.clientHeight;
             direction = direction.toLowerCase();
             var scrolled = false;
             var a = this.preanim(arguments, 2);
             switch(direction){
                 case "l":
                 case "left":
                     if(w - l > cw){
                         var v = Math.min(l + distance, w-cw);
                         this.scrollTo("left", v, a);
                         scrolled = true;
                     }
                     break;
                case "r":
                case "right":
                     if(l > 0){
                         var v = Math.max(l - distance, 0);
                         this.scrollTo("left", v, a);
                         scrolled = true;
                     }
                     break;
                case "t":
                case "top":
                case "up":
                     if(t > 0){
                         var v = Math.max(t - distance, 0);
                         this.scrollTo("top", v, a);
                         scrolled = true;
                     }
                     break;
                case "b":
                case "bottom":
                case "down":
                     if(h - t > ch){
                         var v = Math.min(t + distance, h-ch);
                         this.scrollTo("top", v, a);
                         scrolled = true;
                     }
                     break;
             }
             return scrolled;
        },

        translatePoints : function(x, y){
            if(typeof x == 'object' || Ext.isArray(x)){
                y = x[1]; x = x[0];
            }
            var p = this.getStyle('position');
            var o = this.getXY();

            var l = parseInt(this.getStyle('left'), 10);
            var t = parseInt(this.getStyle('top'), 10);

            if(isNaN(l)){
                l = (p == "relative") ? 0 : this.dom.offsetLeft;
            }
            if(isNaN(t)){
                t = (p == "relative") ? 0 : this.dom.offsetTop;
            }

            return {left: (x - o[0] + l), top: (y - o[1] + t)};
        },

        getScroll : function(){
            var d = this.dom, doc = document;
            if(d == doc || d == doc.body){
                var l, t;
                if(Ext.isIE && Ext.isStrict){
                    l = doc.documentElement.scrollLeft || (doc.body.scrollLeft || 0);
                    t = doc.documentElement.scrollTop || (doc.body.scrollTop || 0);
                }else{
                    l = window.pageXOffset || (doc.body.scrollLeft || 0);
                    t = window.pageYOffset || (doc.body.scrollTop || 0);
                }
                return {left: l, top: t};
            }else{
                return {left: d.scrollLeft, top: d.scrollTop};
            }
        },

        getColor : function(attr, defaultValue, prefix){
            var v = this.getStyle(attr);
            if(!v || v == "transparent" || v == "inherit") {
                return defaultValue;
            }
            var color = typeof prefix == "undefined" ? "#" : prefix;
            if(v.substr(0, 4) == "rgb("){
                var rvs = v.slice(4, v.length -1).split(",");
                for(var i = 0; i < 3; i++){
                    var h = parseInt(rvs[i]);
                    var s = h.toString(16);
                    if(h < 16){
                        s = "0" + s;
                    }
                    color += s;
                }
            } else {
                if(v.substr(0, 1) == "#"){
                    if(v.length == 4) {
                        for(var i = 1; i < 4; i++){
                            var c = v.charAt(i);
                            color +=  c + c;
                        }
                    }else if(v.length == 7){
                        color += v.substr(1);
                    }
                }
            }
            return(color.length > 5 ? color.toLowerCase() : defaultValue);
        },

        boxWrap : function(cls){
            cls = cls || 'x-box';
            var el = Ext.get(this.insertHtml('beforeBegin', String.format(''+El.boxMarkup+'', cls)));
            el.child('.'+cls+'-mc').dom.appendChild(this.dom);
            return el;
        },

        getAttributeNS : Ext.isIE ? function(ns, name){
            var d = this.dom;
            var type = typeof d[ns+":"+name];
            if(type != 'undefined' && type != 'unknown'){
                return d[ns+":"+name];
            }
            return d[name];
        } : function(ns, name){
            var d = this.dom;
            return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];
        },

        getTextWidth : function(text, min, max){
            return (Ext.util.TextMetrics.measure(this.dom, Ext.value(text, this.dom.innerHTML, true)).width).constrain(min || 0, max || 1000000);
        }
    };

    var ep = El.prototype;

    ep.on = ep.addListener;
        ep.mon = ep.addListener;

    ep.getUpdateManager = ep.getUpdater;

    ep.un = ep.removeListener;

    ep.autoBoxAdjust = true;

    El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;

    El.addUnits = function(v, defaultUnit){
        if(v === "" || v == "auto"){
            return v;
        }
        if(v === undefined){
            return '';
        }
        if(typeof v == "number" || !El.unitPattern.test(v)){
            return v + (defaultUnit || 'px');
        }
        return v;
    };

    El.boxMarkup = '';

    El.VISIBILITY = 1;

    El.DISPLAY = 2;

    El.borders = {l: "border-left-width", r: "border-right-width", t: "border-top-width", b: "border-bottom-width"};
    El.paddings = {l: "padding-left", r: "padding-right", t: "padding-top", b: "padding-bottom"};
    El.margins = {l: "margin-left", r: "margin-right", t: "margin-top", b: "margin-bottom"};

    El.cache = {};

    var docEl;

    El.get = function(el){
        var ex, elm, id;
        if(!el){ return null; }
        if(typeof el == "string"){         if(!(elm = document.getElementById(el))){
                return null;
            }
            if(ex = El.cache[el]){
                ex.dom = elm;
            }else{
                ex = El.cache[el] = new El(elm);
            }
            return ex;
        }else if(el.tagName){         if(!(id = el.id)){
                id = Ext.id(el);
            }
            if(ex = El.cache[id]){
                ex.dom = el;
            }else{
                ex = El.cache[id] = new El(el);
            }
            return ex;
        }else if(el instanceof El){
            if(el != docEl){
                el.dom = document.getElementById(el.id) || el.dom;                                                                       El.cache[el.id] = el;         }
            return el;
        }else if(el.isComposite){
            return el;
        }else if(Ext.isArray(el)){
            return El.select(el);
        }else if(el == document){
                    if(!docEl){
                var f = function(){};
                f.prototype = El.prototype;
                docEl = new f();
                docEl.dom = document;
            }
            return docEl;
        }
        return null;
    };

    El.uncache = function(el){
        for(var i = 0, a = arguments, len = a.length; i < len; i++) {
            if(a[i]){
                delete El.cache[a[i].id || a[i]];
            }
        }
    };

    El.garbageCollect = function(){
        if(!Ext.enableGarbageCollector){
            clearInterval(El.collectorThread);
            return;
        }
        for(var eid in El.cache){
            var el = El.cache[eid], d = el.dom;
                                                                                                                                                    if(!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))){
                delete El.cache[eid];
                if(d && Ext.enableListenerCollection){
                    E.purgeElement(d);
                }
            }
        }
    }
    El.collectorThreadId = setInterval(El.garbageCollect, 30000);

    var flyFn = function(){};
    flyFn.prototype = El.prototype;
    var _cls = new flyFn();

    El.Flyweight = function(dom){
        this.dom = dom;
    };

    El.Flyweight.prototype = _cls;
    El.Flyweight.prototype.isFlyweight = true;

    El._flyweights = {};

    El.fly = function(el, named){
        named = named || '_global';
        el = Ext.getDom(el);
        if(!el){
            return null;
        }
        if(!El._flyweights[named]){
            El._flyweights[named] = new El.Flyweight();
        }
        El._flyweights[named].dom = el;
        return El._flyweights[named];
    };

    Ext.get = El.get;

    Ext.fly = El.fly;

    var noBoxAdjust = Ext.isStrict ? {
        select:1
    } : {
        input:1, select:1, textarea:1
    };
    if(Ext.isIE || Ext.isGecko){
        noBoxAdjust['button'] = 1;
    }

    Ext.EventManager.on(window, 'unload', function(){
        delete El.cache;
        delete El._flyweights;
    });
    })();

    Ext.enableFx = true;

    Ext.Fx = {

        slideIn : function(anchor, o){
            var el = this.getFxEl();
            o = o || {};

            el.queueFx(o, function(){

                anchor = anchor || "t";

                            this.fixDisplay();

                            var r = this.getFxRestore();
                var b = this.getBox();
                            this.setSize(b);

                            var wrap = this.fxWrap(r.pos, o, "hidden");

                var st = this.dom.style;
                st.visibility = "visible";
                st.position = "absolute";

                            var after = function(){
                    el.fxUnwrap(wrap, r.pos, o);
                    st.width = r.width;
                    st.height = r.height;
                    el.afterFx(o);
                };
                            var a, pt = {to: [b.x, b.y]}, bw = {to: b.width}, bh = {to: b.height};

                switch(anchor.toLowerCase()){
                    case "t":
                        wrap.setSize(b.width, 0);
                        st.left = st.bottom = "0";
                        a = {height: bh};
                    break;
                    case "l":
                        wrap.setSize(0, b.height);
                        st.right = st.top = "0";
                        a = {width: bw};
                    break;
                    case "r":
                        wrap.setSize(0, b.height);
                        wrap.setX(b.right);
                        st.left = st.top = "0";
                        a = {width: bw, points: pt};
                    break;
                    case "b":
                        wrap.setSize(b.width, 0);
                        wrap.setY(b.bottom);
                        st.left = st.top = "0";
                        a = {height: bh, points: pt};
                    break;
                    case "tl":
                        wrap.setSize(0, 0);
                        st.right = st.bottom = "0";
                        a = {width: bw, height: bh};
                    break;
                    case "bl":
                        wrap.setSize(0, 0);
                        wrap.setY(b.y+b.height);
                        st.right = st.top = "0";
                        a = {width: bw, height: bh, points: pt};
                    break;
                    case "br":
                        wrap.setSize(0, 0);
                        wrap.setXY([b.right, b.bottom]);
                        st.left = st.top = "0";
                        a = {width: bw, height: bh, points: pt};
                    break;
                    case "tr":
                        wrap.setSize(0, 0);
                        wrap.setX(b.x+b.width);
                        st.left = st.bottom = "0";
                        a = {width: bw, height: bh, points: pt};
                    break;
                }
                this.dom.style.visibility = "visible";
                wrap.show();

                arguments.callee.anim = wrap.fxanim(a,
                    o,
                    'motion',
                    .5,
                    'easeOut', after);
            });
            return this;
        },

        slideOut : function(anchor, o){
            var el = this.getFxEl();
            o = o || {};

            el.queueFx(o, function(){

                anchor = anchor || "t";

                            var r = this.getFxRestore();

                var b = this.getBox();
                            this.setSize(b);

                            var wrap = this.fxWrap(r.pos, o, "visible");

                var st = this.dom.style;
                st.visibility = "visible";
                st.position = "absolute";

                wrap.setSize(b);

                var after = function(){
                    if(o.useDisplay){
                        el.setDisplayed(false);
                    }else{
                        el.hide();
                    }

                    el.fxUnwrap(wrap, r.pos, o);

                    st.width = r.width;
                    st.height = r.height;

                    el.afterFx(o);
                };

                var a, zero = {to: 0};
                switch(anchor.toLowerCase()){
                    case "t":
                        st.left = st.bottom = "0";
                        a = {height: zero};
                    break;
                    case "l":
                        st.right = st.top = "0";
                        a = {width: zero};
                    break;
                    case "r":
                        st.left = st.top = "0";
                        a = {width: zero, points: {to:[b.right, b.y]}};
                    break;
                    case "b":
                        st.left = st.top = "0";
                        a = {height: zero, points: {to:[b.x, b.bottom]}};
                    break;
                    case "tl":
                        st.right = st.bottom = "0";
                        a = {width: zero, height: zero};
                    break;
                    case "bl":
                        st.right = st.top = "0";
                        a = {width: zero, height: zero, points: {to:[b.x, b.bottom]}};
                    break;
                    case "br":
                        st.left = st.top = "0";
                        a = {width: zero, height: zero, points: {to:[b.x+b.width, b.bottom]}};
                    break;
                    case "tr":
                        st.left = st.bottom = "0";
                        a = {width: zero, height: zero, points: {to:[b.right, b.y]}};
                    break;
                }

                arguments.callee.anim = wrap.fxanim(a,
                    o,
                    'motion',
                    .5,
                    "easeOut", after);
            });
            return this;
        },

        puff : function(o){
            var el = this.getFxEl();
            o = o || {};

            el.queueFx(o, function(){
                this.clearOpacity();
                this.show();

                            var r = this.getFxRestore();
                var st = this.dom.style;

                var after = function(){
                    if(o.useDisplay){
                        el.setDisplayed(false);
                    }else{
                        el.hide();
                    }

                    el.clearOpacity();

                    el.setPositioning(r.pos);
                    st.width = r.width;
                    st.height = r.height;
                    st.fontSize = '';
                    el.afterFx(o);
                };

                var width = this.getWidth();
                var height = this.getHeight();

                arguments.callee.anim = this.fxanim({
                        width : {to: this.adjustWidth(width * 2)},
                        height : {to: this.adjustHeight(height * 2)},
                        points : {by: [-(width * .5), -(height * .5)]},
                        opacity : {to: 0},
                        fontSize: {to:200, unit: "%"}
                    },
                    o,
                    'motion',
                    .5,
                    "easeOut", after);
            });
            return this;
        },

        switchOff : function(o){
            var el = this.getFxEl();
            o = o || {};

            el.queueFx(o, function(){
                this.clearOpacity();
                this.clip();

                            var r = this.getFxRestore();
                var st = this.dom.style;

                var after = function(){
                    if(o.useDisplay){
                        el.setDisplayed(false);
                    }else{
                        el.hide();
                    }

                    el.clearOpacity();
                    el.setPositioning(r.pos);
                    st.width = r.width;
                    st.height = r.height;

                    el.afterFx(o);
                };

                this.fxanim({opacity:{to:0.3}}, null, null, .1, null, function(){
                    this.clearOpacity();
                    (function(){
                        this.fxanim({
                            height:{to:1},
                            points:{by:[0, this.getHeight() * .5]}
                        }, o, 'motion', 0.3, 'easeIn', after);
                    }).defer(100, this);
                });
            });
            return this;
        },

        highlight : function(color, o){
            var el = this.getFxEl();
            o = o || {};

            el.queueFx(o, function(){
                color = color || "ffff9c";
                var attr = o.attr || "backgroundColor";

                this.clearOpacity();
                this.show();

                var origColor = this.getColor(attr);
                var restoreColor = this.dom.style[attr];
                var endColor = (o.endColor || origColor) || "ffffff";

                var after = function(){
                    el.dom.style[attr] = restoreColor;
                    el.afterFx(o);
                };

                var a = {};
                a[attr] = {from: color, to: endColor};
                arguments.callee.anim = this.fxanim(a,
                    o,
                    'color',
                    1,
                    'easeIn', after);
            });
            return this;
        },

        frame : function(color, count, o){
            var el = this.getFxEl();
            o = o || {};

            el.queueFx(o, function(){
                color = color || "#C3DAF9";
                if(color.length == 6){
                    color = "#" + color;
                }
                count = count || 1;
                var duration = o.duration || 1;
                this.show();

                var b = this.getBox();
                var animFn = function(){
                    var proxy = Ext.getBody().createChild({
                         style:{
                            visbility:"hidden",
                            position:"absolute",
                            "z-index":"35000",                         border:"0px solid " + color
                         }
                      });
                    var scale = Ext.isBorderBox ? 2 : 1;
                    proxy.animate({
                        top:{from:b.y, to:b.y - 20},
                        left:{from:b.x, to:b.x - 20},
                        borderWidth:{from:0, to:10},
                        opacity:{from:1, to:0},
                        height:{from:b.height, to:(b.height + (20*scale))},
                        width:{from:b.width, to:(b.width + (20*scale))}
                    }, duration, function(){
                        proxy.remove();
                        if(--count > 0){
                             animFn();
                        }else{
                            el.afterFx(o);
                        }
                    });
                };
                animFn.call(this);
            });
            return this;
        },

        pause : function(seconds){
            var el = this.getFxEl();
            var o = {};

            el.queueFx(o, function(){
                setTimeout(function(){
                    el.afterFx(o);
                }, seconds * 1000);
            });
            return this;
        },

        fadeIn : function(o){
            var el = this.getFxEl();
            o = o || {};
            el.queueFx(o, function(){
                this.setOpacity(0);
                this.fixDisplay();
                this.dom.style.visibility = 'visible';
                var to = o.endOpacity || 1;
                arguments.callee.anim = this.fxanim({opacity:{to:to}},
                    o, null, .5, "easeOut", function(){
                    if(to == 1){
                        this.clearOpacity();
                    }
                    el.afterFx(o);
                });
            });
            return this;
        },

        fadeOut : function(o){
            var el = this.getFxEl();
            o = o || {};
            el.queueFx(o, function(){
                arguments.callee.anim = this.fxanim({opacity:{to:o.endOpacity || 0}},
                    o, null, .5, "easeOut", function(){
                    if(this.visibilityMode == Ext.Element.DISPLAY || o.useDisplay){
                         this.dom.style.display = "none";
                    }else{
                         this.dom.style.visibility = "hidden";
                    }
                    this.clearOpacity();
                    el.afterFx(o);
                });
            });
            return this;
        },

        scale : function(w, h, o){
            this.shift(Ext.apply({}, o, {
                width: w,
                height: h
            }));
            return this;
        },

        shift : function(o){
            var el = this.getFxEl();
            o = o || {};
            el.queueFx(o, function(){
                var a = {}, w = o.width, h = o.height, x = o.x, y = o.y,  op = o.opacity;
                if(w !== undefined){
                    a.width = {to: this.adjustWidth(w)};
                }
                if(h !== undefined){
                    a.height = {to: this.adjustHeight(h)};
                }
                if(x !== undefined || y !== undefined){
                    a.points = {to: [
                        x !== undefined ? x : this.getX(),
                        y !== undefined ? y : this.getY()
                    ]};
                }
                if(op !== undefined){
                    a.opacity = {to: op};
                }
                if(o.xy !== undefined){
                    a.points = {to: o.xy};
                }
                arguments.callee.anim = this.fxanim(a,
                    o, 'motion', .35, "easeOut", function(){
                    el.afterFx(o);
                });
            });
            return this;
        },

        ghost : function(anchor, o){
            var el = this.getFxEl();
            o = o || {};

            el.queueFx(o, function(){
                anchor = anchor || "b";

                            var r = this.getFxRestore();
                var w = this.getWidth(),
                    h = this.getHeight();

                var st = this.dom.style;

                var after = function(){
                    if(o.useDisplay){
                        el.setDisplayed(false);
                    }else{
                        el.hide();
                    }

                    el.clearOpacity();
                    el.setPositioning(r.pos);
                    st.width = r.width;
                    st.height = r.height;

                    el.afterFx(o);
                };

                var a = {opacity: {to: 0}, points: {}}, pt = a.points;
                switch(anchor.toLowerCase()){
                    case "t":
                        pt.by = [0, -h];
                    break;
                    case "l":
                        pt.by = [-w, 0];
                    break;
                    case "r":
                        pt.by = [w, 0];
                    break;
                    case "b":
                        pt.by = [0, h];
                    break;
                    case "tl":
                        pt.by = [-w, -h];
                    break;
                    case "bl":
                        pt.by = [-w, h];
                    break;
                    case "br":
                        pt.by = [w, h];
                    break;
                    case "tr":
                        pt.by = [w, -h];
                    break;
                }

                arguments.callee.anim = this.fxanim(a,
                    o,
                    'motion',
                    .5,
                    "easeOut", after);
            });
            return this;
        },

        syncFx : function(){
            this.fxDefaults = Ext.apply(this.fxDefaults || {}, {
                block : false,
                concurrent : true,
                stopFx : false
            });
            return this;
        },

        sequenceFx : function(){
            this.fxDefaults = Ext.apply(this.fxDefaults || {}, {
                block : false,
                concurrent : false,
                stopFx : false
            });
            return this;
        },

        nextFx : function(){
            var ef = this.fxQueue[0];
            if(ef){
                ef.call(this);
            }
        },

        hasActiveFx : function(){
            return this.fxQueue && this.fxQueue[0];
        },

        stopFx : function(){
            if(this.hasActiveFx()){
                var cur = this.fxQueue[0];
                if(cur && cur.anim && cur.anim.isAnimated()){
                    this.fxQueue = [cur];                 cur.anim.stop(true);
                }
            }
            return this;
        },

        beforeFx : function(o){
            if(this.hasActiveFx() && !o.concurrent){
               if(o.stopFx){
                   this.stopFx();
                   return true;
               }
               return false;
            }
            return true;
        },

        hasFxBlock : function(){
            var q = this.fxQueue;
            return q && q[0] && q[0].block;
        },

        queueFx : function(o, fn){
            if(!this.fxQueue){
                this.fxQueue = [];
            }
            if(!this.hasFxBlock()){
                Ext.applyIf(o, this.fxDefaults);
                if(!o.concurrent){
                    var run = this.beforeFx(o);
                    fn.block = o.block;
                    this.fxQueue.push(fn);
                    if(run){
                        this.nextFx();
                    }
                }else{
                    fn.call(this);
                }
            }
            return this;
        },

        fxWrap : function(pos, o, vis){
            var wrap;
            if(!o.wrap || !(wrap = Ext.get(o.wrap))){
                var wrapXY;
                if(o.fixPosition){
                    wrapXY = this.getXY();
                }
                var div = document.createElement("div");
                div.style.visibility = vis;
                wrap = Ext.get(this.dom.parentNode.insertBefore(div, this.dom));
                wrap.setPositioning(pos);
                if(wrap.getStyle("position") == "static"){
                    wrap.position("relative");
                }
                this.clearPositioning('auto');
                wrap.clip();
                wrap.dom.appendChild(this.dom);
                if(wrapXY){
                    wrap.setXY(wrapXY);
                }
            }
            return wrap;
        },

        fxUnwrap : function(wrap, pos, o){
            this.clearPositioning();
            this.setPositioning(pos);
            if(!o.wrap){
                wrap.dom.parentNode.insertBefore(this.dom, wrap.dom);
                wrap.remove();
            }
        },

        getFxRestore : function(){
            var st = this.dom.style;
            return {pos: this.getPositioning(), width: st.width, height : st.height};
        },

        afterFx : function(o){
            if(o.afterStyle){
                this.applyStyles(o.afterStyle);
            }
            if(o.afterCls){
                this.addClass(o.afterCls);
            }
            if(o.remove === true){
                this.remove();
            }
            Ext.callback(o.callback, o.scope, [this]);
            if(!o.concurrent){
                this.fxQueue.shift();
                this.nextFx();
            }
        },

        getFxEl : function(){         return Ext.get(this.dom);
        },

        fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
            animType = animType || 'run';
            opt = opt || {};
            var anim = Ext.lib.Anim[animType](
                this.dom, args,
                (opt.duration || defaultDur) || .35,
                (opt.easing || defaultEase) || 'easeOut',
                function(){
                    Ext.callback(cb, this);
                },
                this
            );
            opt.anim = anim;
            return anim;
        }
    };

    Ext.Fx.resize = Ext.Fx.scale;

    Ext.apply(Ext.Element.prototype, Ext.Fx);

    Ext.CompositeElement = function(els){
        this.elements = [];
        this.addElements(els);
    };
    Ext.CompositeElement.prototype = {
        isComposite: true,
        addElements : function(els){
            if(!els) return this;
            if(typeof els == "string"){
                els = Ext.Element.selectorFunction(els);
            }
            var yels = this.elements;
            var index = yels.length-1;
            for(var i = 0, len = els.length; i < len; i++) {
            	yels[++index] = Ext.get(els[i]);
            }
            return this;
        },

        fill : function(els){
            this.elements = [];
            this.add(els);
            return this;
        },

        filter : function(selector){
            var els = [];
            this.each(function(el){
                if(el.is(selector)){
                    els[els.length] = el.dom;
                }
            });
            this.fill(els);
            return this;
        },

        invoke : function(fn, args){
            var els = this.elements;
            for(var i = 0, len = els.length; i < len; i++) {
            	Ext.Element.prototype[fn].apply(els[i], args);
            }
            return this;
        },

        add : function(els){
            if(typeof els == "string"){
                this.addElements(Ext.Element.selectorFunction(els));
            }else if(els.length !== undefined){
                this.addElements(els);
            }else{
                this.addElements([els]);
            }
            return this;
        },

        each : function(fn, scope){
            var els = this.elements;
            for(var i = 0, len = els.length; i < len; i++){
                if(fn.call(scope || els[i], els[i], this, i) === false) {
                    break;
                }
            }
            return this;
        },

        item : function(index){
            return this.elements[index] || null;
        },

        first : function(){
            return this.item(0);
        },

        last : function(){
            return this.item(this.elements.length-1);
        },

        getCount : function(){
            return this.elements.length;
        },

        contains : function(el){
            return this.indexOf(el) !== -1;
        },

        indexOf : function(el){
            return this.elements.indexOf(Ext.get(el));
        },

        removeElement : function(el, removeDom){
            if(Ext.isArray(el)){
                for(var i = 0, len = el.length; i < len; i++){
                    this.removeElement(el[i]);
                }
                return this;
            }
            var index = typeof el == 'number' ? el : this.indexOf(el);
            if(index !== -1 && this.elements[index]){
                if(removeDom){
                    var d = this.elements[index];
                    if(d.dom){
                        d.remove();
                    }else{
                        Ext.removeNode(d);
                    }
                }
                this.elements.splice(index, 1);
            }
            return this;
        },

        replaceElement : function(el, replacement, domReplace){
            var index = typeof el == 'number' ? el : this.indexOf(el);
            if(index !== -1){
                if(domReplace){
                    this.elements[index].replaceWith(replacement);
                }else{
                    this.elements.splice(index, 1, Ext.get(replacement))
                }
            }
            return this;
        },

        clear : function(){
            this.elements = [];
        }
    };
    (function(){
    Ext.CompositeElement.createCall = function(proto, fnName){
        if(!proto[fnName]){
            proto[fnName] = function(){
                return this.invoke(fnName, arguments);
            };
        }
    };
    for(var fnName in Ext.Element.prototype){
        if(typeof Ext.Element.prototype[fnName] == "function"){
            Ext.CompositeElement.createCall(Ext.CompositeElement.prototype, fnName);
        }
    };
    })();

    Ext.CompositeElementLite = function(els){
        Ext.CompositeElementLite.superclass.constructor.call(this, els);
        this.el = new Ext.Element.Flyweight();
    };
    Ext.extend(Ext.CompositeElementLite, Ext.CompositeElement, {
        addElements : function(els){
            if(els){
                if(Ext.isArray(els)){
                    this.elements = this.elements.concat(els);
                }else{
                    var yels = this.elements;
                    var index = yels.length-1;
                    for(var i = 0, len = els.length; i < len; i++) {
                        yels[++index] = els[i];
                    }
                }
            }
            return this;
        },
        invoke : function(fn, args){
            var els = this.elements;
            var el = this.el;
            for(var i = 0, len = els.length; i < len; i++) {
                el.dom = els[i];
            	Ext.Element.prototype[fn].apply(el, args);
            }
            return this;
        },

        item : function(index){
            if(!this.elements[index]){
                return null;
            }
            this.el.dom = this.elements[index];
            return this.el;
        },

        addListener : function(eventName, handler, scope, opt){
            var els = this.elements;
            for(var i = 0, len = els.length; i < len; i++) {
                Ext.EventManager.on(els[i], eventName, handler, scope || els[i], opt);
            }
            return this;
        },

        each : function(fn, scope){
            var els = this.elements;
            var el = this.el;
            for(var i = 0, len = els.length; i < len; i++){
                el.dom = els[i];
            	if(fn.call(scope || el, el, this, i) === false){
                    break;
                }
            }
            return this;
        },

        indexOf : function(el){
            return this.elements.indexOf(Ext.getDom(el));
        },

        replaceElement : function(el, replacement, domReplace){
            var index = typeof el == 'number' ? el : this.indexOf(el);
            if(index !== -1){
                replacement = Ext.getDom(replacement);
                if(domReplace){
                    var d = this.elements[index];
                    d.parentNode.insertBefore(replacement, d);
                    Ext.removeNode(d);
                }
                this.elements.splice(index, 1, replacement);
            }
            return this;
        }
    });
    Ext.CompositeElementLite.prototype.on = Ext.CompositeElementLite.prototype.addListener;
    if(Ext.DomQuery){
        Ext.Element.selectorFunction = Ext.DomQuery.select;
    }

    Ext.Element.select = function(selector, unique, root){
        var els;
        if(typeof selector == "string"){
            els = Ext.Element.selectorFunction(selector, root);
        }else if(selector.length !== undefined){
            els = selector;
        }else{
            throw "Invalid selector";
        }
        if(unique === true){
            return new Ext.CompositeElement(els);
        }else{
            return new Ext.CompositeElementLite(els);
        }
    };

    Ext.select = Ext.Element.select;

    Ext.data.Connection = function(config){
        Ext.apply(this, config);
        this.addEvents(

            "beforerequest",

            "requestcomplete",

            "requestexception"
        );
        Ext.data.Connection.superclass.constructor.call(this);
    };

    Ext.extend(Ext.data.Connection, Ext.util.Observable, {

        timeout : 30000,

        autoAbort:false,

        disableCaching: true,

        request : function(o){
            if(this.fireEvent("beforerequest", this, o) !== false){
                var p = o.params;

                if(typeof p == "function"){
                    p = p.call(o.scope||window, o);
                }
                if(typeof p == "object"){
                    p = Ext.urlEncode(p);
                }
                if(this.extraParams){
                    var extras = Ext.urlEncode(this.extraParams);
                    p = p ? (p + '&' + extras) : extras;
                }

                var url = o.url || this.url;
                if(typeof url == 'function'){
                    url = url.call(o.scope||window, o);
                }

                if(o.form){
                    var form = Ext.getDom(o.form);
                    url = url || form.action;

                    var enctype = form.getAttribute("enctype");
                    if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
                        return this.doFormUpload(o, p, url);
                    }
                    var f = Ext.lib.Ajax.serializeForm(form);
                    p = p ? (p + '&' + f) : f;
                }

                var hs = o.headers;
                if(this.defaultHeaders){
                    hs = Ext.apply(hs || {}, this.defaultHeaders);
                    if(!o.headers){
                        o.headers = hs;
                    }
                }

                var cb = {
                    success: this.handleResponse,
                    failure: this.handleFailure,
                    scope: this,
                    argument: {options: o},
                    timeout : o.timeout || this.timeout
                };

                var method = o.method||this.method||(p ? "POST" : "GET");

                if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
                    url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime());
                }

                if(typeof o.autoAbort == 'boolean'){
                    if(o.autoAbort){
                        this.abort();
                    }
                }else if(this.autoAbort !== false){
                    this.abort();
                }
                if((method == 'GET' && p) || o.xmlData || o.jsonData){
                    url += (url.indexOf('?') != -1 ? '&' : '?') + p;
                    p = '';
                }
                this.transId = Ext.lib.Ajax.request(method, url, cb, p, o);
                return this.transId;
            }else{
                Ext.callback(o.callback, o.scope, [o, null, null]);
                return null;
            }
        },

        isLoading : function(transId){
            if(transId){
                return Ext.lib.Ajax.isCallInProgress(transId);
            }else{
                return this.transId ? true : false;
            }
        },

        abort : function(transId){
            if(transId || this.isLoading()){
                Ext.lib.Ajax.abort(transId || this.transId);
            }
        },

        handleResponse : function(response){
            this.transId = false;
            var options = response.argument.options;
            response.argument = options ? options.argument : null;
            this.fireEvent("requestcomplete", this, response, options);
            Ext.callback(options.success, options.scope, [response, options]);
            Ext.callback(options.callback, options.scope, [options, true, response]);
        },

        handleFailure : function(response, e){
            this.transId = false;
            var options = response.argument.options;
            response.argument = options ? options.argument : null;
            this.fireEvent("requestexception", this, response, options, e);
            Ext.callback(options.failure, options.scope, [response, options]);
            Ext.callback(options.callback, options.scope, [options, false, response]);
        },

        doFormUpload : function(o, ps, url){
            var id = Ext.id();
            var frame = document.createElement('iframe');
            frame.id = id;
            frame.name = id;
            frame.className = 'x-hidden';
            if(Ext.isIE){
                frame.src = Ext.SSL_SECURE_URL;
            }
            document.body.appendChild(frame);

            if(Ext.isIE){
               document.frames[id].name = id;
            }

            var form = Ext.getDom(o.form);
            form.target = id;
            form.method = 'POST';
            form.enctype = form.encoding = 'multipart/form-data';
            if(url){
                form.action = url;
            }

            var hiddens, hd;
            if(ps){
                hiddens = [];
                ps = Ext.urlDecode(ps, false);
                for(var k in ps){
                    if(ps.hasOwnProperty(k)){
                        hd = document.createElement('input');
                        hd.type = 'hidden';
                        hd.name = k;
                        hd.value = ps[k];
                        form.appendChild(hd);
                        hiddens.push(hd);
                    }
                }
            }

            function cb(){
                var r = {
                    responseText : '',
                    responseXML : null
                };

                r.argument = o ? o.argument : null;

                try {
                    var doc;
                    if(Ext.isIE){
                        doc = frame.contentWindow.document;
                    }else {
                        doc = (frame.contentDocument || window.frames[id].document);
                    }
                    if(doc && doc.body){
                        r.responseText = doc.body.innerHTML;
                    }
                    if(doc && doc.XMLDocument){
                        r.responseXML = doc.XMLDocument;
                    }else {
                        r.responseXML = doc;
                    }
                }
                catch(e) {

                }

                Ext.EventManager.removeListener(frame, 'load', cb, this);

                this.fireEvent("requestcomplete", this, r, o);

                Ext.callback(o.success, o.scope, [r, o]);
                Ext.callback(o.callback, o.scope, [o, true, r]);

                setTimeout(function(){Ext.removeNode(frame);}, 100);
            }

            Ext.EventManager.on(frame, 'load', cb, this);
            form.submit();

            if(hiddens){
                for(var i = 0, len = hiddens.length; i < len; i++){
                    Ext.removeNode(hiddens[i]);
                }
            }
        }
    });

    Ext.Ajax = new Ext.data.Connection({

        autoAbort : false,

        serializeForm : function(form){
            return Ext.lib.Ajax.serializeForm(form);
        }
    });

    Ext.Updater = function(el, forceNew){
        el = Ext.get(el);
        if(!forceNew && el.updateManager){
            return el.updateManager;
        }

        this.el = el;

        this.defaultUrl = null;

        this.addEvents(

            "beforeupdate",

            "update",

            "failure"
        );
        var d = Ext.Updater.defaults;

        this.sslBlankUrl = d.sslBlankUrl;

        this.disableCaching = d.disableCaching;

        this.indicatorText = d.indicatorText;

        this.showLoadIndicator = d.showLoadIndicator;

        this.timeout = d.timeout;

        this.loadScripts = d.loadScripts;

        this.transaction = null;

        this.autoRefreshProcId = null;

        this.refreshDelegate = this.refresh.createDelegate(this);

        this.updateDelegate = this.update.createDelegate(this);

        this.formUpdateDelegate = this.formUpdate.createDelegate(this);

        if(!this.renderer){

        this.renderer = new Ext.Updater.BasicRenderer();
        }
        Ext.Updater.superclass.constructor.call(this);
    };

    Ext.extend(Ext.Updater, Ext.util.Observable, {

        getEl : function(){
            return this.el;
        },

        update : function(url, params, callback, discardUrl){
            if(this.fireEvent("beforeupdate", this.el, url, params) !== false){
                var method = this.method, cfg, callerScope;
                if(typeof url == "object"){
                    cfg = url;
                    url = cfg.url;
                    params = params || cfg.params;
                    callback = callback || cfg.callback;
                    discardUrl = discardUrl || cfg.discardUrl;
    	            callerScope = cfg.scope;
                    if(typeof cfg.method != "undefined"){method = cfg.method;};
                    if(typeof cfg.nocache != "undefined"){this.disableCaching = cfg.nocache;};
                    if(typeof cfg.text != "undefined"){this.indicatorText = ''+cfg.text+"";};
                    if(typeof cfg.scripts != "undefined"){this.loadScripts = cfg.scripts;};
                    if(typeof cfg.timeout != "undefined"){this.timeout = cfg.timeout;};
                }
                this.showLoading();
                if(!discardUrl){
                    this.defaultUrl = url;
                }
                if(typeof url == "function"){
                    url = url.call(this);
                }

                method = method || (params ? "POST" : "GET");
                if(method == "GET"){
                    url = this.prepareUrl(url);
                }

                var o = Ext.apply(cfg ||{}, {
                    url : url,
                    params: (typeof params == "function" && callerScope) ? params.createDelegate(callerScope) : params,
                    success: this.processSuccess,
                    failure: this.processFailure,
                    scope: this,
                    callback: undefined,
                    timeout: (this.timeout*1000),
                    argument: {
                    	"options": cfg,
                    	"url": url,
                    	"form": null,
                    	"callback": callback,
                    	"scope": callerScope || window,
                    	"params": params
                    }
                });

                this.transaction = Ext.Ajax.request(o);
            }
        },

        formUpdate : function(form, url, reset, callback){
            if(this.fireEvent("beforeupdate", this.el, form, url) !== false){
                if(typeof url == "function"){
                    url = url.call(this);
                }
                form = Ext.getDom(form)
                this.transaction = Ext.Ajax.request({
                    form: form,
                    url:url,
                    success: this.processSuccess,
                    failure: this.processFailure,
                    scope: this,
                    timeout: (this.timeout*1000),
                    argument: {
                    	"url": url,
                    	"form": form,
                    	"callback": callback,
                    	"reset": reset
                    }
                });
                this.showLoading.defer(1, this);
            }
        },

        refresh : function(callback){
            if(this.defaultUrl == null){
                return;
            }
            this.update(this.defaultUrl, null, callback, true);
        },

        startAutoRefresh : function(interval, url, params, callback, refreshNow){
            if(refreshNow){
                this.update(url || this.defaultUrl, params, callback, true);
            }
            if(this.autoRefreshProcId){
                clearInterval(this.autoRefreshProcId);
            }
            this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [url || this.defaultUrl, params, callback, true]), interval*1000);
        },

         stopAutoRefresh : function(){
            if(this.autoRefreshProcId){
                clearInterval(this.autoRefreshProcId);
                delete this.autoRefreshProcId;
            }
        },

        isAutoRefreshing : function(){
           return this.autoRefreshProcId ? true : false;
        },

        showLoading : function(){
            if(this.showLoadIndicator){
                this.el.update(this.indicatorText);
            }
        },

        prepareUrl : function(url){
            if(this.disableCaching){
                var append = "_dc=" + (new Date().getTime());
                if(url.indexOf("?") !== -1){
                    url += "&" + append;
                }else{
                    url += "?" + append;
                }
            }
            return url;
        },

        processSuccess : function(response){
            this.transaction = null;
            if(response.argument.form && response.argument.reset){
                try{
                    response.argument.form.reset();
                }catch(e){}
            }
            if(this.loadScripts){
                this.renderer.render(this.el, response, this,
                    this.updateComplete.createDelegate(this, [response]));
            }else{
                this.renderer.render(this.el, response, this);
                this.updateComplete(response);
            }
        },

        updateComplete : function(response){
            this.fireEvent("update", this.el, response);
            if(typeof response.argument.callback == "function"){
                response.argument.callback.call(response.argument.scope, this.el, true, response, response.argument.options);
            }
        },

        processFailure : function(response){
            this.transaction = null;
            this.fireEvent("failure", this.el, response);
            if(typeof response.argument.callback == "function"){
                response.argument.callback.call(response.argument.scope, this.el, false, response, response.argument.options);
            }
        },

        setRenderer : function(renderer){
            this.renderer = renderer;
        },

        getRenderer : function(){
           return this.renderer;
        },

        setDefaultUrl : function(defaultUrl){
            this.defaultUrl = defaultUrl;
        },

        abort : function(){
            if(this.transaction){
                Ext.Ajax.abort(this.transaction);
            }
        },

        isUpdating : function(){
            if(this.transaction){
                return Ext.Ajax.isLoading(this.transaction);
            }
            return false;
        }
    });

       Ext.Updater.defaults = {

             timeout : 30,

            loadScripts : false,

            sslBlankUrl : (Ext.SSL_SECURE_URL || "javascript:false"),

            disableCaching : false,

            showLoadIndicator : true,

            indicatorText : 'Loading...'
       };

    Ext.Updater.updateElement = function(el, url, params, options){
        var um = Ext.get(el).getUpdater();
        Ext.apply(um, options);
        um.update(url, params, options ? options.callback : null);
    };

    Ext.Updater.update = Ext.Updater.updateElement;

    Ext.Updater.BasicRenderer = function(){};

    Ext.Updater.BasicRenderer.prototype = {

         render : function(el, response, updateManager, callback){
            el.update(response.responseText, updateManager.loadScripts, callback);
        }
    };

    Ext.UpdateManager = Ext.Updater;

    Date.parseFunctions = {count:0};
    Date.parseRegexes = [];
    Date.formatFunctions = {count:0};

    Date.prototype.dateFormat = function(format) {
        if (Date.formatFunctions[format] == null) {
            Date.createNewFormat(format);
        }
        var func = Date.formatFunctions[format];
        return this[func]();
    };

    Date.prototype.format = Date.prototype.dateFormat;

    Date.createNewFormat = function(format) {
        var funcName = "format" + Date.formatFunctions.count++;
        Date.formatFunctions[format] = funcName;
        var code = "Date.prototype." + funcName + " = function(){return ";
        var special = false;
        var ch = '';
        for (var i = 0; i < format.length; ++i) {
            ch = format.charAt(i);
            if (!special && ch == "\\") {
                special = true;
            }
            else if (special) {
                special = false;
                code += "'" + String.escape(ch) + "' + ";
            }
            else {
                code += Date.getFormatCode(ch);
            }
        }
        eval(code.substring(0, code.length - 3) + ";}");
    };

    Date.getFormatCode = function(character) {
        switch (character) {
        case "d":
            return "String.leftPad(this.getDate(), 2, '0') + ";
        case "D":
            return "Date.getShortDayName(this.getDay()) + ";     case "j":
            return "this.getDate() + ";
        case "l":
            return "Date.dayNames[this.getDay()] + ";
        case "N":
            return "(this.getDay() ? this.getDay() : 7) + ";
        case "S":
            return "this.getSuffix() + ";
        case "w":
            return "this.getDay() + ";
        case "z":
            return "this.getDayOfYear() + ";
        case "W":
            return "String.leftPad(this.getWeekOfYear(), 2, '0') + ";
        case "F":
            return "Date.monthNames[this.getMonth()] + ";
        case "m":
            return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
        case "M":
            return "Date.getShortMonthName(this.getMonth()) + ";     case "n":
            return "(this.getMonth() + 1) + ";
        case "t":
            return "this.getDaysInMonth() + ";
        case "L":
            return "(this.isLeapYear() ? 1 : 0) + ";
        case "o":
            return "(this.getFullYear() + (this.getWeekOfYear() == 1 && this.getMonth() > 0 ? +1 : (this.getWeekOfYear() >= 52 && this.getMonth() < 11 ? -1 : 0))) + ";
        case "Y":
            return "this.getFullYear() + ";
        case "y":
            return "('' + this.getFullYear()).substring(2, 4) + ";
        case "a":
            return "(this.getHours() < 12 ? 'am' : 'pm') + ";
        case "A":
            return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
        case "g":
            return "((this.getHours() % 12) ? this.getHours() % 12 : 12) + ";
        case "G":
            return "this.getHours() + ";
        case "h":
            return "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0') + ";
        case "H":
            return "String.leftPad(this.getHours(), 2, '0') + ";
        case "i":
            return "String.leftPad(this.getMinutes(), 2, '0') + ";
        case "s":
            return "String.leftPad(this.getSeconds(), 2, '0') + ";
        case "u":
            return "String.leftPad(this.getMilliseconds(), 3, '0') + ";
        case "O":
            return "this.getGMTOffset() + ";
        case "P":
            return "this.getGMTOffset(true) + ";
        case "T":
            return "this.getTimezone() + ";
        case "Z":
            return "(this.getTimezoneOffset() * -60) + ";
        case "c":
            for (var df = Date.getFormatCode, c = "Y-m-dTH:i:sP", code = "", i = 0, l = c.length; i < l; ++i) {
              var e = c.charAt(i);
              code += e == "T" ? "'T' + " : df(e);         }
            return code;
        case "U":
            return "Math.round(this.getTime() / 1000) + ";
        default:
            return "'" + String.escape(character) + "' + ";
        }
    };

    Date.parseDate = function(input, format) {
        if (Date.parseFunctions[format] == null) {
            Date.createParser(format);
        }
        var func = Date.parseFunctions[format];
        return Date[func](input);
    };

    Date.createParser = function(format) {
        var funcName = "parse" + Date.parseFunctions.count++;
        var regexNum = Date.parseRegexes.length;
        var currentGroup = 1;
        Date.parseFunctions[format] = funcName;

        var code = "Date." + funcName + " = function(input){\n"
            + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1, ms = -1, o, z, u, v;\n"
            + "input = String(input);var d = new Date();\n"
            + "y = d.getFullYear();\n"
            + "m = d.getMonth();\n"
            + "d = d.getDate();\n"
            + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
            + "if (results && results.length > 0) {";
        var regex = "";

        var special = false;
        var ch = '';
        for (var i = 0; i < format.length; ++i) {
            ch = format.charAt(i);
            if (!special && ch == "\\") {
                special = true;
            }
            else if (special) {
                special = false;
                regex += String.escape(ch);
            }
            else {
                var obj = Date.formatCodeToRegex(ch, currentGroup);
                currentGroup += obj.g;
                regex += obj.s;
                if (obj.g && obj.c) {
                    code += obj.c;
                }
            }
        }

        code += "if (u)\n"
            + "{v = new Date(u * 1000);}"         + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0 && ms >= 0)\n"
            + "{v = new Date(y, m, d, h, i, s, ms);}\n"
            + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n"
            + "{v = new Date(y, m, d, h, i, s);}\n"
            + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n"
            + "{v = new Date(y, m, d, h, i);}\n"
            + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0)\n"
            + "{v = new Date(y, m, d, h);}\n"
            + "else if (y >= 0 && m >= 0 && d > 0)\n"
            + "{v = new Date(y, m, d);}\n"
            + "else if (y >= 0 && m >= 0)\n"
            + "{v = new Date(y, m);}\n"
            + "else if (y >= 0)\n"
            + "{v = new Date(y);}\n"
            + "}return (v && (z || o))?\n"         + "    (z ? v.add(Date.SECOND, (v.getTimezoneOffset() * 60) + (z*1)) :\n"         + "        v.add(Date.HOUR, (v.getGMTOffset() / 100) + (o / -100))) : v\n"         + ";}";

        Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$", "i");
        eval(code);
    };

    Date.formatCodeToRegex = function(character, currentGroup) {

        switch (character) {
        case "d":
            return {g:1,
                c:"d = parseInt(results[" + currentGroup + "], 10);\n",
                s:"(\\d{2})"};     case "D":
            for (var a = [], i = 0; i < 7; a.push(Date.getShortDayName(i)), ++i);         return {g:0,
                c:null,
                s:"(?:" + a.join("|") +")"};
        case "j":
            return {g:1,
                c:"d = parseInt(results[" + currentGroup + "], 10);\n",
                s:"(\\d{1,2})"};     case "l":
            return {g:0,
                c:null,
                s:"(?:" + Date.dayNames.join("|") + ")"};
        case "N":
            return {g:0,
                c:null,
                s:"[1-7]"};     case "S":
            return {g:0,
                c:null,
                s:"(?:st|nd|rd|th)"};
        case "w":
            return {g:0,
                c:null,
                s:"[0-6]"};     case "z":
            return {g:0,
                c:null,
                s:"(?:\\d{1,3}"};     case "W":
            return {g:0,
                c:null,
                s:"(?:\\d{2})"};     case "F":
            return {g:1,
                c:"m = parseInt(Date.getMonthNumber(results[" + currentGroup + "]), 10);\n",             s:"(" + Date.monthNames.join("|") + ")"};
        case "m":
            return {g:1,
                c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
                s:"(\\d{2})"};     case "M":
            for (var a = [], i = 0; i < 12; a.push(Date.getShortMonthName(i)), ++i);         return {g:1,
                c:"m = parseInt(Date.getMonthNumber(results[" + currentGroup + "]), 10);\n",             s:"(" + a.join("|") + ")"};
        case "n":
            return {g:1,
                c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
                s:"(\\d{1,2})"};     case "t":
            return {g:0,
                c:null,
                s:"(?:\\d{2})"};     case "L":
            return {g:0,
                c:null,
                s:"(?:1|0)"};
        case "o":
        case "Y":
            return {g:1,
                c:"y = parseInt(results[" + currentGroup + "], 10);\n",
                s:"(\\d{4})"};     case "y":
            return {g:1,
                c:"var ty = parseInt(results[" + currentGroup + "], 10);\n"
                    + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
                s:"(\\d{1,2})"};     case "a":
            return {g:1,
                c:"if (results[" + currentGroup + "] == 'am') {\n"
                    + "if (h == 12) { h = 0; }\n"
                    + "} else { if (h < 12) { h += 12; }}",
                s:"(am|pm)"};
        case "A":
            return {g:1,
                c:"if (results[" + currentGroup + "] == 'AM') {\n"
                    + "if (h == 12) { h = 0; }\n"
                    + "} else { if (h < 12) { h += 12; }}",
                s:"(AM|PM)"};
        case "g":
        case "G":
            return {g:1,
                c:"h = parseInt(results[" + currentGroup + "], 10);\n",
                s:"(\\d{1,2})"};     case "h":
        case "H":
            return {g:1,
                c:"h = parseInt(results[" + currentGroup + "], 10);\n",
                s:"(\\d{2})"};     case "i":
            return {g:1,
                c:"i = parseInt(results[" + currentGroup + "], 10);\n",
                s:"(\\d{2})"};     case "s":
            return {g:1,
                c:"s = parseInt(results[" + currentGroup + "], 10);\n",
                s:"(\\d{2})"};     case "u":
            return {g:1,
                c:"ms = parseInt(results[" + currentGroup + "], 10);\n",
                s:"(\\d{3})"};     case "O":
            return {g:1,
                c:[
                    "o = results[", currentGroup, "];\n",
                    "var sn = o.substring(0,1);\n",                 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60);\n",                 "var mn = o.substring(3,5) % 60;\n",                 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n",                 "    (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n"
                ].join(""),
                s: "([+\-]\\d{4})"};     case "P":
            return {g:1,
                c:[
                    "o = results[", currentGroup, "];\n",
                    "var sn = o.substring(0,1);\n",                 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60);\n",                 "var mn = o.substring(4,6) % 60;\n",                 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n",                 "    (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n"
                ].join(""),
                s: "([+\-]\\d{2}:\\d{2})"};     case "T":
            return {g:0,
                c:null,
                s:"[A-Z]{1,4}"};     case "Z":
            return {g:1,
                c:"z = results[" + currentGroup + "] * 1;\n"                   + "z = (-43200 <= z && z <= 50400)? z : null;\n",
                s:"([+\-]?\\d{1,5})"};     case "c":
            var df = Date.formatCodeToRegex, calc = [];
            var arr = [df("Y", 1), df("m", 2), df("d", 3), df("h", 4), df("i", 5), df("s", 6), df("P", 7)];
            for (var i = 0, l = arr.length; i < l; ++i) {
              calc.push(arr[i].c);
            }
            return {g:1,
                c:calc.join(""),
                s:arr[0].s + "-" + arr[1].s + "-" + arr[2].s + "T" + arr[3].s + ":" + arr[4].s + ":" + arr[5].s + arr[6].s};
        case "U":
            return {g:1,
                c:"u = parseInt(results[" + currentGroup + "], 10);\n",
                s:"(-?\\d+)"};     default:
            return {g:0,
                c:null,
                s:Ext.escapeRe(character)};
        }
    };

    Date.prototype.getTimezone = function() {
                                                        return this.toString().replace(/^.* (?:\((.*)\)|([A-Z]{1,4})(?:[\-+][0-9]{4})?(?: -?\d+)?)$/, "$1$2").replace(/[^A-Z]/g, "");
    };

    Date.prototype.getGMTOffset = function(colon) {
        return (this.getTimezoneOffset() > 0 ? "-" : "+")
            + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
            + (colon ? ":" : "")
            + String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
    };

    Date.prototype.getDayOfYear = function() {
        var num = 0;
        Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
        for (var i = 0; i < this.getMonth(); ++i) {
            num += Date.daysInMonth[i];
        }
        return num + this.getDate() - 1;
    };

    Date.prototype.getWeekOfYear = function() {
            var ms1d = 864e5;     var ms7d = 7 * ms1d;     var DC3 = Date.UTC(this.getFullYear(), this.getMonth(), this.getDate() + 3) / ms1d;     var AWN = Math.floor(DC3 / 7);     var Wyr = new Date(AWN * ms7d).getUTCFullYear();
        return AWN - Math.floor(Date.UTC(Wyr, 0, 7) / ms7d) + 1;
    };

    Date.prototype.isLeapYear = function() {
        var year = this.getFullYear();
        return !!((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
    };

    Date.prototype.getFirstDayOfMonth = function() {
        var day = (this.getDay() - (this.getDate() - 1)) % 7;
        return (day < 0) ? (day + 7) : day;
    };

    Date.prototype.getLastDayOfMonth = function() {
        var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
        return (day < 0) ? (day + 7) : day;
    };

    Date.prototype.getFirstDateOfMonth = function() {
        return new Date(this.getFullYear(), this.getMonth(), 1);
    };

    Date.prototype.getLastDateOfMonth = function() {
        return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
    };

    Date.prototype.getDaysInMonth = function() {
        Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
        return Date.daysInMonth[this.getMonth()];
    };

    Date.prototype.getSuffix = function() {
        switch (this.getDate()) {
            case 1:
            case 21:
            case 31:
                return "st";
            case 2:
            case 22:
                return "nd";
            case 3:
            case 23:
                return "rd";
            default:
                return "th";
        }
    };

    Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];

    Date.monthNames =
       ["January",
        "February",
        "March",
        "April",
        "May",
        "June",
        "July",
        "August",
        "September",
        "October",
        "November",
        "December"];

    Date.getShortMonthName = function(month) {
        return Date.monthNames[month].substring(0, 3);
    }

    Date.dayNames =
       ["Sunday",
        "Monday",
        "Tuesday",
        "Wednesday",
        "Thursday",
        "Friday",
        "Saturday"];

    Date.getShortDayName = function(day) {
        return Date.dayNames[day].substring(0, 3);
    }

    Date.y2kYear = 50;

    Date.monthNumbers = {
        Jan:0,
        Feb:1,
        Mar:2,
        Apr:3,
        May:4,
        Jun:5,
        Jul:6,
        Aug:7,
        Sep:8,
        Oct:9,
        Nov:10,
        Dec:11};

    Date.getMonthNumber = function(name) {
            return Date.monthNumbers[name.substring(0, 1).toUpperCase() + name.substring(1, 3).toLowerCase()];
    }

    Date.prototype.clone = function() {
      return new Date(this.getTime());
    };

    Date.prototype.clearTime = function(clone){
        if(clone){
            return this.clone().clearTime();
        }
        this.setHours(0);
        this.setMinutes(0);
        this.setSeconds(0);
        this.setMilliseconds(0);
        return this;
    };

    if(Ext.isSafari){
        Date.brokenSetMonth = Date.prototype.setMonth;
      Date.prototype.setMonth = function(num){
        if(num <= -1){
          var n = Math.ceil(-num);
          var back_year = Math.ceil(n/12);
          var month = (n % 12) ? 12 - n % 12 : 0 ;
          this.setFullYear(this.getFullYear() - back_year);
          return Date.brokenSetMonth.call(this, month);
        } else {
          return Date.brokenSetMonth.apply(this, arguments);
        }
      };
    }

    Date.MILLI = "ms";

    Date.SECOND = "s";

    Date.MINUTE = "mi";

    Date.HOUR = "h";

    Date.DAY = "d";

    Date.MONTH = "mo";

    Date.YEAR = "y";

    Date.prototype.add = function(interval, value){
      var d = this.clone();
      if (!interval || value === 0) return d;
      switch(interval.toLowerCase()){
        case Date.MILLI:
          d.setMilliseconds(this.getMilliseconds() + value);
          break;
        case Date.SECOND:
          d.setSeconds(this.getSeconds() + value);
          break;
        case Date.MINUTE:
          d.setMinutes(this.getMinutes() + value);
          break;
        case Date.HOUR:
          d.setHours(this.getHours() + value);
          break;
        case Date.DAY:
          d.setDate(this.getDate() + value);
          break;
        case Date.MONTH:
          var day = this.getDate();
          if(day > 28){
              day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
          }
          d.setDate(day);
          d.setMonth(this.getMonth() + value);
          break;
        case Date.YEAR:
          d.setFullYear(this.getFullYear() + value);
          break;
      }
      return d;
    };

    Date.prototype.between = function(start, end){
        var t = this.getTime();
        return start.getTime() <= t && t <= end.getTime();
    }

    Ext.util.DelayedTask = function(fn, scope, args){
        var id = null, d, t;

        var call = function(){
            var now = new Date().getTime();
            if(now - t >= d){
                clearInterval(id);
                id = null;
                fn.apply(scope, args || []);
            }
        };

        this.delay = function(delay, newFn, newScope, newArgs){
            if(id && delay != d){
                this.cancel();
            }
            d = delay;
            t = new Date().getTime();
            fn = newFn || fn;
            scope = newScope || scope;
            args = newArgs || args;
            if(!id){
                id = setInterval(call, d);
            }
        };

        this.cancel = function(){
            if(id){
                clearInterval(id);
                id = null;
            }
        };
    };

    Ext.util.TaskRunner = function(interval){
        interval = interval || 10;
        var tasks = [], removeQueue = [];
        var id = 0;
        var running = false;

            var stopThread = function(){
            running = false;
            clearInterval(id);
            id = 0;
        };

            var startThread = function(){
            if(!running){
                running = true;
                id = setInterval(runTasks, interval);
            }
        };

            var removeTask = function(t){
            removeQueue.push(t);
            if(t.onStop){
                t.onStop.apply(t.scope || t);
            }
        };

            var runTasks = function(){
            if(removeQueue.length > 0){
                for(var i = 0, len = removeQueue.length; i < len; i++){
                    tasks.remove(removeQueue[i]);
                }
                removeQueue = [];
                if(tasks.length < 1){
                    stopThread();
                    return;
                }
            }
            var now = new Date().getTime();
            for(var i = 0, len = tasks.length; i < len; ++i){
                var t = tasks[i];
                var itime = now - t.taskRunTime;
                if(t.interval <= itime){
                    var rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
                    t.taskRunTime = now;
                    if(rt === false || t.taskRunCount === t.repeat){
                        removeTask(t);
                        return;
                    }
                }
                if(t.duration && t.duration <= (now - t.taskStartTime)){
                    removeTask(t);
                }
            }
        };

        this.start = function(task){
            tasks.push(task);
            task.taskStartTime = new Date().getTime();
            task.taskRunTime = 0;
            task.taskRunCount = 0;
            startThread();
            return task;
        };

        this.stop = function(task){
            removeTask(task);
            return task;
        };

        this.stopAll = function(){
            stopThread();
            for(var i = 0, len = tasks.length; i < len; i++){
                if(tasks[i].onStop){
                    tasks[i].onStop();
                }
            }
            tasks = [];
            removeQueue = [];
        };
    };

    Ext.TaskMgr = new Ext.util.TaskRunner();

    Ext.util.MixedCollection = function(allowFunctions, keyFn){
        this.items = [];
        this.map = {};
        this.keys = [];
        this.length = 0;
        this.addEvents(

            "clear",

            "add",

            "replace",

            "remove",
            "sort"
        );
        this.allowFunctions = allowFunctions === true;
        if(keyFn){
            this.getKey = keyFn;
        }
        Ext.util.MixedCollection.superclass.constructor.call(this);
    };

    Ext.extend(Ext.util.MixedCollection, Ext.util.Observable, {
        allowFunctions : false,

        add : function(key, o){
            if(arguments.length == 1){
                o = arguments[0];
                key = this.getKey(o);
            }
            if(typeof key == "undefined" || key === null){
                this.length++;
                this.items.push(o);
                this.keys.push(null);
            }else{
                var old = this.map[key];
                if(old){
                    return this.replace(key, o);
                }
                this.length++;
                this.items.push(o);
                this.map[key] = o;
                this.keys.push(key);
            }
            this.fireEvent("add", this.length-1, o, key);
            return o;
        },

        getKey : function(o){
             return o.id;
        },

        replace : function(key, o){
            if(arguments.length == 1){
                o = arguments[0];
                key = this.getKey(o);
            }
            var old = this.item(key);
            if(typeof key == "undefined" || key === null || typeof old == "undefined"){
                 return this.add(key, o);
            }
            var index = this.indexOfKey(key);
            this.items[index] = o;
            this.map[key] = o;
            this.fireEvent("replace", key, old, o);
            return o;
        },

        addAll : function(objs){
            if(arguments.length > 1 || Ext.isArray(objs)){
                var args = arguments.length > 1 ? arguments : objs;
                for(var i = 0, len = args.length; i < len; i++){
                    this.add(args[i]);
                }
            }else{
                for(var key in objs){
                    if(this.allowFunctions || typeof objs[key] != "function"){
                        this.add(key, objs[key]);
                    }
                }
            }
        },

        each : function(fn, scope){
            var items = [].concat(this.items);
            for(var i = 0, len = items.length; i < len; i++){
                if(fn.call(scope || items[i], items[i], i, len) === false){
                    break;
                }
            }
        },

        eachKey : function(fn, scope){
            for(var i = 0, len = this.keys.length; i < len; i++){
                fn.call(scope || window, this.keys[i], this.items[i], i, len);
            }
        },

        find : function(fn, scope){
            for(var i = 0, len = this.items.length; i < len; i++){
                if(fn.call(scope || window, this.items[i], this.keys[i])){
                    return this.items[i];
                }
            }
            return null;
        },

        insert : function(index, key, o){
            if(arguments.length == 2){
                o = arguments[1];
                key = this.getKey(o);
            }
            if(index >= this.length){
                return this.add(key, o);
            }
            this.length++;
            this.items.splice(index, 0, o);
            if(typeof key != "undefined" && key != null){
                this.map[key] = o;
            }
            this.keys.splice(index, 0, key);
            this.fireEvent("add", index, o, key);
            return o;
        },

        remove : function(o){
            return this.removeAt(this.indexOf(o));
        },

        removeAt : function(index){
            if(index < this.length && index >= 0){
                this.length--;
                var o = this.items[index];
                this.items.splice(index, 1);
                var key = this.keys[index];
                if(typeof key != "undefined"){
                    delete this.map[key];
                }
                this.keys.splice(index, 1);
                this.fireEvent("remove", o, key);
                return o;
            }
            return false;
        },

        removeKey : function(key){
            return this.removeAt(this.indexOfKey(key));
        },

        getCount : function(){
            return this.length;
        },

        indexOf : function(o){
            return this.items.indexOf(o);
        },

        indexOfKey : function(key){
            return this.keys.indexOf(key);
        },

        item : function(key){
            var item = typeof this.map[key] != "undefined" ? this.map[key] : this.items[key];
            return typeof item != 'function' || this.allowFunctions ? item : null;
        },

        itemAt : function(index){
            return this.items[index];
        },

        key : function(key){
            return this.map[key];
        },

        contains : function(o){
            return this.indexOf(o) != -1;
        },

        containsKey : function(key){
            return typeof this.map[key] != "undefined";
        },

        clear : function(){
            this.length = 0;
            this.items = [];
            this.keys = [];
            this.map = {};
            this.fireEvent("clear");
        },

        first : function(){
            return this.items[0];
        },

        last : function(){
            return this.items[this.length-1];
        },

        _sort : function(property, dir, fn){
            var dsc = String(dir).toUpperCase() == "DESC" ? -1 : 1;
            fn = fn || function(a, b){
                return a-b;
            };
            var c = [], k = this.keys, items = this.items;
            for(var i = 0, len = items.length; i < len; i++){
                c[c.length] = {key: k[i], value: items[i], index: i};
            }
            c.sort(function(a, b){
                var v = fn(a[property], b[property]) * dsc;
                if(v == 0){
                    v = (a.index < b.index ? -1 : 1);
                }
                return v;
            });
            for(var i = 0, len = c.length; i < len; i++){
                items[i] = c[i].value;
                k[i] = c[i].key;
            }
            this.fireEvent("sort", this);
        },

        sort : function(dir, fn){
            this._sort("value", dir, fn);
        },

        keySort : function(dir, fn){
            this._sort("key", dir, fn || function(a, b){
                return String(a).toUpperCase()-String(b).toUpperCase();
            });
        },

        getRange : function(start, end){
            var items = this.items;
            if(items.length < 1){
                return [];
            }
            start = start || 0;
            end = Math.min(typeof end == "undefined" ? this.length-1 : end, this.length-1);
            var r = [];
            if(start <= end){
                for(var i = start; i <= end; i++) {
            	    r[r.length] = items[i];
                }
            }else{
                for(var i = start; i >= end; i--) {
            	    r[r.length] = items[i];
                }
            }
            return r;
        },

        filter : function(property, value, anyMatch, caseSensitive){
            if(Ext.isEmpty(value, false)){
                return this.clone();
            }
            value = this.createValueMatcher(value, anyMatch, caseSensitive);
            return this.filterBy(function(o){
                return o && value.test(o[property]);
            });
    	},

        filterBy : function(fn, scope){
            var r = new Ext.util.MixedCollection();
            r.getKey = this.getKey;
            var k = this.keys, it = this.items;
            for(var i = 0, len = it.length; i < len; i++){
                if(fn.call(scope||this, it[i], k[i])){
    				r.add(k[i], it[i]);
    			}
            }
            return r;
        },

        findIndex : function(property, value, start, anyMatch, caseSensitive){
            if(Ext.isEmpty(value, false)){
                return -1;
            }
            value = this.createValueMatcher(value, anyMatch, caseSensitive);
            return this.findIndexBy(function(o){
                return o && value.test(o[property]);
            }, null, start);
    	},

        findIndexBy : function(fn, scope, start){
            var k = this.keys, it = this.items;
            for(var i = (start||0), len = it.length; i < len; i++){
                if(fn.call(scope||this, it[i], k[i])){
    				return i;
                }
            }
            if(typeof start == 'number' && start > 0){
                for(var i = 0; i < start; i++){
                    if(fn.call(scope||this, it[i], k[i])){
                        return i;
                    }
                }
            }
            return -1;
        },

        createValueMatcher : function(value, anyMatch, caseSensitive){
            if(!value.exec){
                value = String(value);
                value = new RegExp((anyMatch === true ? '' : '^') + Ext.escapeRe(value), caseSensitive ? '' : 'i');
            }
            return value;
        },

        clone : function(){
            var r = new Ext.util.MixedCollection();
            var k = this.keys, it = this.items;
            for(var i = 0, len = it.length; i < len; i++){
                r.add(k[i], it[i]);
            }
            r.getKey = this.getKey;
            return r;
        }
    });

    Ext.util.MixedCollection.prototype.get = Ext.util.MixedCollection.prototype.item;

    Ext.util.JSON = new (function(){
        var useHasOwn = {}.hasOwnProperty ? true : false;

        var pad = function(n) {
            return n < 10 ? "0" + n : n;
        };

        var m = {
            "\b": '\\b',
            "\t": '\\t',
            "\n": '\\n',
            "\f": '\\f',
            "\r": '\\r',
            '"' : '\\"',
            "\\": '\\\\'
        };

        var encodeString = function(s){
            if (/["\\\x00-\x1f]/.test(s)) {
                return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
                    var c = m[b];
                    if(c){
                        return c;
                    }
                    c = b.charCodeAt();
                    return "\\u00" +
                        Math.floor(c / 16).toString(16) +
                        (c % 16).toString(16);
                }) + '"';
            }
            return '"' + s + '"';
        };

        var encodeArray = function(o){
            var a = ["["], b, i, l = o.length, v;
                for (i = 0; i < l; i += 1) {
                    v = o[i];
                    switch (typeof v) {
                        case "undefined":
                        case "function":
                        case "unknown":
                            break;
                        default:
                            if (b) {
                                a.push(',');
                            }
                            a.push(v === null ? "null" : Ext.util.JSON.encode(v));
                            b = true;
                    }
                }
                a.push("]");
                return a.join("");
        };

        var encodeDate = function(o){
            return '"' + o.getFullYear() + "-" +
                    pad(o.getMonth() + 1) + "-" +
                    pad(o.getDate()) + "T" +
                    pad(o.getHours()) + ":" +
                    pad(o.getMinutes()) + ":" +
                    pad(o.getSeconds()) + '"';
        };

        this.encode = function(o){
            if(typeof o == "undefined" || o === null){
                return "null";
            }else if(Ext.isArray(o)){
                return encodeArray(o);
            }else if(Ext.isDate(o)){
                return encodeDate(o);
            }else if(typeof o == "string"){
                return encodeString(o);
            }else if(typeof o == "number"){
                return isFinite(o) ? String(o) : "null";
            }else if(typeof o == "boolean"){
                return String(o);
            }else {
                var a = ["{"], b, i, v;
                for (i in o) {
                    if(!useHasOwn || o.hasOwnProperty(i)) {
                        v = o[i];
                        switch (typeof v) {
                        case "undefined":
                        case "function":
                        case "unknown":
                            break;
                        default:
                            if(b){
                                a.push(',');
                            }
                            a.push(this.encode(i), ":",
                                    v === null ? "null" : this.encode(v));
                            b = true;
                        }
                    }
                }
                a.push("}");
                return a.join("");
            }
        };

        this.decode = function(json){
            return eval("(" + json + ')');
        };
    })();

    Ext.encode = Ext.util.JSON.encode;

    Ext.decode = Ext.util.JSON.decode;

    Ext.util.Format = function(){
        var trimRe = /^\s+|\s+$/g;
        return {

            ellipsis : function(value, len){
                if(value && value.length > len){
                    return value.substr(0, len-3)+"...";
                }
                return value;
            },

            undef : function(value){
                return value !== undefined ? value : "";
            },

            defaultValue : function(value, defaultValue){
                return value !== undefined && value !== '' ? value : defaultValue;
            },

            htmlEncode : function(value){
                return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/").replace(/</g, "<").replace(/"/g, '"');
            },

            trim : function(value){
                return String(value).replace(trimRe, "");
            },

            substr : function(value, start, length){
                return String(value).substr(start, length);
            },

            lowercase : function(value){
                return String(value).toLowerCase();
            },

            uppercase : function(value){
                return String(value).toUpperCase();
            },

            capitalize : function(value){
                return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
            },

            call : function(value, fn){
                if(arguments.length > 2){
                    var args = Array.prototype.slice.call(arguments, 2);
                    args.unshift(value);
                    return eval(fn).apply(window, args);
                }else{
                    return eval(fn).call(window, value);
                }
            },

            usMoney : function(v){
                v = (Math.round((v-0)*100))/100;
                v = (v == Math.floor(v)) ? v + ".00" : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
                v = String(v);
                var ps = v.split('.');
                var whole = ps[0];
                var sub = ps[1] ? '.'+ ps[1] : '.00';
                var r = /(\d+)(\d{3})/;
                while (r.test(whole)) {
                    whole = whole.replace(r, '$1' + ',' + '$2');
                }
                v = whole + sub;
                if(v.charAt(0) == '-'){
                    return '-$' + v.substr(1);
                }
                return "$" +  v;
            },

            date : function(v, format){
                if(!v){
                    return "";
                }
                if(!Ext.isDate(v)){
                    v = new Date(Date.parse(v));
                }
                return v.dateFormat(format || "m/d/Y");
            },

            dateRenderer : function(format){
                return function(v){
                    return Ext.util.Format.date(v, format);
                };
            },

            stripTagsRE : /<\/?[^>]+>/gi,

            stripTags : function(v){
                return !v ? v : String(v).replace(this.stripTagsRE, "");
            },

            stripScriptsRe : /(?:)((\n|\r|.)*?)(?:<\/script>)/ig,

            stripScripts : function(v){
                return !v ? v : String(v).replace(this.stripScriptsRe, "");
            },

            fileSize : function(size){
                if(size < 1024) {
                    return size + " bytes";
                } else if(size < 1048576) {
                    return (Math.round(((size*10) / 1024))/10) + " KB";
                } else {
                    return (Math.round(((size*10) / 1048576))/10) + " MB";
                }
            },

            math : function(){
                var fns = {};
                return function(v, a){
                    if(!fns[a]){
                        fns[a] = new Function('v', 'return v ' + a + ';');
                    }
                    return fns[a](v);
                }
            }()
        };
    }();

    Ext.XTemplate = function(){
        Ext.XTemplate.superclass.constructor.apply(this, arguments);
        var s = this.html;

        s = ['', s, ''].join('');

        var re = /]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/;

        var nameRe = /^]*?for="(.*?)"/;
        var ifRe = /^]*?if="(.*?)"/;
        var execRe = /^]*?exec="(.*?)"/;
        var m, id = 0;
        var tpls = [];

        while(m = s.match(re)){
           var m2 = m[0].match(nameRe);
           var m3 = m[0].match(ifRe);
           var m4 = m[0].match(execRe);
           var exp = null, fn = null, exec = null;
           var name = m2 && m2[1] ? m2[1] : '';
           if(m3){
               exp = m3 && m3[1] ? m3[1] : null;
               if(exp){
                   fn = new Function('values', 'parent', 'xindex', 'xcount', 'with(values){ return '+(Ext.util.Format.htmlDecode(exp))+'; }');
               }
           }
           if(m4){
               exp = m4 && m4[1] ? m4[1] : null;
               if(exp){
                   exec = new Function('values', 'parent', 'xindex', 'xcount', 'with(values){ '+(Ext.util.Format.htmlDecode(exp))+'; }');
               }
           }
           if(name){
               switch(name){
                   case '.': name = new Function('values', 'parent', 'with(values){ return values; }'); break;
                   case '..': name = new Function('values', 'parent', 'with(values){ return parent; }'); break;
                   default: name = new Function('values', 'parent', 'with(values){ return '+name+'; }');
               }
           }
           tpls.push({
                id: id,
                target: name,
                exec: exec,
                test: fn,
                body: m[1]||''
            });
           s = s.replace(m[0], '{xtpl'+ id + '}');
           ++id;
        }
        for(var i = tpls.length-1; i >= 0; --i){
            this.compileTpl(tpls[i]);
        }
        this.master = tpls[tpls.length-1];
        this.tpls = tpls;
    };
    Ext.extend(Ext.XTemplate, Ext.Template, {

        re : /\{([\w-\.\#]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?(\s?[\+\-\*\\]\s?[\d\.\+\-\*\\\(\)]+)?\}/g,

        codeRe : /\{\[((?:\\\]|.|\n)*?)\]\}/g,

        applySubTemplate : function(id, values, parent, xindex, xcount){
            var t = this.tpls[id];
            if(t.test && !t.test.call(this, values, parent, xindex, xcount)){
                return '';
            }
            if(t.exec && t.exec.call(this, values, parent, xindex, xcount)){
                return '';
            }
            var vs = t.target ? t.target.call(this, values, parent) : values;
            parent = t.target ? values : parent;
            if(t.target && Ext.isArray(vs)){
                var buf = [];
                for(var i = 0, len = vs.length; i < len; i++){
                    buf[buf.length] = t.compiled.call(this, vs[i], parent, i+1, len);
                }
                return buf.join('');
            }
            return t.compiled.call(this, vs, parent, xindex, xcount);
        },

        compileTpl : function(tpl){
            var fm = Ext.util.Format;
            var useF = this.disableFormats !== true;
            var sep = Ext.isGecko ? "+" : ",";
            var fn = function(m, name, format, args, math){
                if(name.substr(0, 4) == 'xtpl'){
                    return "'"+ sep +'this.applySubTemplate('+name.substr(4)+', values, parent, xindex, xcount)'+sep+"'";
                }
                var v;
                if(name === '.'){
                    v = 'values';
                }else if(name === '#'){
                    v = 'xindex';
                }else if(name.indexOf('.') != -1){
                    v = name;
                }else{
                    v = "values['" + name + "']";
                }
                if(math){
                    v = '(' + v + math + ')';
                }
                if(format && useF){
                    args = args ? ',' + args : "";
                    if(format.substr(0, 5) != "this."){
                        format = "fm." + format + '(';
                    }else{
                        format = 'this.call("'+ format.substr(5) + '", ';
                        args = ", values";
                    }
                }else{
                    args= ''; format = "("+v+" === undefined ? '' : ";
                }
                return "'"+ sep + format + v + args + ")"+sep+"'";
            };
            var codeFn = function(m, code){
                return "'"+ sep +'('+code+')'+sep+"'";
            };

            var body;

            if(Ext.isGecko){
                body = "tpl.compiled = function(values, parent, xindex, xcount){ return '" +
                       tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn).replace(this.codeRe, codeFn) +
                        "';};";
            }else{
                body = ["tpl.compiled = function(values, parent, xindex, xcount){ return ['"];
                body.push(tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn).replace(this.codeRe, codeFn));
                body.push("'].join('');};");
                body = body.join('');
            }
            eval(body);
            return this;
        },

        apply : function(values){
            return this.master.compiled.call(this, values, {}, 1, 1);
        },

        applyTemplate : function(values){
            return this.master.compiled.call(this, values, {}, 1, 1);
        },

        compile : function(){return this;}

    });

    Ext.XTemplate.from = function(el){
        el = Ext.getDom(el);
        return new Ext.XTemplate(el.value || el.innerHTML);
    };

    Ext.util.CSS = function(){
    	var rules = null;
       	var doc = document;

        var camelRe = /(-[a-z])/gi;
        var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };

       return {

       createStyleSheet : function(cssText, id){
           var ss;
           var head = doc.getElementsByTagName("head")[0];
           var rules = doc.createElement("style");
           rules.setAttribute("type", "text/css");
           if(id){
               rules.setAttribute("id", id);
           }
           if(Ext.isIE){
               head.appendChild(rules);
               ss = rules.styleSheet;
               ss.cssText = cssText;
           }else{
               try{
                    rules.appendChild(doc.createTextNode(cssText));
               }catch(e){
                   rules.cssText = cssText;
               }
               head.appendChild(rules);
               ss = rules.styleSheet ? rules.styleSheet : (rules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
           }
           this.cacheStyleSheet(ss);
           return ss;
       },

       removeStyleSheet : function(id){
           var existing = doc.getElementById(id);
           if(existing){
               existing.parentNode.removeChild(existing);
           }
       },

       swapStyleSheet : function(id, url){
           this.removeStyleSheet(id);
           var ss = doc.createElement("link");
           ss.setAttribute("rel", "stylesheet");
           ss.setAttribute("type", "text/css");
           ss.setAttribute("id", id);
           ss.setAttribute("href", url);
           doc.getElementsByTagName("head")[0].appendChild(ss);
       },

       refreshCache : function(){
           return this.getRules(true);
       },

       cacheStyleSheet : function(ss){
           if(!rules){
               rules = {};
           }
           try{
               var ssRules = ss.cssRules || ss.rules;
               for(var j = ssRules.length-1; j >= 0; --j){
                   rules[ssRules[j].selectorText] = ssRules[j];
               }
           }catch(e){}
       },

       getRules : function(refreshCache){
       		if(rules == null || refreshCache){
       			rules = {};
       			var ds = doc.styleSheets;
       			for(var i =0, len = ds.length; i < len; i++){
       			    try{
        		        this.cacheStyleSheet(ds[i]);
        		    }catch(e){}
    	        }
       		}
       		return rules;
       	},

       getRule : function(selector, refreshCache){
       		var rs = this.getRules(refreshCache);
       		if(!Ext.isArray(selector)){
       		    return rs[selector];
       		}
       		for(var i = 0; i < selector.length; i++){
    			if(rs[selector[i]]){
    				return rs[selector[i]];
    			}
    		}
    		return null;
       	},

       updateRule : function(selector, property, value){
       		if(!Ext.isArray(selector)){
       			var rule = this.getRule(selector);
       			if(rule){
       				rule.style[property.replace(camelRe, camelFn)] = value;
       				return true;
       			}
       		}else{
       			for(var i = 0; i < selector.length; i++){
       				if(this.updateRule(selector[i], property, value)){
       					return true;
       				}
       			}
       		}
       		return false;
       	}
       };
    }();

    Ext.util.ClickRepeater = function(el, config)
    {
        this.el = Ext.get(el);
        this.el.unselectable();

        Ext.apply(this, config);

        this.addEvents(

            "mousedown",

            "click",

            "mouseup"
        );

        this.el.on("mousedown", this.handleMouseDown, this);
        if(this.preventDefault || this.stopDefault){
            this.el.on("click", function(e){
                if(this.preventDefault){
                    e.preventDefault();
                }
                if(this.stopDefault){
                    e.stopEvent();
                }
            }, this);
        }

            if(this.handler){
            this.on("click", this.handler,  this.scope || this);
        }

        Ext.util.ClickRepeater.superclass.constructor.call(this);
    };

    Ext.extend(Ext.util.ClickRepeater, Ext.util.Observable, {
        interval : 20,
        delay: 250,
        preventDefault : true,
        stopDefault : false,
        timer : 0,

            handleMouseDown : function(){
            clearTimeout(this.timer);
            this.el.blur();
            if(this.pressClass){
                this.el.addClass(this.pressClass);
            }
            this.mousedownTime = new Date();

            Ext.getDoc().on("mouseup", this.handleMouseUp, this);
            this.el.on("mouseout", this.handleMouseOut, this);

            this.fireEvent("mousedown", this);
            this.fireEvent("click", this);

            if (this.accelerate) {
                this.delay = 400;
    	    }
            this.timer = this.click.defer(this.delay || this.interval, this);
        },

            click : function(){
            this.fireEvent("click", this);
            this.timer = this.click.defer(this.accelerate ?
                this.easeOutExpo(this.mousedownTime.getElapsed(),
                    400,
                    -390,
                    12000) :
                this.interval, this);
        },

        easeOutExpo : function (t, b, c, d) {
            return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
        },

            handleMouseOut : function(){
            clearTimeout(this.timer);
            if(this.pressClass){
                this.el.removeClass(this.pressClass);
            }
            this.el.on("mouseover", this.handleMouseReturn, this);
        },

            handleMouseReturn : function(){
            this.el.un("mouseover", this.handleMouseReturn);
            if(this.pressClass){
                this.el.addClass(this.pressClass);
            }
            this.click();
        },

            handleMouseUp : function(){
            clearTimeout(this.timer);
            this.el.un("mouseover", this.handleMouseReturn);
            this.el.un("mouseout", this.handleMouseOut);
            Ext.getDoc().un("mouseup", this.handleMouseUp);
            this.el.removeClass(this.pressClass);
            this.fireEvent("mouseup", this);
        }
    });

    Ext.KeyNav = function(el, config){
        this.el = Ext.get(el);
        Ext.apply(this, config);
        if(!this.disabled){
            this.disabled = true;
            this.enable();
        }
    };

    Ext.KeyNav.prototype = {

        disabled : false,

        defaultEventAction: "stopEvent",

        forceKeyDown : false,

            prepareEvent : function(e){
            var k = e.getKey();
            var h = this.keyToHandler[k];
                                    if(Ext.isSafari && h && k >= 37 && k <= 40){
                e.stopEvent();
            }
        },

            relay : function(e){
            var k = e.getKey();
            var h = this.keyToHandler[k];
            if(h && this[h]){
                if(this.doRelay(e, this[h], h) !== true){
                    e[this.defaultEventAction]();
                }
            }
        },

            doRelay : function(e, h, hname){
            return h.call(this.scope || this, e);
        },

            enter : false,
        left : false,
        right : false,
        up : false,
        down : false,
        tab : false,
        esc : false,
        pageUp : false,
        pageDown : false,
        del : false,
        home : false,
        end : false,

            keyToHandler : {
            37 : "left",
            39 : "right",
            38 : "up",
            40 : "down",
            33 : "pageUp",
            34 : "pageDown",
            46 : "del",
            36 : "home",
            35 : "end",
            13 : "enter",
            27 : "esc",
            9  : "tab"
        },

    	enable: function(){
    		if(this.disabled){
                                        if(this.forceKeyDown || Ext.isIE || Ext.isAir){
                    this.el.on("keydown", this.relay,  this);
                }else{
                    this.el.on("keydown", this.prepareEvent,  this);
                    this.el.on("keypress", this.relay,  this);
                }
    		    this.disabled = false;
    		}
    	},

    	disable: function(){
    		if(!this.disabled){
    		    if(this.forceKeyDown || Ext.isIE || Ext.isAir){
                    this.el.un("keydown", this.relay);
                }else{
                    this.el.un("keydown", this.prepareEvent);
                    this.el.un("keypress", this.relay);
                }
    		    this.disabled = true;
    		}
    	}
    };

    Ext.KeyMap = function(el, config, eventName){
        this.el  = Ext.get(el);
        this.eventName = eventName || "keydown";
        this.bindings = [];
        if(config){
            this.addBinding(config);
        }
        this.enable();
    };

    Ext.KeyMap.prototype = {

        stopEvent : false,

    	addBinding : function(config){
            if(Ext.isArray(config)){
                for(var i = 0, len = config.length; i < len; i++){
                    this.addBinding(config[i]);
                }
                return;
            }
            var keyCode = config.key,
                shift = config.shift,
                ctrl = config.ctrl,
                alt = config.alt,
                fn = config.fn || config.handler,
                scope = config.scope;

            if(typeof keyCode == "string"){
                var ks = [];
                var keyString = keyCode.toUpperCase();
                for(var j = 0, len = keyString.length; j < len; j++){
                    ks.push(keyString.charCodeAt(j));
                }
                keyCode = ks;
            }
            var keyArray = Ext.isArray(keyCode);

            var handler = function(e){
                if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) &&  (!alt || e.altKey)){
                    var k = e.getKey();
                    if(keyArray){
                        for(var i = 0, len = keyCode.length; i < len; i++){
                            if(keyCode[i] == k){
                              if(this.stopEvent){
                                  e.stopEvent();
                              }
                              fn.call(scope || window, k, e);
                              return;
                            }
                        }
                    }else{
                        if(k == keyCode){
                            if(this.stopEvent){
                               e.stopEvent();
                            }
                            fn.call(scope || window, k, e);
                        }
                    }
                }
            };
            this.bindings.push(handler);
    	},

        on : function(key, fn, scope){
            var keyCode, shift, ctrl, alt;
            if(typeof key == "object" && !Ext.isArray(key)){
                keyCode = key.key;
                shift = key.shift;
                ctrl = key.ctrl;
                alt = key.alt;
            }else{
                keyCode = key;
            }
            this.addBinding({
                key: keyCode,
                shift: shift,
                ctrl: ctrl,
                alt: alt,
                fn: fn,
                scope: scope
            })
        },

        handleKeyDown : function(e){
    	    if(this.enabled){
        	    var b = this.bindings;
        	    for(var i = 0, len = b.length; i < len; i++){
        	        b[i].call(this, e);
        	    }
    	    }
    	},

    	isEnabled : function(){
    	    return this.enabled;
    	},

    	enable: function(){
    		if(!this.enabled){
    		    this.el.on(this.eventName, this.handleKeyDown, this);
    		    this.enabled = true;
    		}
    	},

    	disable: function(){
    		if(this.enabled){
    		    this.el.removeListener(this.eventName, this.handleKeyDown, this);
    		    this.enabled = false;
    		}
    	}
    };

    Ext.util.TextMetrics = function(){
        var shared;
        return {

            measure : function(el, text, fixedWidth){
                if(!shared){
                    shared = Ext.util.TextMetrics.Instance(el, fixedWidth);
                }
                shared.bind(el);
                shared.setFixedWidth(fixedWidth || 'auto');
                return shared.getSize(text);
            },

            createInstance : function(el, fixedWidth){
                return Ext.util.TextMetrics.Instance(el, fixedWidth);
            }
        };
    }();

    Ext.util.TextMetrics.Instance = function(bindTo, fixedWidth){
        var ml = new Ext.Element(document.createElement('div'));
        document.body.appendChild(ml.dom);
        ml.position('absolute');
        ml.setLeftTop(-1000, -1000);
        ml.hide();

        if(fixedWidth){
            ml.setWidth(fixedWidth);
        }

        var instance = {

            getSize : function(text){
                ml.update(text);
                var s = ml.getSize();
                ml.update('');
                return s;
            },

            bind : function(el){
                ml.setStyle(
                    Ext.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height')
                );
            },

            setFixedWidth : function(width){
                ml.setWidth(width);
            },

            getWidth : function(text){
                ml.dom.style.width = 'auto';
                return this.getSize(text).width;
            },

            getHeight : function(text){
                return this.getSize(text).height;
            }
        };

        instance.bind(bindTo);

        return instance;
    };

    Ext.Element.measureText = Ext.util.TextMetrics.measure;

    (function() {

    var Event=Ext.EventManager;
    var Dom=Ext.lib.Dom;

    Ext.dd.DragDrop = function(id, sGroup, config) {
        if(id) {
            this.init(id, sGroup, config);
        }
    };

    Ext.dd.DragDrop.prototype = {

        id: null,

        config: null,

        dragElId: null,

        handleElId: null,

        invalidHandleTypes: null,

        invalidHandleIds: null,

        invalidHandleClasses: null,

        startPageX: 0,

        startPageY: 0,

        groups: null,

        locked: false,

        lock: function() { this.locked = true; },

        unlock: function() { this.locked = false; },

        isTarget: true,

        padding: null,

        _domRef: null,

        __ygDragDrop: true,

        constrainX: false,

        constrainY: false,

        minX: 0,

        maxX: 0,

        minY: 0,

        maxY: 0,

        maintainOffset: false,

        xTicks: null,

        yTicks: null,

        primaryButtonOnly: true,

        available: false,

        hasOuterHandles: false,

        b4StartDrag: function(x, y) { },

        startDrag: function(x, y) {  },

        b4Drag: function(e) { },

        onDrag: function(e) {  },

        onDragEnter: function(e, id) {  },

        b4DragOver: function(e) { },

        onDragOver: function(e, id) {  },

        b4DragOut: function(e) { },

        onDragOut: function(e, id) {  },

        b4DragDrop: function(e) { },

        onDragDrop: function(e, id) {  },

        onInvalidDrop: function(e) {  },

        b4EndDrag: function(e) { },

        endDrag: function(e) {  },

        b4MouseDown: function(e) {  },

        onMouseDown: function(e) {  },

        onMouseUp: function(e) {  },

        onAvailable: function () {
        },

        defaultPadding : {left:0, right:0, top:0, bottom:0},

        constrainTo : function(constrainTo, pad, inContent){
            if(typeof pad == "number"){
                pad = {left: pad, right:pad, top:pad, bottom:pad};
            }
            pad = pad || this.defaultPadding;
            var b = Ext.get(this.getEl()).getBox();
            var ce = Ext.get(constrainTo);
            var s = ce.getScroll();
            var c, cd = ce.dom;
            if(cd == document.body){
                c = { x: s.left, y: s.top, width: Ext.lib.Dom.getViewWidth(), height: Ext.lib.Dom.getViewHeight()};
            }else{
                var xy = ce.getXY();
                c = {x : xy[0]+s.left, y: xy[1]+s.top, width: cd.clientWidth, height: cd.clientHeight};
            }

            var topSpace = b.y - c.y;
            var leftSpace = b.x - c.x;

            this.resetConstraints();
            this.setXConstraint(leftSpace - (pad.left||0),
                    c.width - leftSpace - b.width - (pad.right||0),
    				this.xTickSize
            );
            this.setYConstraint(topSpace - (pad.top||0),
                    c.height - topSpace - b.height - (pad.bottom||0),
    				this.yTickSize
            );
        },

        getEl: function() {
            if (!this._domRef) {
                this._domRef = Ext.getDom(this.id);
            }

            return this._domRef;
        },

        getDragEl: function() {
            return Ext.getDom(this.dragElId);
        },

        init: function(id, sGroup, config) {
            this.initTarget(id, sGroup, config);
            Event.on(this.id, "mousedown", this.handleMouseDown, this);

        },

        initTarget: function(id, sGroup, config) {

            this.config = config || {};

            this.DDM = Ext.dd.DDM;

            this.groups = {};

            if (typeof id !== "string") {
                id = Ext.id(id);
            }

            this.id = id;

            this.addToGroup((sGroup) ? sGroup : "default");

            this.handleElId = id;

            this.setDragElId(id);

            this.invalidHandleTypes = { A: "A" };
            this.invalidHandleIds = {};
            this.invalidHandleClasses = [];

            this.applyConfig();

            this.handleOnAvailable();
        },

        applyConfig: function() {

            this.padding           = this.config.padding || [0, 0, 0, 0];
            this.isTarget          = (this.config.isTarget !== false);
            this.maintainOffset    = (this.config.maintainOffset);
            this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);

        },

        handleOnAvailable: function() {
            this.available = true;
            this.resetConstraints();
            this.onAvailable();
        },

        setPadding: function(iTop, iRight, iBot, iLeft) {

            if (!iRight && 0 !== iRight) {
                this.padding = [iTop, iTop, iTop, iTop];
            } else if (!iBot && 0 !== iBot) {
                this.padding = [iTop, iRight, iTop, iRight];
            } else {
                this.padding = [iTop, iRight, iBot, iLeft];
            }
        },

        setInitPosition: function(diffX, diffY) {
            var el = this.getEl();

            if (!this.DDM.verifyEl(el)) {
                return;
            }

            var dx = diffX || 0;
            var dy = diffY || 0;

            var p = Dom.getXY( el );

            this.initPageX = p[0] - dx;
            this.initPageY = p[1] - dy;

            this.lastPageX = p[0];
            this.lastPageY = p[1];

            this.setStartPosition(p);
        },

        setStartPosition: function(pos) {
            var p = pos || Dom.getXY( this.getEl() );
            this.deltaSetXY = null;

            this.startPageX = p[0];
            this.startPageY = p[1];
        },

        addToGroup: function(sGroup) {
            this.groups[sGroup] = true;
            this.DDM.regDragDrop(this, sGroup);
        },

        removeFromGroup: function(sGroup) {
            if (this.groups[sGroup]) {
                delete this.groups[sGroup];
            }

            this.DDM.removeDDFromGroup(this, sGroup);
        },

        setDragElId: function(id) {
            this.dragElId = id;
        },

        setHandleElId: function(id) {
            if (typeof id !== "string") {
                id = Ext.id(id);
            }
            this.handleElId = id;
            this.DDM.regHandle(this.id, id);
        },

        setOuterHandleElId: function(id) {
            if (typeof id !== "string") {
                id = Ext.id(id);
            }
            Event.on(id, "mousedown",
                    this.handleMouseDown, this);
            this.setHandleElId(id);

            this.hasOuterHandles = true;
        },

        unreg: function() {
            Event.un(this.id, "mousedown",
                    this.handleMouseDown);
            this._domRef = null;
            this.DDM._remove(this);
        },

        destroy : function(){
            this.unreg();
        },

        isLocked: function() {
            return (this.DDM.isLocked() || this.locked);
        },

        handleMouseDown: function(e, oDD){
            if (this.primaryButtonOnly && e.button != 0) {
                return;
            }

            if (this.isLocked()) {
                return;
            }

            this.DDM.refreshCache(this.groups);

            var pt = new Ext.lib.Point(Ext.lib.Event.getPageX(e), Ext.lib.Event.getPageY(e));
            if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) )  {
            } else {
                if (this.clickValidator(e)) {

                    this.setStartPosition();

                    this.b4MouseDown(e);
                    this.onMouseDown(e);

                    this.DDM.handleMouseDown(e, this);

                    this.DDM.stopEvent(e);
                } else {

                }
            }
        },

        clickValidator: function(e) {
            var target = e.getTarget();
            return ( this.isValidHandleChild(target) &&
                        (this.id == this.handleElId ||
                            this.DDM.handleWasClicked(target, this.id)) );
        },

        addInvalidHandleType: function(tagName) {
            var type = tagName.toUpperCase();
            this.invalidHandleTypes[type] = type;
        },

        addInvalidHandleId: function(id) {
            if (typeof id !== "string") {
                id = Ext.id(id);
            }
            this.invalidHandleIds[id] = id;
        },

        addInvalidHandleClass: function(cssClass) {
            this.invalidHandleClasses.push(cssClass);
        },

        removeInvalidHandleType: function(tagName) {
            var type = tagName.toUpperCase();

            delete this.invalidHandleTypes[type];
        },

        removeInvalidHandleId: function(id) {
            if (typeof id !== "string") {
                id = Ext.id(id);
            }
            delete this.invalidHandleIds[id];
        },

        removeInvalidHandleClass: function(cssClass) {
            for (var i=0, len=this.invalidHandleClasses.length; i= this.minX; i = i - iTickSize) {
                if (!tickMap[i]) {
                    this.xTicks[this.xTicks.length] = i;
                    tickMap[i] = true;
                }
            }

            for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
                if (!tickMap[i]) {
                    this.xTicks[this.xTicks.length] = i;
                    tickMap[i] = true;
                }
            }

            this.xTicks.sort(this.DDM.numericSort) ;
        },

        setYTicks: function(iStartY, iTickSize) {
            this.yTicks = [];
            this.yTickSize = iTickSize;

            var tickMap = {};

            for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
                if (!tickMap[i]) {
                    this.yTicks[this.yTicks.length] = i;
                    tickMap[i] = true;
                }
            }

            for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
                if (!tickMap[i]) {
                    this.yTicks[this.yTicks.length] = i;
                    tickMap[i] = true;
                }
            }

            this.yTicks.sort(this.DDM.numericSort) ;
        },

        setXConstraint: function(iLeft, iRight, iTickSize) {
            this.leftConstraint = iLeft;
            this.rightConstraint = iRight;

            this.minX = this.initPageX - iLeft;
            this.maxX = this.initPageX + iRight;
            if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }

            this.constrainX = true;
        },

        clearConstraints: function() {
            this.constrainX = false;
            this.constrainY = false;
            this.clearTicks();
        },

        clearTicks: function() {
            this.xTicks = null;
            this.yTicks = null;
            this.xTickSize = 0;
            this.yTickSize = 0;
        },

        setYConstraint: function(iUp, iDown, iTickSize) {
            this.topConstraint = iUp;
            this.bottomConstraint = iDown;

            this.minY = this.initPageY - iUp;
            this.maxY = this.initPageY + iDown;
            if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }

            this.constrainY = true;

        },

        resetConstraints: function() {

            if (this.initPageX || this.initPageX === 0) {

                var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
                var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;

                this.setInitPosition(dx, dy);

            } else {
                this.setInitPosition();
            }

            if (this.constrainX) {
                this.setXConstraint( this.leftConstraint,
                                     this.rightConstraint,
                                     this.xTickSize        );
            }

            if (this.constrainY) {
                this.setYConstraint( this.topConstraint,
                                     this.bottomConstraint,
                                     this.yTickSize         );
            }
        },

        getTick: function(val, tickArray) {

            if (!tickArray) {

                return val;
            } else if (tickArray[0] >= val) {

                return tickArray[0];
            } else {
                for (var i=0, len=tickArray.length; i= val) {
                        var diff1 = val - tickArray[i];
                        var diff2 = tickArray[next] - val;
                        return (diff2 > diff1) ? tickArray[i] : tickArray[next];
                    }
                }

                return tickArray[tickArray.length - 1];
            }
        },

        toString: function() {
            return ("DragDrop " + this.id);
        }

    };

    })();

    if (!Ext.dd.DragDropMgr) {

    Ext.dd.DragDropMgr = function() {

        var Event = Ext.EventManager;

        return {

            ids: {},

            handleIds: {},

            dragCurrent: null,

            dragOvers: {},

            deltaX: 0,

            deltaY: 0,

            preventDefault: true,

            stopPropagation: true,

            initalized: false,

            locked: false,

            init: function() {
                this.initialized = true;
            },

            POINT: 0,

            INTERSECT: 1,

            mode: 0,

            _execOnAll: function(sMethod, args) {
                for (var i in this.ids) {
                    for (var j in this.ids[i]) {
                        var oDD = this.ids[i][j];
                        if (! this.isTypeOfDD(oDD)) {
                            continue;
                        }
                        oDD[sMethod].apply(oDD, args);
                    }
                }
            },

            _onLoad: function() {

                this.init();

                Event.on(document, "mouseup",   this.handleMouseUp, this, true);
                Event.on(document, "mousemove", this.handleMouseMove, this, true);
                Event.on(window,   "unload",    this._onUnload, this, true);
                Event.on(window,   "resize",    this._onResize, this, true);

            },

            _onResize: function(e) {
                this._execOnAll("resetConstraints", []);
            },

            lock: function() { this.locked = true; },

            unlock: function() { this.locked = false; },

            isLocked: function() { return this.locked; },

            locationCache: {},

            useCache: true,

            clickPixelThresh: 3,

            clickTimeThresh: 350,

            dragThreshMet: false,

            clickTimeout: null,

            startX: 0,

            startY: 0,

            regDragDrop: function(oDD, sGroup) {
                if (!this.initialized) { this.init(); }

                if (!this.ids[sGroup]) {
                    this.ids[sGroup] = {};
                }
                this.ids[sGroup][oDD.id] = oDD;
            },

            removeDDFromGroup: function(oDD, sGroup) {
                if (!this.ids[sGroup]) {
                    this.ids[sGroup] = {};
                }

                var obj = this.ids[sGroup];
                if (obj && obj[oDD.id]) {
                    delete obj[oDD.id];
                }
            },

            _remove: function(oDD) {
                for (var g in oDD.groups) {
                    if (g && this.ids[g][oDD.id]) {
                        delete this.ids[g][oDD.id];
                    }
                }
                delete this.handleIds[oDD.id];
            },

            regHandle: function(sDDId, sHandleId) {
                if (!this.handleIds[sDDId]) {
                    this.handleIds[sDDId] = {};
                }
                this.handleIds[sDDId][sHandleId] = sHandleId;
            },

            isDragDrop: function(id) {
                return ( this.getDDById(id) ) ? true : false;
            },

            getRelated: function(p_oDD, bTargetsOnly) {
                var oDDs = [];
                for (var i in p_oDD.groups) {
                    for (j in this.ids[i]) {
                        var dd = this.ids[i][j];
                        if (! this.isTypeOfDD(dd)) {
                            continue;
                        }
                        if (!bTargetsOnly || dd.isTarget) {
                            oDDs[oDDs.length] = dd;
                        }
                    }
                }

                return oDDs;
            },

            isLegalTarget: function (oDD, oTargetDD) {
                var targets = this.getRelated(oDD, true);
                for (var i=0, len=targets.length;i this.clickPixelThresh ||
                                diffY > this.clickPixelThresh) {
                        this.startDrag(this.startX, this.startY);
                    }
                }

                if (this.dragThreshMet) {
                    this.dragCurrent.b4Drag(e);
                    this.dragCurrent.onDrag(e);
                    if(!this.dragCurrent.moveOnly){
                        this.fireEvents(e, false);
                    }
                }

                this.stopEvent(e);

                return true;
            },

            fireEvents: function(e, isDrop) {
                var dc = this.dragCurrent;

                if (!dc || dc.isLocked()) {
                    return;
                }

                var pt = e.getPoint();

                var oldOvers = [];

                var outEvts   = [];
                var overEvts  = [];
                var dropEvts  = [];
                var enterEvts = [];

                for (var i in this.dragOvers) {

                    var ddo = this.dragOvers[i];

                    if (! this.isTypeOfDD(ddo)) {
                        continue;
                    }

                    if (! this.isOverTarget(pt, ddo, this.mode)) {
                        outEvts.push( ddo );
                    }

                    oldOvers[i] = true;
                    delete this.dragOvers[i];
                }

                for (var sGroup in dc.groups) {

                    if ("string" != typeof sGroup) {
                        continue;
                    }

                    for (i in this.ids[sGroup]) {
                        var oDD = this.ids[sGroup][i];
                        if (! this.isTypeOfDD(oDD)) {
                            continue;
                        }

                        if (oDD.isTarget && !oDD.isLocked() && oDD != dc) {
                            if (this.isOverTarget(pt, oDD, this.mode)) {

                                if (isDrop) {
                                    dropEvts.push( oDD );

                                } else {

                                    if (!oldOvers[oDD.id]) {
                                        enterEvts.push( oDD );

                                    } else {
                                        overEvts.push( oDD );
                                    }

                                    this.dragOvers[oDD.id] = oDD;
                                }
                            }
                        }
                    }
                }

                if (this.mode) {
                    if (outEvts.length) {
                        dc.b4DragOut(e, outEvts);
                        dc.onDragOut(e, outEvts);
                    }

                    if (enterEvts.length) {
                        dc.onDragEnter(e, enterEvts);
                    }

                    if (overEvts.length) {
                        dc.b4DragOver(e, overEvts);
                        dc.onDragOver(e, overEvts);
                    }

                    if (dropEvts.length) {
                        dc.b4DragDrop(e, dropEvts);
                        dc.onDragDrop(e, dropEvts);
                    }

                } else {

                    var len = 0;
                    for (i=0, len=outEvts.length; i 2000) {
                    } else {
                        setTimeout(DDM._addListeners, 10);
                        if (document && document.body) {
                            DDM._timeoutCount += 1;
                        }
                    }
                }
            },

            handleWasClicked: function(node, id) {
                if (this.isHandle(id, node.id)) {
                    return true;
                } else {

                    var p = node.parentNode;

                    while (p) {
                        if (this.isHandle(id, p.id)) {
                            return true;
                        } else {
                            p = p.parentNode;
                        }
                    }
                }

                return false;
            }

        };

    }();

    Ext.dd.DDM = Ext.dd.DragDropMgr;
    Ext.dd.DDM._addListeners();

    }

    Ext.dd.DD = function(id, sGroup, config) {
        if (id) {
            this.init(id, sGroup, config);
        }
    };

    Ext.extend(Ext.dd.DD, Ext.dd.DragDrop, {

        scroll: true,

        autoOffset: function(iPageX, iPageY) {
            var x = iPageX - this.startPageX;
            var y = iPageY - this.startPageY;
            this.setDelta(x, y);
        },

        setDelta: function(iDeltaX, iDeltaY) {
            this.deltaX = iDeltaX;
            this.deltaY = iDeltaY;
        },

        setDragElPos: function(iPageX, iPageY) {

            var el = this.getDragEl();
            this.alignElWithMouse(el, iPageX, iPageY);
        },

        alignElWithMouse: function(el, iPageX, iPageY) {
            var oCoord = this.getTargetCoord(iPageX, iPageY);
            var fly = el.dom ? el : Ext.fly(el, '_dd');
            if (!this.deltaSetXY) {
                var aCoord = [oCoord.x, oCoord.y];
                fly.setXY(aCoord);
                var newLeft = fly.getLeft(true);
                var newTop  = fly.getTop(true);
                this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ];
            } else {
                fly.setLeftTop(oCoord.x + this.deltaSetXY[0], oCoord.y + this.deltaSetXY[1]);
            }

            this.cachePosition(oCoord.x, oCoord.y);
            this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
            return oCoord;
        },

        cachePosition: function(iPageX, iPageY) {
            if (iPageX) {
                this.lastPageX = iPageX;
                this.lastPageY = iPageY;
            } else {
                var aCoord = Ext.lib.Dom.getXY(this.getEl());
                this.lastPageX = aCoord[0];
                this.lastPageY = aCoord[1];
            }
        },

        autoScroll: function(x, y, h, w) {

            if (this.scroll) {

                var clientH = Ext.lib.Dom.getViewHeight();

                var clientW = Ext.lib.Dom.getViewWidth();

                var st = this.DDM.getScrollTop();

                var sl = this.DDM.getScrollLeft();

                var bot = h + y;

                var right = w + x;

                var toBot = (clientH + st - y - this.deltaY);

                var toRight = (clientW + sl - x - this.deltaX);

                var thresh = 40;

                var scrAmt = (document.all) ? 80 : 30;

                if ( bot > clientH && toBot < thresh ) {
                    window.scrollTo(sl, st + scrAmt);
                }

                if ( y < st && st > 0 && y - st < thresh ) {
                    window.scrollTo(sl, st - scrAmt);
                }

                if ( right > clientW && toRight < thresh ) {
                    window.scrollTo(sl + scrAmt, st);
                }

                if ( x < sl && sl > 0 && x - sl < thresh ) {
                    window.scrollTo(sl - scrAmt, st);
                }
            }
        },

        getTargetCoord: function(iPageX, iPageY) {

            var x = iPageX - this.deltaX;
            var y = iPageY - this.deltaY;

            if (this.constrainX) {
                if (x < this.minX) { x = this.minX; }
                if (x > this.maxX) { x = this.maxX; }
            }

            if (this.constrainY) {
                if (y < this.minY) { y = this.minY; }
                if (y > this.maxY) { y = this.maxY; }
            }

            x = this.getTick(x, this.xTicks);
            y = this.getTick(y, this.yTicks);

            return {x:x, y:y};
        },

        applyConfig: function() {
            Ext.dd.DD.superclass.applyConfig.call(this);
            this.scroll = (this.config.scroll !== false);
        },

        b4MouseDown: function(e) {

            this.autoOffset(e.getPageX(),
                                e.getPageY());
        },

        b4Drag: function(e) {
            this.setDragElPos(e.getPageX(),
                                e.getPageY());
        },

        toString: function() {
            return ("DD " + this.id);
        }

    });

    Ext.dd.DDProxy = function(id, sGroup, config) {
        if (id) {
            this.init(id, sGroup, config);
            this.initFrame();
        }
    };

    Ext.dd.DDProxy.dragElId = "ygddfdiv";

    Ext.extend(Ext.dd.DDProxy, Ext.dd.DD, {

        resizeFrame: true,

        centerFrame: false,

        createFrame: function() {
            var self = this;
            var body = document.body;

            if (!body || !body.firstChild) {
                setTimeout( function() { self.createFrame(); }, 50 );
                return;
            }

            var div = this.getDragEl();

            if (!div) {
                div    = document.createElement("div");
                div.id = this.dragElId;
                var s  = div.style;

                s.position   = "absolute";
                s.visibility = "hidden";
                s.cursor     = "move";
                s.border     = "2px solid #aaa";
                s.zIndex     = 999;

                body.insertBefore(div, body.firstChild);
            }
        },

        initFrame: function() {
            this.createFrame();
        },

        applyConfig: function() {
            Ext.dd.DDProxy.superclass.applyConfig.call(this);

            this.resizeFrame = (this.config.resizeFrame !== false);
            this.centerFrame = (this.config.centerFrame);
            this.setDragElId(this.config.dragElId || Ext.dd.DDProxy.dragElId);
        },

        showFrame: function(iPageX, iPageY) {
            var el = this.getEl();
            var dragEl = this.getDragEl();
            var s = dragEl.style;

            this._resizeProxy();

            if (this.centerFrame) {
                this.setDelta( Math.round(parseInt(s.width,  10)/2),
                               Math.round(parseInt(s.height, 10)/2) );
            }

            this.setDragElPos(iPageX, iPageY);

            Ext.fly(dragEl).show();
        },

        _resizeProxy: function() {
            if (this.resizeFrame) {
                var el = this.getEl();
                Ext.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);
            }
        },

        b4MouseDown: function(e) {
            var x = e.getPageX();
            var y = e.getPageY();
            this.autoOffset(x, y);
            this.setDragElPos(x, y);
        },

        b4StartDrag: function(x, y) {

            this.showFrame(x, y);
        },

        b4EndDrag: function(e) {
            Ext.fly(this.getDragEl()).hide();
        },

        endDrag: function(e) {

            var lel = this.getEl();
            var del = this.getDragEl();

            del.style.visibility = "";

            this.beforeMove();

            lel.style.visibility = "hidden";
            Ext.dd.DDM.moveToEl(lel, del);
            del.style.visibility = "hidden";
            lel.style.visibility = "";

            this.afterDrag();
        },

        beforeMove : function(){

        },

        afterDrag : function(){

        },

        toString: function() {
            return ("DDProxy " + this.id);
        }

    });

    Ext.dd.DDTarget = function(id, sGroup, config) {
        if (id) {
            this.initTarget(id, sGroup, config);
        }
    };

    Ext.extend(Ext.dd.DDTarget, Ext.dd.DragDrop, {
        toString: function() {
            return ("DDTarget " + this.id);
        }
    });

    Ext.dd.DragTracker = function(config){
        Ext.apply(this, config);
        this.addEvents(
            'mousedown',
            'mouseup',
            'mousemove',
            'dragstart',
            'dragend',
            'drag'
        );

        this.dragRegion = new Ext.lib.Region(0,0,0,0);

        if(this.el){
            this.initEl(this.el);
        }
    }

    Ext.extend(Ext.dd.DragTracker, Ext.util.Observable,  {
        active: false,
        tolerance: 5,
        autoStart: false,

        initEl: function(el){
            this.el = Ext.get(el);
            el.on('mousedown', this.onMouseDown, this,
                    this.delegate ? {delegate: this.delegate} : undefined);
        },

        destroy : function(){
            this.el.un('mousedown', this.onMouseDown, this);
        },

        onMouseDown: function(e, target){
            if(this.fireEvent('mousedown', this, e) !== false && this.onBeforeStart(e) !== false){
                this.startXY = this.lastXY = e.getXY();
                this.dragTarget = this.delegate ? target : this.el.dom;
                e.preventDefault();
                var doc = Ext.getDoc();
                doc.on('mouseup', this.onMouseUp, this);
                doc.on('mousemove', this.onMouseMove, this);
                doc.on('selectstart', this.stopSelect, this);
                if(this.autoStart){
                    this.timer = this.triggerStart.defer(this.autoStart === true ? 1000 : this.autoStart, this);
                }
            }
        },

        onMouseMove: function(e, target){
            e.preventDefault();
            var xy = e.getXY(), s = this.startXY;
            this.lastXY = xy;
            if(!this.active){
                if(Math.abs(s[0]-xy[0]) > this.tolerance || Math.abs(s[1]-xy[1]) > this.tolerance){
                    this.triggerStart();
                }else{
                    return;
                }
            }
            this.fireEvent('mousemove', this, e);
            this.onDrag(e);
            this.fireEvent('drag', this, e);
        },

        onMouseUp: function(e){
            var doc = Ext.getDoc();
            doc.un('mousemove', this.onMouseMove, this);
            doc.un('mouseup', this.onMouseUp, this);
            doc.un('selectstart', this.stopSelect, this);
            e.preventDefault();
            this.clearStart();
            this.active = false;
            delete this.elRegion;
            this.fireEvent('mouseup', this, e);
            this.onEnd(e);
            this.fireEvent('dragend', this, e);
        },

        triggerStart: function(isTimer){
            this.clearStart();
            this.active = true;
            this.onStart(this.startXY);
            this.fireEvent('dragstart', this, this.startXY);
        },

        clearStart : function(){
            if(this.timer){
                clearTimeout(this.timer);
                delete this.timer;
            }
        },

        stopSelect : function(e){
            e.stopEvent();
            return false;
        },

        onBeforeStart : function(e){

        },

        onStart : function(xy){

        },

        onDrag : function(e){

        },

        onEnd : function(e){

        },

        getDragTarget : function(){
            return this.dragTarget;
        },

        getDragCt : function(){
            return this.el;
        },

        getXY : function(constrain){
            return constrain ?
                   this.constrainModes[constrain].call(this, this.lastXY) : this.lastXY;
        },

        getOffset : function(constrain){
            var xy = this.getXY(constrain);
            var s = this.startXY;
            return [s[0]-xy[0], s[1]-xy[1]];
        },

        constrainModes: {
            'point' : function(xy){

                if(!this.elRegion){
                    this.elRegion = this.getDragCt().getRegion();
                }

                var dr = this.dragRegion;

                dr.left = xy[0];
                dr.top = xy[1];
                dr.right = xy[0];
                dr.bottom = xy[1];

                dr.constrainTo(this.elRegion);

                return [dr.left, dr.top];
            }
        }
    });

    Ext.dd.ScrollManager = function(){
        var ddm = Ext.dd.DragDropMgr;
        var els = {};
        var dragEl = null;
        var proc = {};

        var onStop = function(e){
            dragEl = null;
            clearProc();
        };

        var triggerRefresh = function(){
            if(ddm.dragCurrent){
                 ddm.refreshCache(ddm.dragCurrent.groups);
            }
        };

        var doScroll = function(){
            if(ddm.dragCurrent){
                var dds = Ext.dd.ScrollManager;
                var inc = proc.el.ddScrollConfig ?
                          proc.el.ddScrollConfig.increment : dds.increment;
                if(!dds.animate){
                    if(proc.el.scroll(proc.dir, inc)){
                        triggerRefresh();
                    }
                }else{
                    proc.el.scroll(proc.dir, inc, true, dds.animDuration, triggerRefresh);
                }
            }
        };

        var clearProc = function(){
            if(proc.id){
                clearInterval(proc.id);
            }
            proc.id = 0;
            proc.el = null;
            proc.dir = "";
        };

        var startProc = function(el, dir){
            clearProc();
            proc.el = el;
            proc.dir = dir;
            proc.id = setInterval(doScroll, Ext.dd.ScrollManager.frequency);
        };

        var onFire = function(e, isDrop){
            if(isDrop || !ddm.dragCurrent){ return; }
            var dds = Ext.dd.ScrollManager;
            if(!dragEl || dragEl != ddm.dragCurrent){
                dragEl = ddm.dragCurrent;

                dds.refreshCache();
            }

            var xy = Ext.lib.Event.getXY(e);
            var pt = new Ext.lib.Point(xy[0], xy[1]);
            for(var id in els){
                var el = els[id], r = el._region;
                var c = el.ddScrollConfig ? el.ddScrollConfig : dds;
                if(r && r.contains(pt) && el.isScrollable()){
                    if(r.bottom - pt.y <= c.vthresh){
                        if(proc.el != el){
                            startProc(el, "down");
                        }
                        return;
                    }else if(r.right - pt.x <= c.hthresh){
                        if(proc.el != el){
                            startProc(el, "left");
                        }
                        return;
                    }else if(pt.y - r.top <= c.vthresh){
                        if(proc.el != el){
                            startProc(el, "up");
                        }
                        return;
                    }else if(pt.x - r.left <= c.hthresh){
                        if(proc.el != el){
                            startProc(el, "right");
                        }
                        return;
                    }
                }
            }
            clearProc();
        };

        ddm.fireEvents = ddm.fireEvents.createSequence(onFire, ddm);
        ddm.stopDrag = ddm.stopDrag.createSequence(onStop, ddm);

        return {

            register : function(el){
                if(Ext.isArray(el)){
                    for(var i = 0, len = el.length; i < len; i++) {
                    	this.register(el[i]);
                    }
                }else{
                    el = Ext.get(el);
                    els[el.id] = el;
                }
            },

            unregister : function(el){
                if(Ext.isArray(el)){
                    for(var i = 0, len = el.length; i < len; i++) {
                    	this.unregister(el[i]);
                    }
                }else{
                    el = Ext.get(el);
                    delete els[el.id];
                }
            },

            vthresh : 25,

            hthresh : 25,

            increment : 100,

            frequency : 500,

            animate: true,

            animDuration: .4,

            refreshCache : function(){
                for(var id in els){
                    if(typeof els[id] == 'object'){
                        els[id]._region = els[id].getRegion();
                    }
                }
            }
        };
    }();

    Ext.dd.Registry = function(){
        var elements = {};
        var handles = {};
        var autoIdSeed = 0;

        var getId = function(el, autogen){
            if(typeof el == "string"){
                return el;
            }
            var id = el.id;
            if(!id && autogen !== false){
                id = "extdd-" + (++autoIdSeed);
                el.id = id;
            }
            return id;
        };

        return {

            register : function(el, data){
                data = data || {};
                if(typeof el == "string"){
                    el = document.getElementById(el);
                }
                data.ddel = el;
                elements[getId(el)] = data;
                if(data.isHandle !== false){
                    handles[data.ddel.id] = data;
                }
                if(data.handles){
                    var hs = data.handles;
                    for(var i = 0, len = hs.length; i < len; i++){
                    	handles[getId(hs[i])] = data;
                    }
                }
            },

            unregister : function(el){
                var id = getId(el, false);
                var data = elements[id];
                if(data){
                    delete elements[id];
                    if(data.handles){
                        var hs = data.handles;
                        for(var i = 0, len = hs.length; i < len; i++){
                        	delete handles[getId(hs[i], false)];
                        }
                    }
                }
            },

            getHandle : function(id){
                if(typeof id != "string"){
                    id = id.id;
                }
                return handles[id];
            },

            getHandleFromEvent : function(e){
                var t = Ext.lib.Event.getTarget(e);
                return t ? handles[t.id] : null;
            },

            getTarget : function(id){
                if(typeof id != "string"){
                    id = id.id;
                }
                return elements[id];
            },

            getTargetFromEvent : function(e){
                var t = Ext.lib.Event.getTarget(e);
                return t ? elements[t.id] || handles[t.id] : null;
            }
        };
    }();

    Ext.dd.StatusProxy = function(config){
        Ext.apply(this, config);
        this.id = this.id || Ext.id();
        this.el = new Ext.Layer({
            dh: {
                id: this.id, tag: "div", cls: "x-dd-drag-proxy "+this.dropNotAllowed, children: [
                    {tag: "div", cls: "x-dd-drop-icon"},
                    {tag: "div", cls: "x-dd-drag-ghost"}
                ]
            },
            shadow: !config || config.shadow !== false
        });
        this.ghost = Ext.get(this.el.dom.childNodes[1]);
        this.dropStatus = this.dropNotAllowed;
    };

    Ext.dd.StatusProxy.prototype = {

        dropAllowed : "x-dd-drop-ok",

        dropNotAllowed : "x-dd-drop-nodrop",

        setStatus : function(cssClass){
            cssClass = cssClass || this.dropNotAllowed;
            if(this.dropStatus != cssClass){
                this.el.replaceClass(this.dropStatus, cssClass);
                this.dropStatus = cssClass;
            }
        },

        reset : function(clearGhost){
            this.el.dom.className = "x-dd-drag-proxy " + this.dropNotAllowed;
            this.dropStatus = this.dropNotAllowed;
            if(clearGhost){
                this.ghost.update("");
            }
        },

        update : function(html){
            if(typeof html == "string"){
                this.ghost.update(html);
            }else{
                this.ghost.update("");
                html.style.margin = "0";
                this.ghost.dom.appendChild(html);
            }
        },

        getEl : function(){
            return this.el;
        },

        getGhost : function(){
            return this.ghost;
        },

        hide : function(clear){
            this.el.hide();
            if(clear){
                this.reset(true);
            }
        },

        stop : function(){
            if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){
                this.anim.stop();
            }
        },

        show : function(){
            this.el.show();
        },

        sync : function(){
            this.el.sync();
        },

        repair : function(xy, callback, scope){
            this.callback = callback;
            this.scope = scope;
            if(xy && this.animRepair !== false){
                this.el.addClass("x-dd-drag-repair");
                this.el.hideUnders(true);
                this.anim = this.el.shift({
                    duration: this.repairDuration || .5,
                    easing: 'easeOut',
                    xy: xy,
                    stopFx: true,
                    callback: this.afterRepair,
                    scope: this
                });
            }else{
                this.afterRepair();
            }
        },

        afterRepair : function(){
            this.hide(true);
            if(typeof this.callback == "function"){
                this.callback.call(this.scope || this);
            }
            this.callback = null;
            this.scope = null;
        }
    };

    Ext.dd.DragSource = function(el, config){
        this.el = Ext.get(el);
        if(!this.dragData){
            this.dragData = {};
        }

        Ext.apply(this, config);

        if(!this.proxy){
            this.proxy = new Ext.dd.StatusProxy();
        }
        Ext.dd.DragSource.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group,
              {dragElId : this.proxy.id, resizeFrame: false, isTarget: false, scroll: this.scroll === true});

        this.dragging = false;
    };

    Ext.extend(Ext.dd.DragSource, Ext.dd.DDProxy, {

        dropAllowed : "x-dd-drop-ok",

        dropNotAllowed : "x-dd-drop-nodrop",

        getDragData : function(e){
            return this.dragData;
        },

        onDragEnter : function(e, id){
            var target = Ext.dd.DragDropMgr.getDDById(id);
            this.cachedTarget = target;
            if(this.beforeDragEnter(target, e, id) !== false){
                if(target.isNotifyTarget){
                    var status = target.notifyEnter(this, e, this.dragData);
                    this.proxy.setStatus(status);
                }else{
                    this.proxy.setStatus(this.dropAllowed);
                }

                if(this.afterDragEnter){

                    this.afterDragEnter(target, e, id);
                }
            }
        },

        beforeDragEnter : function(target, e, id){
            return true;
        },

        alignElWithMouse: function() {
            Ext.dd.DragSource.superclass.alignElWithMouse.apply(this, arguments);
            this.proxy.sync();
        },

        onDragOver : function(e, id){
            var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
            if(this.beforeDragOver(target, e, id) !== false){
                if(target.isNotifyTarget){
                    var status = target.notifyOver(this, e, this.dragData);
                    this.proxy.setStatus(status);
                }

                if(this.afterDragOver){

                    this.afterDragOver(target, e, id);
                }
            }
        },

        beforeDragOver : function(target, e, id){
            return true;
        },

        onDragOut : function(e, id){
            var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
            if(this.beforeDragOut(target, e, id) !== false){
                if(target.isNotifyTarget){
                    target.notifyOut(this, e, this.dragData);
                }
                this.proxy.reset();
                if(this.afterDragOut){

                    this.afterDragOut(target, e, id);
                }
            }
            this.cachedTarget = null;
        },

        beforeDragOut : function(target, e, id){
            return true;
        },

        onDragDrop : function(e, id){
            var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
            if(this.beforeDragDrop(target, e, id) !== false){
                if(target.isNotifyTarget){
                    if(target.notifyDrop(this, e, this.dragData)){
                        this.onValidDrop(target, e, id);
                    }else{
                        this.onInvalidDrop(target, e, id);
                    }
                }else{
                    this.onValidDrop(target, e, id);
                }

                if(this.afterDragDrop){

                    this.afterDragDrop(target, e, id);
                }
            }
            delete this.cachedTarget;
        },

        beforeDragDrop : function(target, e, id){
            return true;
        },

        onValidDrop : function(target, e, id){
            this.hideProxy();
            if(this.afterValidDrop){

                this.afterValidDrop(target, e, id);
            }
        },

        getRepairXY : function(e, data){
            return this.el.getXY();
        },

        onInvalidDrop : function(target, e, id){
            this.beforeInvalidDrop(target, e, id);
            if(this.cachedTarget){
                if(this.cachedTarget.isNotifyTarget){
                    this.cachedTarget.notifyOut(this, e, this.dragData);
                }
                this.cacheTarget = null;
            }
            this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);

            if(this.afterInvalidDrop){

                this.afterInvalidDrop(e, id);
            }
        },

        afterRepair : function(){
            if(Ext.enableFx){
                this.el.highlight(this.hlColor || "c3daf9");
            }
            this.dragging = false;
        },

        beforeInvalidDrop : function(target, e, id){
            return true;
        },

        handleMouseDown : function(e){
            if(this.dragging) {
                return;
            }
            var data = this.getDragData(e);
            if(data && this.onBeforeDrag(data, e) !== false){
                this.dragData = data;
                this.proxy.stop();
                Ext.dd.DragSource.superclass.handleMouseDown.apply(this, arguments);
            }
        },

        onBeforeDrag : function(data, e){
            return true;
        },

        onStartDrag : Ext.emptyFn,

        startDrag : function(x, y){
            this.proxy.reset();
            this.dragging = true;
            this.proxy.update("");
            this.onInitDrag(x, y);
            this.proxy.show();
        },

        onInitDrag : function(x, y){
            var clone = this.el.dom.cloneNode(true);
            clone.id = Ext.id();
            this.proxy.update(clone);
            this.onStartDrag(x, y);
            return true;
        },

        getProxy : function(){
            return this.proxy;
        },

        hideProxy : function(){
            this.proxy.hide();
            this.proxy.reset(true);
            this.dragging = false;
        },

        triggerCacheRefresh : function(){
            Ext.dd.DDM.refreshCache(this.groups);
        },

        b4EndDrag: function(e) {
        },

        endDrag : function(e){
            this.onEndDrag(this.dragData, e);
        },

        onEndDrag : function(data, e){
        },

        autoOffset : function(x, y) {
            this.setDelta(-12, -20);
        }
    });

    Ext.dd.DropTarget = function(el, config){
        this.el = Ext.get(el);

        Ext.apply(this, config);

        if(this.containerScroll){
            Ext.dd.ScrollManager.register(this.el);
        }

        Ext.dd.DropTarget.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group,
              {isTarget: true});

    };

    Ext.extend(Ext.dd.DropTarget, Ext.dd.DDTarget, {

        dropAllowed : "x-dd-drop-ok",

        dropNotAllowed : "x-dd-drop-nodrop",

        isTarget : true,

        isNotifyTarget : true,

        notifyEnter : function(dd, e, data){
            if(this.overClass){
                this.el.addClass(this.overClass);
            }
            return this.dropAllowed;
        },

        notifyOver : function(dd, e, data){
            return this.dropAllowed;
        },

        notifyOut : function(dd, e, data){
            if(this.overClass){
                this.el.removeClass(this.overClass);
            }
        },

        notifyDrop : function(dd, e, data){
            return false;
        }
    });

    Ext.dd.DragZone = function(el, config){
        Ext.dd.DragZone.superclass.constructor.call(this, el, config);
        if(this.containerScroll){
            Ext.dd.ScrollManager.register(this.el);
        }
    };

    Ext.extend(Ext.dd.DragZone, Ext.dd.DragSource, {

        getDragData : function(e){
            return Ext.dd.Registry.getHandleFromEvent(e);
        },

        onInitDrag : function(x, y){
            this.proxy.update(this.dragData.ddel.cloneNode(true));
            this.onStartDrag(x, y);
            return true;
        },

        afterRepair : function(){
            if(Ext.enableFx){
                Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
            }
            this.dragging = false;
        },

        getRepairXY : function(e){
            return Ext.Element.fly(this.dragData.ddel).getXY();
        }
    });

    Ext.dd.DropZone = function(el, config){
        Ext.dd.DropZone.superclass.constructor.call(this, el, config);
    };

    Ext.extend(Ext.dd.DropZone, Ext.dd.DropTarget, {

        getTargetFromEvent : function(e){
            return Ext.dd.Registry.getTargetFromEvent(e);
        },

        onNodeEnter : function(n, dd, e, data){

        },

        onNodeOver : function(n, dd, e, data){
            return this.dropAllowed;
        },

        onNodeOut : function(n, dd, e, data){

        },

        onNodeDrop : function(n, dd, e, data){
            return false;
        },

        onContainerOver : function(dd, e, data){
            return this.dropNotAllowed;
        },

        onContainerDrop : function(dd, e, data){
            return false;
        },

        notifyEnter : function(dd, e, data){
            return this.dropNotAllowed;
        },

        notifyOver : function(dd, e, data){
            var n = this.getTargetFromEvent(e);
            if(!n){
                if(this.lastOverNode){
                    this.onNodeOut(this.lastOverNode, dd, e, data);
                    this.lastOverNode = null;
                }
                return this.onContainerOver(dd, e, data);
            }
            if(this.lastOverNode != n){
                if(this.lastOverNode){
                    this.onNodeOut(this.lastOverNode, dd, e, data);
                }
                this.onNodeEnter(n, dd, e, data);
                this.lastOverNode = n;
            }
            return this.onNodeOver(n, dd, e, data);
        },

        notifyOut : function(dd, e, data){
            if(this.lastOverNode){
                this.onNodeOut(this.lastOverNode, dd, e, data);
                this.lastOverNode = null;
            }
        },

        notifyDrop : function(dd, e, data){
            if(this.lastOverNode){
                this.onNodeOut(this.lastOverNode, dd, e, data);
                this.lastOverNode = null;
            }
            var n = this.getTargetFromEvent(e);
            return n ?
                this.onNodeDrop(n, dd, e, data) :
                this.onContainerDrop(dd, e, data);
        },

        triggerCacheRefresh : function(){
            Ext.dd.DDM.refreshCache(this.groups);
        }
    });

    Ext.data.SortTypes = {

        none : function(s){
            return s;
        },

        stripTagsRE : /<\/?[^>]+>/gi,

        asText : function(s){
            return String(s).replace(this.stripTagsRE, "");
        },

        asUCText : function(s){
            return String(s).toUpperCase().replace(this.stripTagsRE, "");
        },

        asUCString : function(s) {
        	return String(s).toUpperCase();
        },

        asDate : function(s) {
            if(!s){
                return 0;
            }
            if(Ext.isDate(s)){
                return s.getTime();
            }
        	return Date.parse(String(s));
        },

        asFloat : function(s) {
        	var val = parseFloat(String(s).replace(/,/g, ""));
            if(isNaN(val)) val = 0;
        	return val;
        },

        asInt : function(s) {
            var val = parseInt(String(s).replace(/,/g, ""));
            if(isNaN(val)) val = 0;
        	return val;
        }
    };

    Ext.data.Record = function(data, id){
        this.id = (id || id === 0) ? id : ++Ext.data.Record.AUTO_ID;
        this.data = data;
    };

    Ext.data.Record.create = function(o){
        var f = Ext.extend(Ext.data.Record, {});
    	var p = f.prototype;
        p.fields = new Ext.util.MixedCollection(false, function(field){
            return field.name;
        });
        for(var i = 0, len = o.length; i < len; i++){
            p.fields.add(new Ext.data.Field(o[i]));
        }
        f.getField = function(name){
            return p.fields.get(name);
        };
        return f;
    };

    Ext.data.Record.AUTO_ID = 1000;
    Ext.data.Record.EDIT = 'edit';
    Ext.data.Record.REJECT = 'reject';
    Ext.data.Record.COMMIT = 'commit';

    Ext.data.Record.prototype = {

        dirty : false,
        editing : false,
        error: null,

        modified: null,

        join : function(store){
            this.store = store;
        },

        set : function(name, value){
            if(String(this.data[name]) == String(value)){
                return;
            }
            this.dirty = true;
            if(!this.modified){
                this.modified = {};
            }
            if(typeof this.modified[name] == 'undefined'){
                this.modified[name] = this.data[name];
            }
            this.data[name] = value;
            if(!this.editing && this.store){
                this.store.afterEdit(this);
            }
        },

        get : function(name){
            return this.data[name];
        },

        beginEdit : function(){
            this.editing = true;
            this.modified = {};
        },

        cancelEdit : function(){
            this.editing = false;
            delete this.modified;
        },

        endEdit : function(){
            this.editing = false;
            if(this.dirty && this.store){
                this.store.afterEdit(this);
            }
        },

        reject : function(silent){
            var m = this.modified;
            for(var n in m){
                if(typeof m[n] != "function"){
                    this.data[n] = m[n];
                }
            }
            this.dirty = false;
            delete this.modified;
            this.editing = false;
            if(this.store && silent !== true){
                this.store.afterReject(this);
            }
        },

        commit : function(silent){
            this.dirty = false;
            delete this.modified;
            this.editing = false;
            if(this.store && silent !== true){
                this.store.afterCommit(this);
            }
        },

        getChanges : function(){
            var m = this.modified, cs = {};
            for(var n in m){
                if(m.hasOwnProperty(n)){
                    cs[n] = this.data[n];
                }
            }
            return cs;
        },

        hasError : function(){
            return this.error != null;
        },

        clearError : function(){
            this.error = null;
        },

        copy : function(newId) {
            return new this.constructor(Ext.apply({}, this.data), newId || this.id);
        },

        isModified : function(fieldName){
            return this.modified && this.modified.hasOwnProperty(fieldName);
        }
    };

    Ext.StoreMgr = Ext.apply(new Ext.util.MixedCollection(), {
        register : function(){
            for(var i = 0, s; s = arguments[i]; i++){
                this.add(s);
            }
        },

        unregister : function(){
            for(var i = 0, s; s = arguments[i]; i++){
                this.remove(this.lookup(s));
            }
        },

        lookup : function(id){
            return typeof id == "object" ? id : this.get(id);
        },

        getKey : function(o){
             return o.storeId || o.id;
        }
    });

    Ext.data.Store = function(config){
        this.data = new Ext.util.MixedCollection(false);
        this.data.getKey = function(o){
            return o.id;
        };

        this.baseParams = {};

        this.paramNames = {
            "start" : "start",
            "limit" : "limit",
            "sort" : "sort",
            "dir" : "dir"
        };

        if(config && config.data){
            this.inlineData = config.data;
            delete config.data;
        }

        Ext.apply(this, config);

        if(this.url && !this.proxy){
            this.proxy = new Ext.data.HttpProxy({url: this.url});
        }

        if(this.reader){
            if(!this.recordType){
                this.recordType = this.reader.recordType;
            }
            if(this.reader.onMetaChange){
                this.reader.onMetaChange = this.onMetaChange.createDelegate(this);
            }
        }

        if(this.recordType){
            this.fields = this.recordType.prototype.fields;
        }
        this.modified = [];

        this.addEvents(

            'datachanged',

            'metachange',

            'add',

            'remove',

            'update',

            'clear',

            'beforeload',

            'load',

            'loadexception'
        );

        if(this.proxy){
            this.relayEvents(this.proxy,  ["loadexception"]);
        }

        this.sortToggle = {};
    	if(this.sortInfo){
    		this.setDefaultSort(this.sortInfo.field, this.sortInfo.direction);
    	}

        Ext.data.Store.superclass.constructor.call(this);

        if(this.storeId || this.id){
            Ext.StoreMgr.register(this);
        }
        if(this.inlineData){
            this.loadData(this.inlineData);
            delete this.inlineData;
        }else if(this.autoLoad){
            this.load.defer(10, this, [
                typeof this.autoLoad == 'object' ?
                    this.autoLoad : undefined]);
        }
    };
    Ext.extend(Ext.data.Store, Ext.util.Observable, {

        remoteSort : false,

        pruneModifiedRecords : false,

       lastOptions : null,

        destroy : function(){
            if(this.id){
                Ext.StoreMgr.unregister(this);
            }
            this.data = null;
            this.purgeListeners();
        },

        add : function(records){
            records = [].concat(records);
            if(records.length < 1){
                return;
            }
            for(var i = 0, len = records.length; i < len; i++){
                records[i].join(this);
            }
            var index = this.data.length;
            this.data.addAll(records);
            if(this.snapshot){
                this.snapshot.addAll(records);
            }
            this.fireEvent("add", this, records, index);
        },

        addSorted : function(record){
            var index = this.findInsertIndex(record);
            this.insert(index, record);
        },

        remove : function(record){
            var index = this.data.indexOf(record);
            this.data.removeAt(index);
            if(this.pruneModifiedRecords){
                this.modified.remove(record);
            }
            if(this.snapshot){
                this.snapshot.remove(record);
            }
            this.fireEvent("remove", this, record, index);
        },

        removeAll : function(){
            this.data.clear();
            if(this.snapshot){
                this.snapshot.clear();
            }
            if(this.pruneModifiedRecords){
                this.modified = [];
            }
            this.fireEvent("clear", this);
        },

        insert : function(index, records){
            records = [].concat(records);
            for(var i = 0, len = records.length; i < len; i++){
                this.data.insert(index, records[i]);
                records[i].join(this);
            }
            this.fireEvent("add", this, records, index);
        },

        indexOf : function(record){
            return this.data.indexOf(record);
        },

        indexOfId : function(id){
            return this.data.indexOfKey(id);
        },

        getById : function(id){
            return this.data.key(id);
        },

        getAt : function(index){
            return this.data.itemAt(index);
        },

        getRange : function(start, end){
            return this.data.getRange(start, end);
        },

        storeOptions : function(o){
            o = Ext.apply({}, o);
            delete o.callback;
            delete o.scope;
            this.lastOptions = o;
        },

        load : function(options){
            options = options || {};
            if(this.fireEvent("beforeload", this, options) !== false){
                this.storeOptions(options);
                var p = Ext.apply(options.params || {}, this.baseParams);
                if(this.sortInfo && this.remoteSort){
                    var pn = this.paramNames;
                    p[pn["sort"]] = this.sortInfo.field;
                    p[pn["dir"]] = this.sortInfo.direction;
                }
                this.proxy.load(p, this.reader, this.loadRecords, this, options);
                return true;
            } else {
              return false;
            }
        },

        reload : function(options){
            this.load(Ext.applyIf(options||{}, this.lastOptions));
        },

        loadRecords : function(o, options, success){
            if(!o || success === false){
                if(success !== false){
                    this.fireEvent("load", this, [], options);
                }
                if(options.callback){
                    options.callback.call(options.scope || this, [], options, false);
                }
                return;
            }
            var r = o.records, t = o.totalRecords || r.length;
            if(!options || options.add !== true){
                if(this.pruneModifiedRecords){
                    this.modified = [];
                }
                for(var i = 0, len = r.length; i < len; i++){
                    r[i].join(this);
                }
                if(this.snapshot){
                    this.data = this.snapshot;
                    delete this.snapshot;
                }
                this.data.clear();
                this.data.addAll(r);
                this.totalLength = t;
                this.applySort();
                this.fireEvent("datachanged", this);
            }else{
                this.totalLength = Math.max(t, this.data.length+r.length);
                this.add(r);
            }
            this.fireEvent("load", this, r, options);
            if(options.callback){
                options.callback.call(options.scope || this, r, options, true);
            }
        },

        loadData : function(o, append){
            var r = this.reader.readRecords(o);
            this.loadRecords(r, {add: append}, true);
        },

        getCount : function(){
            return this.data.length || 0;
        },

        getTotalCount : function(){
            return this.totalLength || 0;
        },

        getSortState : function(){
            return this.sortInfo;
        },

        applySort : function(){
            if(this.sortInfo && !this.remoteSort){
                var s = this.sortInfo, f = s.field;
                this.sortData(f, s.direction);
            }
        },

        sortData : function(f, direction){
            direction = direction || 'ASC';
            var st = this.fields.get(f).sortType;
            var fn = function(r1, r2){
                var v1 = st(r1.data[f]), v2 = st(r2.data[f]);
                return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
            };
            this.data.sort(direction, fn);
            if(this.snapshot && this.snapshot != this.data){
                this.snapshot.sort(direction, fn);
            }
        },

        setDefaultSort : function(field, dir){
            dir = dir ? dir.toUpperCase() : "ASC";
            this.sortInfo = {field: field, direction: dir};
            this.sortToggle[field] = dir;
        },

        sort : function(fieldName, dir){
            var f = this.fields.get(fieldName);
            if(!f){
                return false;
            }
            if(!dir){
                if(this.sortInfo && this.sortInfo.field == f.name){
                    dir = (this.sortToggle[f.name] || "ASC").toggle("ASC", "DESC");
                }else{
                    dir = f.sortDir;
                }
            }
            var st = (this.sortToggle) ? this.sortToggle[f.name] : null;
            var si = (this.sortInfo) ? this.sortInfo : null;

            this.sortToggle[f.name] = dir;
            this.sortInfo = {field: f.name, direction: dir};
            if(!this.remoteSort){
                this.applySort();
                this.fireEvent("datachanged", this);
            }else{
                if (!this.load(this.lastOptions)) {
                    if (st) {
                        this.sortToggle[f.name] = st;
                    }
                    if (si) {
                        this.sortInfo = si;
                    }
                }
            }
        },

        each : function(fn, scope){
            this.data.each(fn, scope);
        },

        getModifiedRecords : function(){
            return this.modified;
        },

        createFilterFn : function(property, value, anyMatch, caseSensitive){
            if(Ext.isEmpty(value, false)){
                return false;
            }
            value = this.data.createValueMatcher(value, anyMatch, caseSensitive);
            return function(r){
                return value.test(r.data[property]);
            };
        },

        sum : function(property, start, end){
            var rs = this.data.items, v = 0;
            start = start || 0;
            end = (end || end === 0) ? end : rs.length-1;

            for(var i = start; i <= end; i++){
                v += (rs[i].data[property] || 0);
            }
            return v;
        },

        filter : function(property, value, anyMatch, caseSensitive){
            var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
            return fn ? this.filterBy(fn) : this.clearFilter();
        },

        filterBy : function(fn, scope){
            this.snapshot = this.snapshot || this.data;
            this.data = this.queryBy(fn, scope||this);
            this.fireEvent("datachanged", this);
        },

        query : function(property, value, anyMatch, caseSensitive){
            var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
            return fn ? this.queryBy(fn) : this.data.clone();
        },

        queryBy : function(fn, scope){
            var data = this.snapshot || this.data;
            return data.filterBy(fn, scope||this);
        },

        find : function(property, value, start, anyMatch, caseSensitive){
            var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
            return fn ? this.data.findIndexBy(fn, null, start) : -1;
        },

        findBy : function(fn, scope, start){
            return this.data.findIndexBy(fn, scope, start);
        },

        collect : function(dataIndex, allowNull, bypassFilter){
            var d = (bypassFilter === true && this.snapshot) ?
                    this.snapshot.items : this.data.items;
            var v, sv, r = [], l = {};
            for(var i = 0, len = d.length; i < len; i++){
                v = d[i].data[dataIndex];
                sv = String(v);
                if((allowNull || !Ext.isEmpty(v)) && !l[sv]){
                    l[sv] = true;
                    r[r.length] = v;
                }
            }
            return r;
        },

        clearFilter : function(suppressEvent){
            if(this.isFiltered()){
                this.data = this.snapshot;
                delete this.snapshot;
                if(suppressEvent !== true){
                    this.fireEvent("datachanged", this);
                }
            }
        },

        isFiltered : function(){
            return this.snapshot && this.snapshot != this.data;
        },

        afterEdit : function(record){
            if(this.modified.indexOf(record) == -1){
                this.modified.push(record);
            }
            this.fireEvent("update", this, record, Ext.data.Record.EDIT);
        },

        afterReject : function(record){
            this.modified.remove(record);
            this.fireEvent("update", this, record, Ext.data.Record.REJECT);
        },

        afterCommit : function(record){
            this.modified.remove(record);
            this.fireEvent("update", this, record, Ext.data.Record.COMMIT);
        },

        commitChanges : function(){
            var m = this.modified.slice(0);
            this.modified = [];
            for(var i = 0, len = m.length; i < len; i++){
                m[i].commit();
            }
        },

        rejectChanges : function(){
            var m = this.modified.slice(0);
            this.modified = [];
            for(var i = 0, len = m.length; i < len; i++){
                m[i].reject();
            }
        },

        onMetaChange : function(meta, rtype, o){
            this.recordType = rtype;
            this.fields = rtype.prototype.fields;
            delete this.snapshot;
            this.sortInfo = meta.sortInfo;
            this.modified = [];
            this.fireEvent('metachange', this, this.reader.meta);
        },

        findInsertIndex : function(record){
            this.suspendEvents();
            var data = this.data.clone();
            this.data.add(record);
            this.applySort();
            var index = this.data.indexOf(record);
            this.data = data;
            this.resumeEvents();
            return index;
        }
    });

    Ext.data.SimpleStore = function(config){
        Ext.data.SimpleStore.superclass.constructor.call(this, Ext.apply(config, {
            reader: new Ext.data.ArrayReader({
                    id: config.id
                },
                Ext.data.Record.create(config.fields)
            )
        }));
    };
    Ext.extend(Ext.data.SimpleStore, Ext.data.Store, {
        loadData : function(data, append){
            if(this.expandData === true){
                var r = [];
                for(var i = 0, len = data.length; i < len; i++){
                    r[r.length] = [data[i]];
                }
                data = r;
            }
            Ext.data.SimpleStore.superclass.loadData.call(this, data, append);
        }
    });

    Ext.data.JsonStore = function(c){
        Ext.data.JsonStore.superclass.constructor.call(this, Ext.apply(c, {
            proxy: !c.data ? new Ext.data.HttpProxy({url: c.url}) : undefined,
            reader: new Ext.data.JsonReader(c, c.fields)
        }));
    };
    Ext.extend(Ext.data.JsonStore, Ext.data.Store);

    Ext.data.Field = function(config){
        if(typeof config == "string"){
            config = {name: config};
        }
        Ext.apply(this, config);

        if(!this.type){
            this.type = "auto";
        }

        var st = Ext.data.SortTypes;

        if(typeof this.sortType == "string"){
            this.sortType = st[this.sortType];
        }

        if(!this.sortType){
            switch(this.type){
                case "string":
                    this.sortType = st.asUCString;
                    break;
                case "date":
                    this.sortType = st.asDate;
                    break;
                default:
                    this.sortType = st.none;
            }
        }

        var stripRe = /[\$,%]/g;

        if(!this.convert){
            var cv, dateFormat = this.dateFormat;
            switch(this.type){
                case "":
                case "auto":
                case undefined:
                    cv = function(v){ return v; };
                    break;
                case "string":
                    cv = function(v){ return (v === undefined || v === null) ? '' : String(v); };
                    break;
                case "int":
                    cv = function(v){
                        return v !== undefined && v !== null && v !== '' ?
                               parseInt(String(v).replace(stripRe, ""), 10) : '';
                        };
                    break;
                case "float":
                    cv = function(v){
                        return v !== undefined && v !== null && v !== '' ?
                               parseFloat(String(v).replace(stripRe, ""), 10) : '';
                        };
                    break;
                case "bool":
                case "boolean":
                    cv = function(v){ return v === true || v === "true" || v == 1; };
                    break;
                case "date":
                    cv = function(v){
                        if(!v){
                            return '';
                        }
                        if(Ext.isDate(v)){
                            return v;
                        }
                        if(dateFormat){
                            if(dateFormat == "timestamp"){
                                return new Date(v*1000);
                            }
                            if(dateFormat == "time"){
                                return new Date(parseInt(v, 10));
                            }
                            return Date.parseDate(v, dateFormat);
                        }
                        var parsed = Date.parse(v);
                        return parsed ? new Date(parsed) : null;
                    };
                 break;

            }
            this.convert = cv;
        }
    };

    Ext.data.Field.prototype = {
        dateFormat: null,
        defaultValue: "",
        mapping: null,
        sortType : null,
        sortDir : "ASC"
    };

    Ext.data.DataReader = function(meta, recordType){

        this.meta = meta;
        this.recordType = Ext.isArray(recordType) ?
            Ext.data.Record.create(recordType) : recordType;
    };

    Ext.data.DataReader.prototype = {

    };

    Ext.data.DataProxy = function(){
        this.addEvents(

            'beforeload',

            'load',

            'loadexception'
        );
        Ext.data.DataProxy.superclass.constructor.call(this);
    };

    Ext.extend(Ext.data.DataProxy, Ext.util.Observable);

    Ext.data.MemoryProxy = function(data){
        Ext.data.MemoryProxy.superclass.constructor.call(this);
        this.data = data;
    };

    Ext.extend(Ext.data.MemoryProxy, Ext.data.DataProxy, {

        load : function(params, reader, callback, scope, arg){
            params = params || {};
            var result;
            try {
                result = reader.readRecords(this.data);
            }catch(e){
                this.fireEvent("loadexception", this, arg, null, e);
                callback.call(scope, null, arg, false);
                return;
            }
            callback.call(scope, result, arg, true);
        },

        update : function(params, records){

        }
    });

    Ext.data.HttpProxy = function(conn){
        Ext.data.HttpProxy.superclass.constructor.call(this);

        this.conn = conn;
        this.useAjax = !conn || !conn.events;
    };

    Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {

        getConnection : function(){
            return this.useAjax ? Ext.Ajax : this.conn;
        },

        load : function(params, reader, callback, scope, arg){
            if(this.fireEvent("beforeload", this, params) !== false){
                var  o = {
                    params : params || {},
                    request: {
                        callback : callback,
                        scope : scope,
                        arg : arg
                    },
                    reader: reader,
                    callback : this.loadResponse,
                    scope: this
                };
                if(this.useAjax){
                    Ext.applyIf(o, this.conn);
                    if(this.activeRequest){
                        Ext.Ajax.abort(this.activeRequest);
                    }
                    this.activeRequest = Ext.Ajax.request(o);
                }else{
                    this.conn.request(o);
                }
            }else{
                callback.call(scope||this, null, arg, false);
            }
        },

        loadResponse : function(o, success, response){
            delete this.activeRequest;
            if(!success){
                this.fireEvent("loadexception", this, o, response);
                o.request.callback.call(o.request.scope, null, o.request.arg, false);
                return;
            }
            var result;
            try {
                result = o.reader.read(response);
            }catch(e){
                this.fireEvent("loadexception", this, o, response, e);
                o.request.callback.call(o.request.scope, null, o.request.arg, false);
                return;
            }
            this.fireEvent("load", this, o, o.request.arg);
            o.request.callback.call(o.request.scope, result, o.request.arg, true);
        },

        update : function(dataSet){

        },

        updateResponse : function(dataSet){

        }
    });

    Ext.data.ScriptTagProxy = function(config){
        Ext.data.ScriptTagProxy.superclass.constructor.call(this);
        Ext.apply(this, config);
        this.head = document.getElementsByTagName("head")[0];
    };

    Ext.data.ScriptTagProxy.TRANS_ID = 1000;

    Ext.extend(Ext.data.ScriptTagProxy, Ext.data.DataProxy, {

        timeout : 30000,

        callbackParam : "callback",

        nocache : true,

        load : function(params, reader, callback, scope, arg){
            if(this.fireEvent("beforeload", this, params) !== false){

                var p = Ext.urlEncode(Ext.apply(params, this.extraParams));

                var url = this.url;
                url += (url.indexOf("?") != -1 ? "&" : "?") + p;
                if(this.nocache){
                    url += "&_dc=" + (new Date().getTime());
                }
                var transId = ++Ext.data.ScriptTagProxy.TRANS_ID;
                var trans = {
                    id : transId,
                    cb : "stcCallback"+transId,
                    scriptId : "stcScript"+transId,
                    params : params,
                    arg : arg,
                    url : url,
                    callback : callback,
                    scope : scope,
                    reader : reader
                };
                var conn = this;

                window[trans.cb] = function(o){
                    conn.handleResponse(o, trans);
                };

                url += String.format("&{0}={1}", this.callbackParam, trans.cb);

                if(this.autoAbort !== false){
                    this.abort();
                }

                trans.timeoutId = this.handleFailure.defer(this.timeout, this, [trans]);

                var script = document.createElement("script");
                script.setAttribute("src", url);
                script.setAttribute("type", "text/javascript");
                script.setAttribute("id", trans.scriptId);
                this.head.appendChild(script);

                this.trans = trans;
            }else{
                callback.call(scope||this, null, arg, false);
            }
        },

        isLoading : function(){
            return this.trans ? true : false;
        },

        abort : function(){
            if(this.isLoading()){
                this.destroyTrans(this.trans);
            }
        },

        destroyTrans : function(trans, isLoaded){
            this.head.removeChild(document.getElementById(trans.scriptId));
            clearTimeout(trans.timeoutId);
            if(isLoaded){
                window[trans.cb] = undefined;
                try{
                    delete window[trans.cb];
                }catch(e){}
            }else{

                window[trans.cb] = function(){
                    window[trans.cb] = undefined;
                    try{
                        delete window[trans.cb];
                    }catch(e){}
                };
            }
        },

        handleResponse : function(o, trans){
            this.trans = false;
            this.destroyTrans(trans, true);
            var result;
            try {
                result = trans.reader.readRecords(o);
            }catch(e){
                this.fireEvent("loadexception", this, o, trans.arg, e);
                trans.callback.call(trans.scope||window, null, trans.arg, false);
                return;
            }
            this.fireEvent("load", this, o, trans.arg);
            trans.callback.call(trans.scope||window, result, trans.arg, true);
        },

        handleFailure : function(trans){
            this.trans = false;
            this.destroyTrans(trans, false);
            this.fireEvent("loadexception", this, null, trans.arg);
            trans.callback.call(trans.scope||window, null, trans.arg, false);
        }
    });

    Ext.data.JsonReader = function(meta, recordType){
        meta = meta || {};
        Ext.data.JsonReader.superclass.constructor.call(this, meta, recordType || meta.fields);
    };
    Ext.extend(Ext.data.JsonReader, Ext.data.DataReader, {

        read : function(response){
            var json = response.responseText;
            var o = eval("("+json+")");
            if(!o) {
                throw {message: "JsonReader.read: Json object not found"};
            }
            if(o.metaData){
                delete this.ef;
                this.meta = o.metaData;
                this.recordType = Ext.data.Record.create(o.metaData.fields);
                this.onMetaChange(this.meta, this.recordType, o);
            }
            return this.readRecords(o);
        },

        onMetaChange : function(meta, recordType, o){

        },

        simpleAccess: function(obj, subsc) {
        	return obj[subsc];
        },

        getJsonAccessor: function(){
            var re = /[\[\.]/;
            return function(expr) {
                try {
                    return(re.test(expr))
                        ? new Function("obj", "return obj." + expr)
                        : function(obj){
                            return obj[expr];
                        };
                } catch(e){}
                return Ext.emptyFn;
            };
        }(),

        readRecords : function(o){

            this.jsonData = o;
            var s = this.meta, Record = this.recordType,
                f = Record.prototype.fields, fi = f.items, fl = f.length;

            if (!this.ef) {
                if(s.totalProperty) {
    	            this.getTotal = this.getJsonAccessor(s.totalProperty);
    	        }
    	        if(s.successProperty) {
    	            this.getSuccess = this.getJsonAccessor(s.successProperty);
    	        }
    	        this.getRoot = s.root ? this.getJsonAccessor(s.root) : function(p){return p;};
    	        if (s.id) {
    	        	var g = this.getJsonAccessor(s.id);
    	        	this.getId = function(rec) {
    	        		var r = g(rec);
    		        	return (r === undefined || r === "") ? null : r;
    	        	};
    	        } else {
    	        	this.getId = function(){return null;};
    	        }
                this.ef = [];
                for(var i = 0; i < fl; i++){
                    f = fi[i];
                    var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;
                    this.ef[i] = this.getJsonAccessor(map);
                }
            }

        	var root = this.getRoot(o), c = root.length, totalRecords = c, success = true;
        	if(s.totalProperty){
                var v = parseInt(this.getTotal(o), 10);
                if(!isNaN(v)){
                    totalRecords = v;
                }
            }
            if(s.successProperty){
                var v = this.getSuccess(o);
                if(v === false || v === 'false'){
                    success = false;
                }
            }
            var records = [];
    	    for(var i = 0; i < c; i++){
    		    var n = root[i];
    	        var values = {};
    	        var id = this.getId(n);
    	        for(var j = 0; j < fl; j++){
    	            f = fi[j];
                    var v = this.ef[j](n);
                    values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue, n);
    	        }
    	        var record = new Record(values, id);
    	        record.json = n;
    	        records[i] = record;
    	    }
    	    return {
    	        success : success,
    	        records : records,
    	        totalRecords : totalRecords
    	    };
        }
    });

    Ext.data.XmlReader = function(meta, recordType){
        meta = meta || {};
        Ext.data.XmlReader.superclass.constructor.call(this, meta, recordType || meta.fields);
    };
    Ext.extend(Ext.data.XmlReader, Ext.data.DataReader, {

        read : function(response){
            var doc = response.responseXML;
            if(!doc) {
                throw {message: "XmlReader.read: XML Document not available"};
            }
            return this.readRecords(doc);
        },

        readRecords : function(doc){

            this.xmlData = doc;
            var root = doc.documentElement || doc;
        	var q = Ext.DomQuery;
        	var recordType = this.recordType, fields = recordType.prototype.fields;
        	var sid = this.meta.id;
        	var totalRecords = 0, success = true;
        	if(this.meta.totalRecords){
        	    totalRecords = q.selectNumber(this.meta.totalRecords, root, 0);
        	}

            if(this.meta.success){
                var sv = q.selectValue(this.meta.success, root, true);
                success = sv !== false && sv !== 'false';
        	}
        	var records = [];
        	var ns = q.select(this.meta.record, root);
            for(var i = 0, len = ns.length; i < len; i++) {
    	        var n = ns[i];
    	        var values = {};
    	        var id = sid ? q.selectValue(sid, n) : undefined;
    	        for(var j = 0, jlen = fields.length; j < jlen; j++){
    	            var f = fields.items[j];
                    var v = q.selectValue(f.mapping || f.name, n, f.defaultValue);
    	            v = f.convert(v, n);
    	            values[f.name] = v;
    	        }
    	        var record = new recordType(values, id);
    	        record.node = n;
    	        records[records.length] = record;
    	    }

    	    return {
    	        success : success,
    	        records : records,
    	        totalRecords : totalRecords || records.length
    	    };
        }
    });

    Ext.data.ArrayReader = Ext.extend(Ext.data.JsonReader, {

        readRecords : function(o){
            var sid = this.meta ? this.meta.id : null;
        	var recordType = this.recordType, fields = recordType.prototype.fields;
        	var records = [];
        	var root = o;
    	    for(var i = 0; i < root.length; i++){
    		    var n = root[i];
    	        var values = {};
    	        var id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null);
    	        for(var j = 0, jlen = fields.length; j < jlen; j++){
                    var f = fields.items[j];
                    var k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j;
                    var v = n[k] !== undefined ? n[k] : f.defaultValue;
                    v = f.convert(v, n);
                    values[f.name] = v;
                }
    	        var record = new recordType(values, id);
    	        record.json = n;
    	        records[records.length] = record;
    	    }
    	    return {
    	        records : records,
    	        totalRecords : records.length
    	    };
        }
    });

    Ext.data.Tree = function(root){
       this.nodeHash = {};

       this.root = null;
       if(root){
           this.setRootNode(root);
       }
       this.addEvents(

           "append",

           "remove",

           "move",

           "insert",

           "beforeappend",

           "beforeremove",

           "beforemove",

           "beforeinsert"
       );

        Ext.data.Tree.superclass.constructor.call(this);
    };

    Ext.extend(Ext.data.Tree, Ext.util.Observable, {

        pathSeparator: "/",

        proxyNodeEvent : function(){
            return this.fireEvent.apply(this, arguments);
        },

        getRootNode : function(){
            return this.root;
        },

        setRootNode : function(node){
            this.root = node;
            node.ownerTree = this;
            node.isRoot = true;
            this.registerNode(node);
            return node;
        },

        getNodeById : function(id){
            return this.nodeHash[id];
        },

        registerNode : function(node){
            this.nodeHash[node.id] = node;
        },

        unregisterNode : function(node){
            delete this.nodeHash[node.id];
        },

        toString : function(){
            return "[Tree"+(this.id?" "+this.id:"")+"]";
        }
    });

    Ext.data.Node = function(attributes){

        this.attributes = attributes || {};
        this.leaf = this.attributes.leaf;

        this.id = this.attributes.id;
        if(!this.id){
            this.id = Ext.id(null, "ynode-");
            this.attributes.id = this.id;
        }

        this.childNodes = [];
        if(!this.childNodes.indexOf){
            this.childNodes.indexOf = function(o){
                for(var i = 0, len = this.length; i < len; i++){
                    if(this[i] == o) return i;
                }
                return -1;
            };
        }

        this.parentNode = null;

        this.firstChild = null;

        this.lastChild = null;

        this.previousSibling = null;

        this.nextSibling = null;

        this.addEvents({

           "append" : true,

           "remove" : true,

           "move" : true,

           "insert" : true,

           "beforeappend" : true,

           "beforeremove" : true,

           "beforemove" : true,

           "beforeinsert" : true
       });
        this.listeners = this.attributes.listeners;
        Ext.data.Node.superclass.constructor.call(this);
    };

    Ext.extend(Ext.data.Node, Ext.util.Observable, {

        fireEvent : function(evtName){

            if(Ext.data.Node.superclass.fireEvent.apply(this, arguments) === false){
                return false;
            }

            var ot = this.getOwnerTree();
            if(ot){
                if(ot.proxyNodeEvent.apply(ot, arguments) === false){
                    return false;
                }
            }
            return true;
        },

        isLeaf : function(){
            return this.leaf === true;
        },

        setFirstChild : function(node){
            this.firstChild = node;
        },

        setLastChild : function(node){
            this.lastChild = node;
        },

        isLast : function(){
           return (!this.parentNode ? true : this.parentNode.lastChild == this);
        },

        isFirst : function(){
           return (!this.parentNode ? true : this.parentNode.firstChild == this);
        },

        hasChildNodes : function(){
            return !this.isLeaf() && this.childNodes.length > 0;
        },

        appendChild : function(node){
            var multi = false;
            if(Ext.isArray(node)){
                multi = node;
            }else if(arguments.length > 1){
                multi = arguments;
            }

            if(multi){
                for(var i = 0, len = multi.length; i < len; i++) {
                	this.appendChild(multi[i]);
                }
            }else{
                if(this.fireEvent("beforeappend", this.ownerTree, this, node) === false){
                    return false;
                }
                var index = this.childNodes.length;
                var oldParent = node.parentNode;

                if(oldParent){
                    if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index) === false){
                        return false;
                    }
                    oldParent.removeChild(node);
                }
                index = this.childNodes.length;
                if(index == 0){
                    this.setFirstChild(node);
                }
                this.childNodes.push(node);
                node.parentNode = this;
                var ps = this.childNodes[index-1];
                if(ps){
                    node.previousSibling = ps;
                    ps.nextSibling = node;
                }else{
                    node.previousSibling = null;
                }
                node.nextSibling = null;
                this.setLastChild(node);
                node.setOwnerTree(this.getOwnerTree());
                this.fireEvent("append", this.ownerTree, this, node, index);
                if(oldParent){
                    node.fireEvent("move", this.ownerTree, node, oldParent, this, index);
                }
                return node;
            }
        },

        removeChild : function(node){
            var index = this.childNodes.indexOf(node);
            if(index == -1){
                return false;
            }
            if(this.fireEvent("beforeremove", this.ownerTree, this, node) === false){
                return false;
            }

            this.childNodes.splice(index, 1);

            if(node.previousSibling){
                node.previousSibling.nextSibling = node.nextSibling;
            }
            if(node.nextSibling){
                node.nextSibling.previousSibling = node.previousSibling;
            }

            if(this.firstChild == node){
                this.setFirstChild(node.nextSibling);
            }
            if(this.lastChild == node){
                this.setLastChild(node.previousSibling);
            }

            node.setOwnerTree(null);

            node.parentNode = null;
            node.previousSibling = null;
            node.nextSibling = null;
            this.fireEvent("remove", this.ownerTree, this, node);
            return node;
        },

        insertBefore : function(node, refNode){
            if(!refNode){
                return this.appendChild(node);
            }

            if(node == refNode){
                return false;
            }

            if(this.fireEvent("beforeinsert", this.ownerTree, this, node, refNode) === false){
                return false;
            }
            var index = this.childNodes.indexOf(refNode);
            var oldParent = node.parentNode;
            var refIndex = index;

            if(oldParent == this && this.childNodes.indexOf(node) < index){
                refIndex--;
            }

            if(oldParent){
                if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index, refNode) === false){
                    return false;
                }
                oldParent.removeChild(node);
            }
            if(refIndex == 0){
                this.setFirstChild(node);
            }
            this.childNodes.splice(refIndex, 0, node);
            node.parentNode = this;
            var ps = this.childNodes[refIndex-1];
            if(ps){
                node.previousSibling = ps;
                ps.nextSibling = node;
            }else{
                node.previousSibling = null;
            }
            node.nextSibling = refNode;
            refNode.previousSibling = node;
            node.setOwnerTree(this.getOwnerTree());
            this.fireEvent("insert", this.ownerTree, this, node, refNode);
            if(oldParent){
                node.fireEvent("move", this.ownerTree, node, oldParent, this, refIndex, refNode);
            }
            return node;
        },

        remove : function(){
            this.parentNode.removeChild(this);
            return this;
        },

        item : function(index){
            return this.childNodes[index];
        },

        replaceChild : function(newChild, oldChild){
            this.insertBefore(newChild, oldChild);
            this.removeChild(oldChild);
            return oldChild;
        },

        indexOf : function(child){
            return this.childNodes.indexOf(child);
        },

        getOwnerTree : function(){

            if(!this.ownerTree){
                var p = this;
                while(p){
                    if(p.ownerTree){
                        this.ownerTree = p.ownerTree;
                        break;
                    }
                    p = p.parentNode;
                }
            }
            return this.ownerTree;
        },

        getDepth : function(){
            var depth = 0;
            var p = this;
            while(p.parentNode){
                ++depth;
                p = p.parentNode;
            }
            return depth;
        },

        setOwnerTree : function(tree){

            if(tree != this.ownerTree){
                if(this.ownerTree){
                    this.ownerTree.unregisterNode(this);
                }
                this.ownerTree = tree;
                var cs = this.childNodes;
                for(var i = 0, len = cs.length; i < len; i++) {
                	cs[i].setOwnerTree(tree);
                }
                if(tree){
                    tree.registerNode(this);
                }
            }
        },

        getPath : function(attr){
            attr = attr || "id";
            var p = this.parentNode;
            var b = [this.attributes[attr]];
            while(p){
                b.unshift(p.attributes[attr]);
                p = p.parentNode;
            }
            var sep = this.getOwnerTree().pathSeparator;
            return sep + b.join(sep);
        },

        bubble : function(fn, scope, args){
            var p = this;
            while(p){
                if(fn.apply(scope || p, args || [p]) === false){
                    break;
                }
                p = p.parentNode;
            }
        },

        cascade : function(fn, scope, args){
            if(fn.apply(scope || this, args || [this]) !== false){
                var cs = this.childNodes;
                for(var i = 0, len = cs.length; i < len; i++) {
                	cs[i].cascade(fn, scope, args);
                }
            }
        },

        eachChild : function(fn, scope, args){
            var cs = this.childNodes;
            for(var i = 0, len = cs.length; i < len; i++) {
            	if(fn.apply(scope || this, args || [cs[i]]) === false){
            	    break;
            	}
            }
        },

        findChild : function(attribute, value){
            var cs = this.childNodes;
            for(var i = 0, len = cs.length; i < len; i++) {
            	if(cs[i].attributes[attribute] == value){
            	    return cs[i];
            	}
            }
            return null;
        },

        findChildBy : function(fn, scope){
            var cs = this.childNodes;
            for(var i = 0, len = cs.length; i < len; i++) {
            	if(fn.call(scope||cs[i], cs[i]) === true){
            	    return cs[i];
            	}
            }
            return null;
        },

        sort : function(fn, scope){
            var cs = this.childNodes;
            var len = cs.length;
            if(len > 0){
                var sortFn = scope ? function(){fn.apply(scope, arguments);} : fn;
                cs.sort(sortFn);
                for(var i = 0; i < len; i++){
                    var n = cs[i];
                    n.previousSibling = cs[i-1];
                    n.nextSibling = cs[i+1];
                    if(i == 0){
                        this.setFirstChild(n);
                    }
                    if(i == len-1){
                        this.setLastChild(n);
                    }
                }
            }
        },

        contains : function(node){
            return node.isAncestor(this);
        },

        isAncestor : function(node){
            var p = this.parentNode;
            while(p){
                if(p == node){
                    return true;
                }
                p = p.parentNode;
            }
            return false;
        },

        toString : function(){
            return "[Node"+(this.id?" "+this.id:"")+"]";
        }
    });

    Ext.data.GroupingStore = Ext.extend(Ext.data.Store, {

        remoteGroup : false,

        groupOnSort:false,

        clearGrouping : function(){
            this.groupField = false;
            if(this.remoteGroup){
                if(this.baseParams){
                    delete this.baseParams.groupBy;
                }
                this.reload();
            }else{
                this.applySort();
                this.fireEvent('datachanged', this);
            }
        },

        groupBy : function(field, forceRegroup){
            if(this.groupField == field && !forceRegroup){
                return;
            }
            this.groupField = field;
            if(this.remoteGroup){
                if(!this.baseParams){
                    this.baseParams = {};
                }
                this.baseParams['groupBy'] = field;
            }
            if(this.groupOnSort){
                this.sort(field);
                return;
            }
            if(this.remoteGroup){
                this.reload();
            }else{
                var si = this.sortInfo || {};
                if(si.field != field){
                    this.applySort();
                }else{
                    this.sortData(field);
                }
                this.fireEvent('datachanged', this);
            }
        },

        applySort : function(){
            Ext.data.GroupingStore.superclass.applySort.call(this);
            if(!this.groupOnSort && !this.remoteGroup){
                var gs = this.getGroupState();
                if(gs && gs != this.sortInfo.field){
                    this.sortData(this.groupField);
                }
            }
        },

        applyGrouping : function(alwaysFireChange){
            if(this.groupField !== false){
                this.groupBy(this.groupField, true);
                return true;
            }else{
                if(alwaysFireChange === true){
                    this.fireEvent('datachanged', this);
                }
                return false;
            }
        },

        getGroupState : function(){
            return this.groupOnSort && this.groupField !== false ?
                   (this.sortInfo ? this.sortInfo.field : undefined) : this.groupField;
        }
    });

    Ext.ComponentMgr = function(){
        var all = new Ext.util.MixedCollection();
        var types = {};

        return {

            register : function(c){
                all.add(c);
            },

            unregister : function(c){
                all.remove(c);
            },

            get : function(id){
                return all.get(id);
            },

            onAvailable : function(id, fn, scope){
                all.on("add", function(index, o){
                    if(o.id == id){
                        fn.call(scope || o, o);
                        all.un("add", fn, scope);
                    }
                });
            },

            all : all,

            registerType : function(xtype, cls){
                types[xtype] = cls;
                cls.xtype = xtype;
            },

            create : function(config, defaultType){
                return new types[config.xtype || defaultType](config);
            }
        };
    }();

    Ext.reg = Ext.ComponentMgr.registerType;

    Ext.Component = function(config){
        config = config || {};
        if(config.initialConfig){
            if(config.isAction){                       this.baseAction = config;
            }
            config = config.initialConfig;     }else if(config.tagName || config.dom || typeof config == "string"){         config = {applyTo: config, id: config.id || config};
        }

        this.initialConfig = config;

        Ext.apply(this, config);
        this.addEvents(

            'disable',

            'enable',

            'beforeshow',

            'show',

            'beforehide',

            'hide',

            'beforerender',

            'render',

            'beforedestroy',

            'destroy',

            'beforestaterestore',

            'staterestore',

            'beforestatesave',

            'statesave'
        );
        this.getId();
        Ext.ComponentMgr.register(this);
        Ext.Component.superclass.constructor.call(this);

        if(this.baseAction){
            this.baseAction.addComponent(this);
        }

        this.initComponent();

        if(this.plugins){
            if(Ext.isArray(this.plugins)){
                for(var i = 0, len = this.plugins.length; i < len; i++){
                    this.plugins[i].init(this);
                }
            }else{
                this.plugins.init(this);
            }
        }

        if(this.stateful !== false){
            this.initState(config);
        }

        if(this.applyTo){
            this.applyToMarkup(this.applyTo);
            delete this.applyTo;
        }else if(this.renderTo){
            this.render(this.renderTo);
            delete this.renderTo;
        }
    };

    Ext.Component.AUTO_ID = 1000;

    Ext.extend(Ext.Component, Ext.util.Observable, {

        disabledClass : "x-item-disabled",

        allowDomMove : true,

        autoShow : false,

        hideMode: 'display',

        hideParent: false,

        hidden : false,

        disabled : false,

        rendered : false,

            ctype : "Ext.Component",

            actionMode : "el",

            getActionEl : function(){
            return this[this.actionMode];
        },

        initComponent : Ext.emptyFn,

        render : function(container, position){
            if(!this.rendered && this.fireEvent("beforerender", this) !== false){
                if(!container && this.el){
                    this.el = Ext.get(this.el);
                    container = this.el.dom.parentNode;
                    this.allowDomMove = false;
                }
                this.container = Ext.get(container);
                if(this.ctCls){
                    this.container.addClass(this.ctCls);
                }
                this.rendered = true;
                if(position !== undefined){
                    if(typeof position == 'number'){
                        position = this.container.dom.childNodes[position];
                    }else{
                        position = Ext.getDom(position);
                    }
                }
                this.onRender(this.container, position || null);
                if(this.autoShow){
                    this.el.removeClass(['x-hidden','x-hide-' + this.hideMode]);
                }
                if(this.cls){
                    this.el.addClass(this.cls);
                    delete this.cls;
                }
                if(this.style){
                    this.el.applyStyles(this.style);
                    delete this.style;
                }
                this.fireEvent("render", this);
                this.afterRender(this.container);
                if(this.hidden){
                    this.hide();
                }
                if(this.disabled){
                    this.disable();
                }

                this.initStateEvents();
            }
            return this;
        },

            initState : function(config){
            if(Ext.state.Manager){
                var state = Ext.state.Manager.get(this.stateId || this.id);
                if(state){
                    if(this.fireEvent('beforestaterestore', this, state) !== false){
                        this.applyState(state);
                        this.fireEvent('staterestore', this, state);
                    }
                }
            }
        },

            initStateEvents : function(){
            if(this.stateEvents){
                for(var i = 0, e; e = this.stateEvents[i]; i++){
                    this.on(e, this.saveState, this, {delay:100});
                }
            }
        },

            applyState : function(state, config){
            if(state){
                Ext.apply(this, state);
            }
        },

            getState : function(){
            return null;
        },

            saveState : function(){
            if(Ext.state.Manager){
                var state = this.getState();
                if(this.fireEvent('beforestatesave', this, state) !== false){
                    Ext.state.Manager.set(this.stateId || this.id, state);
                    this.fireEvent('statesave', this, state);
                }
            }
        },

        applyToMarkup : function(el){
            this.allowDomMove = false;
            this.el = Ext.get(el);
            this.render(this.el.dom.parentNode);
        },

        addClass : function(cls){
            if(this.el){
                this.el.addClass(cls);
            }else{
                this.cls = this.cls ? this.cls + ' ' + cls : cls;
            }
        },

        removeClass : function(cls){
            if(this.el){
                this.el.removeClass(cls);
            }else if(this.cls){
                this.cls = this.cls.split(' ').remove(cls).join(' ');
            }
        },

                onRender : function(ct, position){
            if(this.autoEl){
                if(typeof this.autoEl == 'string'){
                    this.el = document.createElement(this.autoEl);
                }else{
                    var div = document.createElement('div');
                    Ext.DomHelper.overwrite(div, this.autoEl);
                    this.el = div.firstChild;
                }
                if (!this.el.id) {
                	this.el.id = this.getId();
                }
            }
            if(this.el){
                this.el = Ext.get(this.el);
                if(this.allowDomMove !== false){
                    ct.dom.insertBefore(this.el.dom, position);
                }
            }
        },

            getAutoCreate : function(){
            var cfg = typeof this.autoCreate == "object" ?
                          this.autoCreate : Ext.apply({}, this.defaultAutoCreate);
            if(this.id && !cfg.id){
                cfg.id = this.id;
            }
            return cfg;
        },

            afterRender : Ext.emptyFn,

        destroy : function(){
            if(this.fireEvent("beforedestroy", this) !== false){
                this.beforeDestroy();
                if(this.rendered){
                    this.el.removeAllListeners();
                    this.el.remove();
                    if(this.actionMode == "container"){
                        this.container.remove();
                    }
                }
                this.onDestroy();
                Ext.ComponentMgr.unregister(this);
                this.fireEvent("destroy", this);
                this.purgeListeners();
            }
        },

    	    beforeDestroy : Ext.emptyFn,

    	    onDestroy  : Ext.emptyFn,

        getEl : function(){
            return this.el;
        },

        getId : function(){
            return this.id || (this.id = "ext-comp-" + (++Ext.Component.AUTO_ID));
        },

        getItemId : function(){
            return this.itemId || this.getId();
        },

        focus : function(selectText, delay){
            if(delay){
                this.focus.defer(typeof delay == 'number' ? delay : 10, this, [selectText, false]);
                return;
            }
            if(this.rendered){
                this.el.focus();
                if(selectText === true){
                    this.el.dom.select();
                }
            }
            return this;
        },

            blur : function(){
            if(this.rendered){
                this.el.blur();
            }
            return this;
        },

        disable : function(){
            if(this.rendered){
                this.onDisable();
            }
            this.disabled = true;
            this.fireEvent("disable", this);
            return this;
        },

    	    onDisable : function(){
            this.getActionEl().addClass(this.disabledClass);
            this.el.dom.disabled = true;
        },

        enable : function(){
            if(this.rendered){
                this.onEnable();
            }
            this.disabled = false;
            this.fireEvent("enable", this);
            return this;
        },

    	    onEnable : function(){
            this.getActionEl().removeClass(this.disabledClass);
            this.el.dom.disabled = false;
        },

        setDisabled : function(disabled){
            this[disabled ? "disable" : "enable"]();
        },

        show: function(){
            if(this.fireEvent("beforeshow", this) !== false){
                this.hidden = false;
                if(this.autoRender){
                    this.render(typeof this.autoRender == 'boolean' ? Ext.getBody() : this.autoRender);
                }
                if(this.rendered){
                    this.onShow();
                }
                this.fireEvent("show", this);
            }
            return this;
        },

            onShow : function(){
            if(this.hideParent){
                this.container.removeClass('x-hide-' + this.hideMode);
            }else{
                this.getActionEl().removeClass('x-hide-' + this.hideMode);
            }

        },

        hide: function(){
            if(this.fireEvent("beforehide", this) !== false){
                this.hidden = true;
                if(this.rendered){
                    this.onHide();
                }
                this.fireEvent("hide", this);
            }
            return this;
        },

            onHide : function(){
            if(this.hideParent){
                this.container.addClass('x-hide-' + this.hideMode);
            }else{
                this.getActionEl().addClass('x-hide-' + this.hideMode);
            }
        },

        setVisible: function(visible){
            if(visible) {
                this.show();
            }else{
                this.hide();
            }
            return this;
        },

        isVisible : function(){
            return this.rendered && this.getActionEl().isVisible();
        },

        cloneConfig : function(overrides){
            overrides = overrides || {};
            var id = overrides.id || Ext.id();
            var cfg = Ext.applyIf(overrides, this.initialConfig);
            cfg.id = id;         return new this.constructor(cfg);
        },

        getXType : function(){
            return this.constructor.xtype;
        },

        isXType : function(xtype, shallow){
            return !shallow ?
                   ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1 :
                    this.constructor.xtype == xtype;
        },

        getXTypes : function(){
            var tc = this.constructor;
            if(!tc.xtypes){
                var c = [], sc = this;
                while(sc && sc.constructor.xtype){
                    c.unshift(sc.constructor.xtype);
                    sc = sc.constructor.superclass;
                }
                tc.xtypeChain = c;
                tc.xtypes = c.join('/');
            }
            return tc.xtypes;
        },

        findParentBy: function(fn) {
            for (var p = this.ownerCt; (p != null) && !fn(p, this); p = p.ownerCt);
            return p || null;
        },

        findParentByType: function(xtype) {
            return typeof xtype == 'function' ?
                this.findParentBy(function(p){
                    return p.constructor === xtype;
                }) :
                this.findParentBy(function(p){
                    return p.constructor.xtype === xtype;
                });
        }
    });

    Ext.reg('component', Ext.Component);

    Ext.Action = function(config){
        this.initialConfig = config;
        this.items = [];
    }

    Ext.Action.prototype = {

        isAction : true,

        setText : function(text){
            this.initialConfig.text = text;
            this.callEach('setText', [text]);
        },

        getText : function(){
            return this.initialConfig.text;
        },

        setIconClass : function(cls){
            this.initialConfig.iconCls = cls;
            this.callEach('setIconClass', [cls]);
        },

        getIconClass : function(){
            return this.initialConfig.iconCls;
        },

        setDisabled : function(v){
            this.initialConfig.disabled = v;
            this.callEach('setDisabled', [v]);
        },

        enable : function(){
            this.setDisabled(false);
        },

        disable : function(){
            this.setDisabled(true);
        },

        isDisabled : function(){
            return this.initialConfig.disabled;
        },

        setHidden : function(v){
            this.initialConfig.hidden = v;
            this.callEach('setVisible', [!v]);
        },

        show : function(){
            this.setHidden(false);
        },

        hide : function(){
            this.setHidden(true);
        },

        isHidden : function(){
            return this.initialConfig.hidden;
        },

        setHandler : function(fn, scope){
            this.initialConfig.handler = fn;
            this.initialConfig.scope = scope;
            this.callEach('setHandler', [fn, scope]);
        },

        each : function(fn, scope){
            Ext.each(this.items, fn, scope);
        },

        callEach : function(fnName, args){
            var cs = this.items;
            for(var i = 0, len = cs.length; i < len; i++){
                cs[i][fnName].apply(cs[i], args);
            }
        },

        addComponent : function(comp){
            this.items.push(comp);
            comp.on('destroy', this.removeComponent, this);
        },

        removeComponent : function(comp){
            this.items.remove(comp);
        },

        execute : function(){
            this.initialConfig.handler.apply(this.initialConfig.scope || window, arguments);
        }
    };

    (function(){
    Ext.Layer = function(config, existingEl){
        config = config || {};
        var dh = Ext.DomHelper;
        var cp = config.parentEl, pel = cp ? Ext.getDom(cp) : document.body;
        if(existingEl){
            this.dom = Ext.getDom(existingEl);
        }
        if(!this.dom){
            var o = config.dh || {tag: "div", cls: "x-layer"};
            this.dom = dh.append(pel, o);
        }
        if(config.cls){
            this.addClass(config.cls);
        }
        this.constrain = config.constrain !== false;
        this.visibilityMode = Ext.Element.VISIBILITY;
        if(config.id){
            this.id = this.dom.id = config.id;
        }else{
            this.id = Ext.id(this.dom);
        }
        this.zindex = config.zindex || this.getZIndex();
        this.position("absolute", this.zindex);
        if(config.shadow){
            this.shadowOffset = config.shadowOffset || 4;
            this.shadow = new Ext.Shadow({
                offset : this.shadowOffset,
                mode : config.shadow
            });
        }else{
            this.shadowOffset = 0;
        }
        this.useShim = config.shim !== false && Ext.useShims;
        this.useDisplay = config.useDisplay;
        this.hide();
    };

    var supr = Ext.Element.prototype;

    var shims = [];

    Ext.extend(Ext.Layer, Ext.Element, {

        getZIndex : function(){
            return this.zindex || parseInt(this.getStyle("z-index"), 10) || 11000;
        },

        getShim : function(){
            if(!this.useShim){
                return null;
            }
            if(this.shim){
                return this.shim;
            }
            var shim = shims.shift();
            if(!shim){
                shim = this.createShim();
                shim.enableDisplayMode('block');
                shim.dom.style.display = 'none';
                shim.dom.style.visibility = 'visible';
            }
            var pn = this.dom.parentNode;
            if(shim.dom.parentNode != pn){
                pn.insertBefore(shim.dom, this.dom);
            }
            shim.setStyle('z-index', this.getZIndex()-2);
            this.shim = shim;
            return shim;
        },

        hideShim : function(){
            if(this.shim){
                this.shim.setDisplayed(false);
                shims.push(this.shim);
                delete this.shim;
            }
        },

        disableShadow : function(){
            if(this.shadow){
                this.shadowDisabled = true;
                this.shadow.hide();
                this.lastShadowOffset = this.shadowOffset;
                this.shadowOffset = 0;
            }
        },

        enableShadow : function(show){
            if(this.shadow){
                this.shadowDisabled = false;
                this.shadowOffset = this.lastShadowOffset;
                delete this.lastShadowOffset;
                if(show){
                    this.sync(true);
                }
            }
        },

        sync : function(doShow){
            var sw = this.shadow;
            if(!this.updating && this.isVisible() && (sw || this.useShim)){
                var sh = this.getShim();

                var w = this.getWidth(),
                    h = this.getHeight();

                var l = this.getLeft(true),
                    t = this.getTop(true);

                if(sw && !this.shadowDisabled){
                    if(doShow && !sw.isVisible()){
                        sw.show(this);
                    }else{
                        sw.realign(l, t, w, h);
                    }
                    if(sh){
                        if(doShow){
                           sh.show();
                        }

                        var a = sw.adjusts, s = sh.dom.style;
                        s.left = (Math.min(l, l+a.l))+"px";
                        s.top = (Math.min(t, t+a.t))+"px";
                        s.width = (w+a.w)+"px";
                        s.height = (h+a.h)+"px";
                    }
                }else if(sh){
                    if(doShow){
                       sh.show();
                    }
                    sh.setSize(w, h);
                    sh.setLeftTop(l, t);
                }

            }
        },

        destroy : function(){
            this.hideShim();
            if(this.shadow){
                this.shadow.hide();
            }
            this.removeAllListeners();
            Ext.removeNode(this.dom);
            Ext.Element.uncache(this.id);
        },

        remove : function(){
            this.destroy();
        },

        beginUpdate : function(){
            this.updating = true;
        },

        endUpdate : function(){
            this.updating = false;
            this.sync(true);
        },

        hideUnders : function(negOffset){
            if(this.shadow){
                this.shadow.hide();
            }
            this.hideShim();
        },

        constrainXY : function(){
            if(this.constrain){
                var vw = Ext.lib.Dom.getViewWidth(),
                    vh = Ext.lib.Dom.getViewHeight();
                var s = Ext.getDoc().getScroll();

                var xy = this.getXY();
                var x = xy[0], y = xy[1];
                var w = this.dom.offsetWidth+this.shadowOffset, h = this.dom.offsetHeight+this.shadowOffset;

                var moved = false;

                if((x + w) > vw+s.left){
                    x = vw - w - this.shadowOffset;
                    moved = true;
                }
                if((y + h) > vh+s.top){
                    y = vh - h - this.shadowOffset;
                    moved = true;
                }

                if(x < s.left){
                    x = s.left;
                    moved = true;
                }
                if(y < s.top){
                    y = s.top;
                    moved = true;
                }
                if(moved){
                    if(this.avoidY){
                        var ay = this.avoidY;
                        if(y <= ay && (y+h) >= ay){
                            y = ay-h-5;
                        }
                    }
                    xy = [x, y];
                    this.storeXY(xy);
                    supr.setXY.call(this, xy);
                    this.sync();
                }
            }
        },

        isVisible : function(){
            return this.visible;
        },

        showAction : function(){
            this.visible = true;
            if(this.useDisplay === true){
                this.setDisplayed("");
            }else if(this.lastXY){
                supr.setXY.call(this, this.lastXY);
            }else if(this.lastLT){
                supr.setLeftTop.call(this, this.lastLT[0], this.lastLT[1]);
            }
        },

        hideAction : function(){
            this.visible = false;
            if(this.useDisplay === true){
                this.setDisplayed(false);
            }else{
                this.setLeftTop(-10000,-10000);
            }
        },

        setVisible : function(v, a, d, c, e){
            if(v){
                this.showAction();
            }
            if(a && v){
                var cb = function(){
                    this.sync(true);
                    if(c){
                        c();
                    }
                }.createDelegate(this);
                supr.setVisible.call(this, true, true, d, cb, e);
            }else{
                if(!v){
                    this.hideUnders(true);
                }
                var cb = c;
                if(a){
                    cb = function(){
                        this.hideAction();
                        if(c){
                            c();
                        }
                    }.createDelegate(this);
                }
                supr.setVisible.call(this, v, a, d, cb, e);
                if(v){
                    this.sync(true);
                }else if(!a){
                    this.hideAction();
                }
            }
        },

        storeXY : function(xy){
            delete this.lastLT;
            this.lastXY = xy;
        },

        storeLeftTop : function(left, top){
            delete this.lastXY;
            this.lastLT = [left, top];
        },

        beforeFx : function(){
            this.beforeAction();
            return Ext.Layer.superclass.beforeFx.apply(this, arguments);
        },

        afterFx : function(){
            Ext.Layer.superclass.afterFx.apply(this, arguments);
            this.sync(this.isVisible());
        },

        beforeAction : function(){
            if(!this.updating && this.shadow){
                this.shadow.hide();
            }
        },

        setLeft : function(left){
            this.storeLeftTop(left, this.getTop(true));
            supr.setLeft.apply(this, arguments);
            this.sync();
        },

        setTop : function(top){
            this.storeLeftTop(this.getLeft(true), top);
            supr.setTop.apply(this, arguments);
            this.sync();
        },

        setLeftTop : function(left, top){
            this.storeLeftTop(left, top);
            supr.setLeftTop.apply(this, arguments);
            this.sync();
        },

        setXY : function(xy, a, d, c, e){
            this.fixDisplay();
            this.beforeAction();
            this.storeXY(xy);
            var cb = this.createCB(c);
            supr.setXY.call(this, xy, a, d, cb, e);
            if(!a){
                cb();
            }
        },

        createCB : function(c){
            var el = this;
            return function(){
                el.constrainXY();
                el.sync(true);
                if(c){
                    c();
                }
            };
        },

        setX : function(x, a, d, c, e){
            this.setXY([x, this.getY()], a, d, c, e);
        },

        setY : function(y, a, d, c, e){
            this.setXY([this.getX(), y], a, d, c, e);
        },

        setSize : function(w, h, a, d, c, e){
            this.beforeAction();
            var cb = this.createCB(c);
            supr.setSize.call(this, w, h, a, d, cb, e);
            if(!a){
                cb();
            }
        },

        setWidth : function(w, a, d, c, e){
            this.beforeAction();
            var cb = this.createCB(c);
            supr.setWidth.call(this, w, a, d, cb, e);
            if(!a){
                cb();
            }
        },

        setHeight : function(h, a, d, c, e){
            this.beforeAction();
            var cb = this.createCB(c);
            supr.setHeight.call(this, h, a, d, cb, e);
            if(!a){
                cb();
            }
        },

        setBounds : function(x, y, w, h, a, d, c, e){
            this.beforeAction();
            var cb = this.createCB(c);
            if(!a){
                this.storeXY([x, y]);
                supr.setXY.call(this, [x, y]);
                supr.setSize.call(this, w, h, a, d, cb, e);
                cb();
            }else{
                supr.setBounds.call(this, x, y, w, h, a, d, cb, e);
            }
            return this;
        },

        setZIndex : function(zindex){
            this.zindex = zindex;
            this.setStyle("z-index", zindex + 2);
            if(this.shadow){
                this.shadow.setZIndex(zindex + 1);
            }
            if(this.shim){
                this.shim.setStyle("z-index", zindex);
            }
        }
    });
    })();

    Ext.Shadow = function(config){
        Ext.apply(this, config);
        if(typeof this.mode != "string"){
            this.mode = this.defaultMode;
        }
        var o = this.offset, a = {h: 0};
        var rad = Math.floor(this.offset/2);
        switch(this.mode.toLowerCase()){         case "drop":
                a.w = 0;
                a.l = a.t = o;
                a.t -= 1;
                if(Ext.isIE){
                    a.l -= this.offset + rad;
                    a.t -= this.offset + rad;
                    a.w -= rad;
                    a.h -= rad;
                    a.t += 1;
                }
            break;
            case "sides":
                a.w = (o*2);
                a.l = -o;
                a.t = o-1;
                if(Ext.isIE){
                    a.l -= (this.offset - rad);
                    a.t -= this.offset + rad;
                    a.l += 1;
                    a.w -= (this.offset - rad)*2;
                    a.w -= rad + 1;
                    a.h -= 1;
                }
            break;
            case "frame":
                a.w = a.h = (o*2);
                a.l = a.t = -o;
                a.t += 1;
                a.h -= 2;
                if(Ext.isIE){
                    a.l -= (this.offset - rad);
                    a.t -= (this.offset - rad);
                    a.l += 1;
                    a.w -= (this.offset + rad + 1);
                    a.h -= (this.offset + rad);
                    a.h += 1;
                }
            break;
        };

        this.adjusts = a;
    };

    Ext.Shadow.prototype = {

        offset: 4,

            defaultMode: "drop",

        show : function(target){
            target = Ext.get(target);
            if(!this.el){
                this.el = Ext.Shadow.Pool.pull();
                if(this.el.dom.nextSibling != target.dom){
                    this.el.insertBefore(target);
                }
            }
            this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10)-1);
            if(Ext.isIE){
                this.el.dom.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius="+(this.offset)+")";
            }
            this.realign(
                target.getLeft(true),
                target.getTop(true),
                target.getWidth(),
                target.getHeight()
            );
            this.el.dom.style.display = "block";
        },

        isVisible : function(){
            return this.el ? true : false;
        },

        realign : function(l, t, w, h){
            if(!this.el){
                return;
            }
            var a = this.adjusts, d = this.el.dom, s = d.style;
            var iea = 0;
            s.left = (l+a.l)+"px";
            s.top = (t+a.t)+"px";
            var sw = (w+a.w), sh = (h+a.h), sws = sw +"px", shs = sh + "px";
            if(s.width != sws || s.height != shs){
                s.width = sws;
                s.height = shs;
                if(!Ext.isIE){
                    var cn = d.childNodes;
                    var sww = Math.max(0, (sw-12))+"px";
                    cn[0].childNodes[1].style.width = sww;
                    cn[1].childNodes[1].style.width = sww;
                    cn[2].childNodes[1].style.width = sww;
                    cn[1].style.height = Math.max(0, (sh-12))+"px";
                }
            }
        },

        hide : function(){
            if(this.el){
                this.el.dom.style.display = "none";
                Ext.Shadow.Pool.push(this.el);
                delete this.el;
            }
        },

        setZIndex : function(z){
            this.zIndex = z;
            if(this.el){
                this.el.setStyle("z-index", z);
            }
        }
    };

    Ext.Shadow.Pool = function(){
        var p = [];
        var markup = Ext.isIE ?
                     '' :
                     '';
        return {
            pull : function(){
                var sh = p.shift();
                if(!sh){
                    sh = Ext.get(Ext.DomHelper.insertHtml("beforeBegin", document.body.firstChild, markup));
                    sh.autoBoxAdjust = false;
                }
                return sh;
            },

            push : function(sh){
                p.push(sh);
            }
        };
    }();

    Ext.BoxComponent = Ext.extend(Ext.Component, {

        initComponent : function(){
            Ext.BoxComponent.superclass.initComponent.call(this);
            this.addEvents(

                'resize',

                'move'
            );
        },

            boxReady : false,
            deferHeight: false,

        setSize : function(w, h){
                    if(typeof w == 'object'){
                h = w.height;
                w = w.width;
            }
                    if(!this.boxReady){
                this.width = w;
                this.height = h;
                return this;
            }

                    if(this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
                return this;
            }
            this.lastSize = {width: w, height: h};
            var adj = this.adjustSize(w, h);
            var aw = adj.width, ah = adj.height;
            if(aw !== undefined || ah !== undefined){             var rz = this.getResizeEl();
                if(!this.deferHeight && aw !== undefined && ah !== undefined){
                    rz.setSize(aw, ah);
                }else if(!this.deferHeight && ah !== undefined){
                    rz.setHeight(ah);
                }else if(aw !== undefined){
                    rz.setWidth(aw);
                }
                this.onResize(aw, ah, w, h);
                this.fireEvent('resize', this, aw, ah, w, h);
            }
            return this;
        },

        setWidth : function(width){
            return this.setSize(width);
        },

        setHeight : function(height){
            return this.setSize(undefined, height);
        },

        getSize : function(){
            return this.el.getSize();
        },

        getPosition : function(local){
            if(local === true){
                return [this.el.getLeft(true), this.el.getTop(true)];
            }
            return this.xy || this.el.getXY();
        },

        getBox : function(local){
            var s = this.el.getSize();
            if(local === true){
                s.x = this.el.getLeft(true);
                s.y = this.el.getTop(true);
            }else{
                var xy = this.xy || this.el.getXY();
                s.x = xy[0];
                s.y = xy[1];
            }
            return s;
        },

        updateBox : function(box){
            this.setSize(box.width, box.height);
            this.setPagePosition(box.x, box.y);
            return this;
        },

            getResizeEl : function(){
            return this.resizeEl || this.el;
        },

            getPositionEl : function(){
            return this.positionEl || this.el;
        },

        setPosition : function(x, y){
            if(x && typeof x[1] == 'number'){
                y = x[1];
                x = x[0];
            }
            this.x = x;
            this.y = y;
            if(!this.boxReady){
                return this;
            }
            var adj = this.adjustPosition(x, y);
            var ax = adj.x, ay = adj.y;

            var el = this.getPositionEl();
            if(ax !== undefined || ay !== undefined){
                if(ax !== undefined && ay !== undefined){
                    el.setLeftTop(ax, ay);
                }else if(ax !== undefined){
                    el.setLeft(ax);
                }else if(ay !== undefined){
                    el.setTop(ay);
                }
                this.onPosition(ax, ay);
                this.fireEvent('move', this, ax, ay);
            }
            return this;
        },

        setPagePosition : function(x, y){
            if(x && typeof x[1] == 'number'){
                y = x[1];
                x = x[0];
            }
            this.pageX = x;
            this.pageY = y;
            if(!this.boxReady){
                return;
            }
            if(x === undefined || y === undefined){             return;
            }
            var p = this.el.translatePoints(x, y);
            this.setPosition(p.left, p.top);
            return this;
        },

            onRender : function(ct, position){
            Ext.BoxComponent.superclass.onRender.call(this, ct, position);
            if(this.resizeEl){
                this.resizeEl = Ext.get(this.resizeEl);
            }
            if(this.positionEl){
                this.positionEl = Ext.get(this.positionEl);
            }
        },

            afterRender : function(){
            Ext.BoxComponent.superclass.afterRender.call(this);
            this.boxReady = true;
            this.setSize(this.width, this.height);
            if(this.x || this.y){
                this.setPosition(this.x, this.y);
            }else if(this.pageX || this.pageY){
                this.setPagePosition(this.pageX, this.pageY);
            }
        },

        syncSize : function(){
            delete this.lastSize;
            this.setSize(this.autoWidth ? undefined : this.el.getWidth(), this.autoHeight ? undefined : this.el.getHeight());
            return this;
        },

        onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){

        },

        onPosition : function(x, y){

        },

            adjustSize : function(w, h){
            if(this.autoWidth){
                w = 'auto';
            }
            if(this.autoHeight){
                h = 'auto';
            }
            return {width : w, height: h};
        },

            adjustPosition : function(x, y){
            return {x : x, y: y};
        }
    });
    Ext.reg('box', Ext.BoxComponent);

    Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy){

        this.el = Ext.get(dragElement, true);
        this.el.dom.unselectable = "on";

        this.resizingEl = Ext.get(resizingElement, true);

        this.orientation = orientation || Ext.SplitBar.HORIZONTAL;

        this.minSize = 0;

        this.maxSize = 2000;

        this.animate = false;

        this.useShim = false;

        this.shim = null;

        if(!existingProxy){

            this.proxy = Ext.SplitBar.createProxy(this.orientation);
        }else{
            this.proxy = Ext.get(existingProxy).dom;
        }

        this.dd = new Ext.dd.DDProxy(this.el.dom.id, "XSplitBars", {dragElId : this.proxy.id});

        this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);

        this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);

        this.dragSpecs = {};

        this.adapter = new Ext.SplitBar.BasicLayoutAdapter();
        this.adapter.init(this);

        if(this.orientation == Ext.SplitBar.HORIZONTAL){

            this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? Ext.SplitBar.LEFT : Ext.SplitBar.RIGHT);
            this.el.addClass("x-splitbar-h");
        }else{

            this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? Ext.SplitBar.TOP : Ext.SplitBar.BOTTOM);
            this.el.addClass("x-splitbar-v");
        }

        this.addEvents(

            "resize",

            "moved",

            "beforeresize",

            "beforeapply"
        );

        Ext.SplitBar.superclass.constructor.call(this);
    };

    Ext.extend(Ext.SplitBar, Ext.util.Observable, {
        onStartProxyDrag : function(x, y){
            this.fireEvent("beforeresize", this);
            this.overlay =  Ext.DomHelper.append(document.body,  {cls: "x-drag-overlay", html: " "}, true);
            this.overlay.unselectable();
            this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
            this.overlay.show();
            Ext.get(this.proxy).setDisplayed("block");
            var size = this.adapter.getElementSize(this);
            this.activeMinSize = this.getMinimumSize();;
            this.activeMaxSize = this.getMaximumSize();;
            var c1 = size - this.activeMinSize;
            var c2 = Math.max(this.activeMaxSize - size, 0);
            if(this.orientation == Ext.SplitBar.HORIZONTAL){
                this.dd.resetConstraints();
                this.dd.setXConstraint(
                    this.placement == Ext.SplitBar.LEFT ? c1 : c2,
                    this.placement == Ext.SplitBar.LEFT ? c2 : c1
                );
                this.dd.setYConstraint(0, 0);
            }else{
                this.dd.resetConstraints();
                this.dd.setXConstraint(0, 0);
                this.dd.setYConstraint(
                    this.placement == Ext.SplitBar.TOP ? c1 : c2,
                    this.placement == Ext.SplitBar.TOP ? c2 : c1
                );
             }
            this.dragSpecs.startSize = size;
            this.dragSpecs.startPoint = [x, y];
            Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);
        },

        onEndProxyDrag : function(e){
            Ext.get(this.proxy).setDisplayed(false);
            var endPoint = Ext.lib.Event.getXY(e);
            if(this.overlay){
                this.overlay.remove();
                delete this.overlay;
            }
            var newSize;
            if(this.orientation == Ext.SplitBar.HORIZONTAL){
                newSize = this.dragSpecs.startSize +
                    (this.placement == Ext.SplitBar.LEFT ?
                        endPoint[0] - this.dragSpecs.startPoint[0] :
                        this.dragSpecs.startPoint[0] - endPoint[0]
                    );
            }else{
                newSize = this.dragSpecs.startSize +
                    (this.placement == Ext.SplitBar.TOP ?
                        endPoint[1] - this.dragSpecs.startPoint[1] :
                        this.dragSpecs.startPoint[1] - endPoint[1]
                    );
            }
            newSize = Math.min(Math.max(newSize, this.activeMinSize), this.activeMaxSize);
            if(newSize != this.dragSpecs.startSize){
                if(this.fireEvent('beforeapply', this, newSize) !== false){
                    this.adapter.setElementSize(this, newSize);
                    this.fireEvent("moved", this, newSize);
                    this.fireEvent("resize", this, newSize);
                }
            }
        },

        getAdapter : function(){
            return this.adapter;
        },

        setAdapter : function(adapter){
            this.adapter = adapter;
            this.adapter.init(this);
        },

        getMinimumSize : function(){
            return this.minSize;
        },

        setMinimumSize : function(minSize){
            this.minSize = minSize;
        },

        getMaximumSize : function(){
            return this.maxSize;
        },

        setMaximumSize : function(maxSize){
            this.maxSize = maxSize;
        },

        setCurrentSize : function(size){
            var oldAnimate = this.animate;
            this.animate = false;
            this.adapter.setElementSize(this, size);
            this.animate = oldAnimate;
        },

        destroy : function(removeEl){
            if(this.shim){
                this.shim.remove();
            }
            this.dd.unreg();
            Ext.removeNode(this.proxy);
            if(removeEl){
                this.el.remove();
            }
        }
    });

    Ext.SplitBar.createProxy = function(dir){
        var proxy = new Ext.Element(document.createElement("div"));
        proxy.unselectable();
        var cls = 'x-splitbar-proxy';
        proxy.addClass(cls + ' ' + (dir == Ext.SplitBar.HORIZONTAL ? cls +'-h' : cls + '-v'));
        document.body.appendChild(proxy.dom);
        return proxy.dom;
    };

    Ext.SplitBar.BasicLayoutAdapter = function(){
    };

    Ext.SplitBar.BasicLayoutAdapter.prototype = {

        init : function(s){

        },

         getElementSize : function(s){
            if(s.orientation == Ext.SplitBar.HORIZONTAL){
                return s.resizingEl.getWidth();
            }else{
                return s.resizingEl.getHeight();
            }
        },

        setElementSize : function(s, newSize, onComplete){
            if(s.orientation == Ext.SplitBar.HORIZONTAL){
                if(!s.animate){
                    s.resizingEl.setWidth(newSize);
                    if(onComplete){
                        onComplete(s, newSize);
                    }
                }else{
                    s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');
                }
            }else{

                if(!s.animate){
                    s.resizingEl.setHeight(newSize);
                    if(onComplete){
                        onComplete(s, newSize);
                    }
                }else{
                    s.resizingEl.setHeight(newSize, true, .1, onComplete, 'easeOut');
                }
            }
        }
    };

    Ext.SplitBar.AbsoluteLayoutAdapter = function(container){
        this.basic = new Ext.SplitBar.BasicLayoutAdapter();
        this.container = Ext.get(container);
    };

    Ext.SplitBar.AbsoluteLayoutAdapter.prototype = {
        init : function(s){
            this.basic.init(s);
        },

        getElementSize : function(s){
            return this.basic.getElementSize(s);
        },

        setElementSize : function(s, newSize, onComplete){
            this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));
        },

        moveSplitter : function(s){
            var yes = Ext.SplitBar;
            switch(s.placement){
                case yes.LEFT:
                    s.el.setX(s.resizingEl.getRight());
                    break;
                case yes.RIGHT:
                    s.el.setStyle("right", (this.container.getWidth() - s.resizingEl.getLeft()) + "px");
                    break;
                case yes.TOP:
                    s.el.setY(s.resizingEl.getBottom());
                    break;
                case yes.BOTTOM:
                    s.el.setY(s.resizingEl.getTop() - s.el.getHeight());
                    break;
            }
        }
    };

    Ext.SplitBar.VERTICAL = 1;

    Ext.SplitBar.HORIZONTAL = 2;

    Ext.SplitBar.LEFT = 1;

    Ext.SplitBar.RIGHT = 2;

    Ext.SplitBar.TOP = 3;

    Ext.SplitBar.BOTTOM = 4;

    Ext.Container = Ext.extend(Ext.BoxComponent, {

        autoDestroy: true,

        defaultType: 'panel',

            initComponent : function(){
            Ext.Container.superclass.initComponent.call(this);

            this.addEvents(

                'afterlayout',

                'beforeadd',

                'beforeremove',

                'add',

                'remove'
            );

            var items = this.items;
            if(items){
                delete this.items;
                if(Ext.isArray(items)){
                    this.add.apply(this, items);
                }else{
                    this.add(items);
                }
            }
        },

            initItems : function(){
            if(!this.items){
                this.items = new Ext.util.MixedCollection(false, this.getComponentId);
                this.getLayout();         }
        },

            setLayout : function(layout){
            if(this.layout && this.layout != layout){
                this.layout.setContainer(null);
            }
            this.initItems();
            this.layout = layout;
            layout.setContainer(this);
        },

            render : function(){
            Ext.Container.superclass.render.apply(this, arguments);
            if(this.layout){
                if(typeof this.layout == 'string'){
                    this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig);
                }
                this.setLayout(this.layout);

                if(this.activeItem !== undefined){
                    var item = this.activeItem;
                    delete this.activeItem;
                    this.layout.setActiveItem(item);
                    return;
                }
            }
            if(!this.ownerCt){
                this.doLayout();
            }
            if(this.monitorResize === true){
                Ext.EventManager.onWindowResize(this.doLayout, this, [false]);
            }
        },

            getLayoutTarget : function(){
            return this.el;
        },

            getComponentId : function(comp){
            return comp.itemId || comp.id;
        },

        add : function(comp){
            if(!this.items){
                this.initItems();
            }
            var a = arguments, len = a.length;
            if(len > 1){
                for(var i = 0; i < len; i++) {
                    this.add(a[i]);
                }
                return;
            }
            var c = this.lookupComponent(this.applyDefaults(comp));
            var pos = this.items.length;
            if(this.fireEvent('beforeadd', this, c, pos) !== false && this.onBeforeAdd(c) !== false){
                this.items.add(c);
                c.ownerCt = this;
                this.fireEvent('add', this, c, pos);
            }
            return c;
        },

        insert : function(index, comp){
            if(!this.items){
                this.initItems();
            }
            var a = arguments, len = a.length;
            if(len > 2){
                for(var i = len-1; i >= 1; --i) {
                    this.insert(index, a[i]);
                }
                return;
            }
            var c = this.lookupComponent(this.applyDefaults(comp));

            if(c.ownerCt == this && this.items.indexOf(c) < index){
                --index;
            }

            if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
                this.items.insert(index, c);
                c.ownerCt = this;
                this.fireEvent('add', this, c, index);
            }
            return c;
        },

            applyDefaults : function(c){
            if(this.defaults){
                if(typeof c == 'string'){
                    c = Ext.ComponentMgr.get(c);
                    Ext.apply(c, this.defaults);
                }else if(!c.events){
                    Ext.applyIf(c, this.defaults);
                }else{
                    Ext.apply(c, this.defaults);
                }
            }
            return c;
        },

            onBeforeAdd : function(item){
            if(item.ownerCt){
                item.ownerCt.remove(item, false);
            }
            if(this.hideBorders === true){
                item.border = (item.border === true);
            }
        },

        remove : function(comp, autoDestroy){
            var c = this.getComponent(comp);
            if(c && this.fireEvent('beforeremove', this, c) !== false){
                this.items.remove(c);
                delete c.ownerCt;
                if(autoDestroy === true || (autoDestroy !== false && this.autoDestroy)){
                    c.destroy();
                }
                if(this.layout && this.layout.activeItem == c){
                    delete this.layout.activeItem;
                }
                this.fireEvent('remove', this, c);
            }
            return c;
        },

        getComponent : function(comp){
            if(typeof comp == 'object'){
                return comp;
            }
            return this.items.get(comp);
        },

            lookupComponent : function(comp){
            if(typeof comp == 'string'){
                return Ext.ComponentMgr.get(comp);
            }else if(!comp.events){
                return this.createComponent(comp);
            }
            return comp;
        },

            createComponent : function(config){
            return Ext.ComponentMgr.create(config, this.defaultType);
        },

        doLayout : function(shallow){
            if(this.rendered && this.layout){
                this.layout.layout();
            }
            if(shallow !== false && this.items){
                var cs = this.items.items;
                for(var i = 0, len = cs.length; i < len; i++) {
                    var c  = cs[i];
                    if(c.doLayout){
                        c.doLayout();
                    }
                }
            }
        },

        getLayout : function(){
            if(!this.layout){
                var layout = new Ext.layout.ContainerLayout(this.layoutConfig);
                this.setLayout(layout);
            }
            return this.layout;
        },

            onDestroy : function(){
            if(this.items){
                var cs = this.items.items;
                for(var i = 0, len = cs.length; i < len; i++) {
                    Ext.destroy(cs[i]);
                }
            }
            if(this.monitorResize){
                Ext.EventManager.removeResizeListener(this.doLayout, this);
            }
            Ext.Container.superclass.onDestroy.call(this);
        },

        bubble : function(fn, scope, args){
            var p = this;
            while(p){
                if(fn.apply(scope || p, args || [p]) === false){
                    break;
                }
                p = p.ownerCt;
            }
        },

        cascade : function(fn, scope, args){
            if(fn.apply(scope || this, args || [this]) !== false){
                if(this.items){
                    var cs = this.items.items;
                    for(var i = 0, len = cs.length; i < len; i++){
                        if(cs[i].cascade){
                            cs[i].cascade(fn, scope, args);
                        }else{
                            fn.apply(scope || this, args || [cs[i]]);
                        }
                    }
                }
            }
        },

        findById : function(id){
            var m, ct = this;
            this.cascade(function(c){
                if(ct != c && c.id === id){
                    m = c;
                    return false;
                }
            });
            return m || null;
        },

        findByType : function(xtype){
            return typeof xtype == 'function' ?
                this.findBy(function(c){
                    return c.constructor === xtype;
                }) :
                this.findBy(function(c){
                    return c.constructor.xtype === xtype;
                });
        },

        find : function(prop, value){
            return this.findBy(function(c){
                return c[prop] === value;
            });
        },

        findBy : function(fn, scope){
            var m = [], ct = this;
            this.cascade(function(c){
                if(ct != c && fn.call(scope || c, c, ct) === true){
                    m.push(c);
                }
            });
            return m;
        }
    });

    Ext.Container.LAYOUTS = {};
    Ext.reg('container', Ext.Container);

    Ext.layout.ContainerLayout = function(config){
        Ext.apply(this, config);
    };

    Ext.layout.ContainerLayout.prototype = {

            monitorResize:false,
            activeItem : null,

            layout : function(){
            var target = this.container.getLayoutTarget();
            this.onLayout(this.container, target);
            this.container.fireEvent('afterlayout', this.container, this);
        },

            onLayout : function(ct, target){
            this.renderAll(ct, target);
        },

            isValidParent : function(c, target){
    		var el = c.getPositionEl ? c.getPositionEl() : c.getEl();
    		return el.dom.parentNode == target.dom;
        },

            renderAll : function(ct, target){
            var items = ct.items.items;
            for(var i = 0, len = items.length; i < len; i++) {
                var c = items[i];
                if(c && (!c.rendered || !this.isValidParent(c, target))){
                    this.renderItem(c, i, target);
                }
            }
        },

            renderItem : function(c, position, target){
            if(c && !c.rendered){
                c.render(target, position);
                if(this.extraCls){
                	var t = c.getPositionEl ? c.getPositionEl() : c;
                	t.addClass(this.extraCls);
                }
                if (this.renderHidden && c != this.activeItem) {
                    c.hide();
                }
            }else if(c && !this.isValidParent(c, target)){
                if(this.extraCls){
                    c.addClass(this.extraCls);
                }
                if(typeof position == 'number'){
                    position = target.dom.childNodes[position];
                }
                target.dom.insertBefore(c.getEl().dom, position || null);
                if (this.renderHidden && c != this.activeItem) {
                    c.hide();
                }
            }
        },

            onResize: function(){
            if(this.container.collapsed){
                return;
            }
            var b = this.container.bufferResize;
            if(b){
                if(!this.resizeTask){
                    this.resizeTask = new Ext.util.DelayedTask(this.layout, this);
                    this.resizeBuffer = typeof b == 'number' ? b : 100;
                }
                this.resizeTask.delay(this.resizeBuffer);
            }else{
                this.layout();
            }
        },

            setContainer : function(ct){
            if(this.monitorResize && ct != this.container){
                if(this.container){
                    this.container.un('resize', this.onResize, this);
                }
                if(ct){
                    ct.on('resize', this.onResize, this);
                }
            }
            this.container = ct;
        },

            parseMargins : function(v){
            var ms = v.split(' ');
            var len = ms.length;
            if(len == 1){
                ms[1] = ms[0];
                ms[2] = ms[0];
                ms[3] = ms[0];
            }
            if(len == 2){
                ms[2] = ms[0];
                ms[3] = ms[1];
            }
            return {
                top:parseInt(ms[0], 10) || 0,
                right:parseInt(ms[1], 10) || 0,
                bottom:parseInt(ms[2], 10) || 0,
                left:parseInt(ms[3], 10) || 0
            };
        }
    };
    Ext.Container.LAYOUTS['auto'] = Ext.layout.ContainerLayout;

    Ext.layout.FitLayout = Ext.extend(Ext.layout.ContainerLayout, {

        monitorResize:true,

        onLayout : function(ct, target){
            Ext.layout.FitLayout.superclass.onLayout.call(this, ct, target);
            if(!this.container.collapsed){
                this.setItemSize(this.activeItem || ct.items.itemAt(0), target.getStyleSize());
            }
        },

        setItemSize : function(item, size){
            if(item && size.height > 0){
                item.setSize(size);
            }
        }
    });
    Ext.Container.LAYOUTS['fit'] = Ext.layout.FitLayout;

    Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {

        deferredRender : false,

        renderHidden : true,

        setActiveItem : function(item){
            item = this.container.getComponent(item);
            if(this.activeItem != item){
                if(this.activeItem){
                    this.activeItem.hide();
                }
                this.activeItem = item;
                item.show();
                this.layout();
            }
        },

        renderAll : function(ct, target){
            if(this.deferredRender){
                this.renderItem(this.activeItem, undefined, target);
            }else{
                Ext.layout.CardLayout.superclass.renderAll.call(this, ct, target);
            }
        }
    });
    Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;

    Ext.layout.AnchorLayout = Ext.extend(Ext.layout.ContainerLayout, {

        monitorResize:true,

        getAnchorViewSize : function(ct, target){
            return target.dom == document.body ?
                       target.getViewSize() : target.getStyleSize();
        },

        onLayout : function(ct, target){
            Ext.layout.AnchorLayout.superclass.onLayout.call(this, ct, target);

            var size = this.getAnchorViewSize(ct, target);

            var w = size.width, h = size.height;

            if(w < 20 || h < 20){
                return;
            }

            var aw, ah;
            if(ct.anchorSize){
                if(typeof ct.anchorSize == 'number'){
                    aw = ct.anchorSize;
                }else{
                    aw = ct.anchorSize.width;
                    ah = ct.anchorSize.height;
                }
            }else{
                aw = ct.initialConfig.width;
                ah = ct.initialConfig.height;
            }

            var cs = ct.items.items, len = cs.length, i, c, a, cw, ch;
            for(i = 0; i < len; i++){
                c = cs[i];
                if(c.anchor){
                    a = c.anchorSpec;
                    if(!a){
                        var vs = c.anchor.split(' ');
                        c.anchorSpec = a = {
                            right: this.parseAnchor(vs[0], c.initialConfig.width, aw),
                            bottom: this.parseAnchor(vs[1], c.initialConfig.height, ah)
                        };
                    }
                    cw = a.right ? this.adjustWidthAnchor(a.right(w), c) : undefined;
                    ch = a.bottom ? this.adjustHeightAnchor(a.bottom(h), c) : undefined;

                    if(cw || ch){
                        c.setSize(cw || undefined, ch || undefined);
                    }
                }
            }
        },

        parseAnchor : function(a, start, cstart){
            if(a && a != 'none'){
                var last;
                if(/^(r|right|b|bottom)$/i.test(a)){
                    var diff = cstart - start;
                    return function(v){
                        if(v !== last){
                            last = v;
                            return v - diff;
                        }
                    }
                }else if(a.indexOf('%') != -1){
                    var ratio = parseFloat(a.replace('%', ''))*.01;
                    return function(v){
                        if(v !== last){
                            last = v;
                            return Math.floor(v*ratio);
                        }
                    }
                }else{
                    a = parseInt(a, 10);
                    if(!isNaN(a)){
                        return function(v){
                            if(v !== last){
                                last = v;
                                return v + a;
                            }
                        }
                    }
                }
            }
            return false;
        },

        adjustWidthAnchor : function(value, comp){
            return value;
        },

        adjustHeightAnchor : function(value, comp){
            return value;
        }

    });
    Ext.Container.LAYOUTS['anchor'] = Ext.layout.AnchorLayout;

    Ext.layout.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {

        monitorResize:true,

        extraCls: 'x-column',

        scrollOffset : 0,

        isValidParent : function(c, target){
            return c.getEl().dom.parentNode == this.innerCt.dom;
        },

        onLayout : function(ct, target){
            var cs = ct.items.items, len = cs.length, c, i;

            if(!this.innerCt){
                target.addClass('x-column-layout-ct');

                this.innerCt = target.createChild({cls:'x-column-inner'});
                this.innerCt.createChild({cls:'x-clear'});
            }
            this.renderAll(ct, this.innerCt);

            var size = target.getViewSize();

            if(size.width < 1 && size.height < 1){
                return;
            }

            var w = size.width - target.getPadding('lr') - this.scrollOffset,
                h = size.height - target.getPadding('tb'),
                pw = w;

            this.innerCt.setWidth(w);

            for(i = 0; i < len; i++){
                c = cs[i];
                if(!c.columnWidth){
                    pw -= (c.getSize().width + c.getEl().getMargins('lr'));
                }
            }

            pw = pw < 0 ? 0 : pw;

            for(i = 0; i < len; i++){
                c = cs[i];
                if(c.columnWidth){
                    c.setSize(Math.floor(c.columnWidth*pw) - c.getEl().getMargins('lr'));
                }
            }
        }

    });

    Ext.Container.LAYOUTS['column'] = Ext.layout.ColumnLayout;

    Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {
            monitorResize:true,
            rendered : false,

            onLayout : function(ct, target){
            var collapsed;
            if(!this.rendered){
                target.position();
                target.addClass('x-border-layout-ct');
                var items = ct.items.items;
                collapsed = [];
                for(var i = 0, len = items.length; i < len; i++) {
                    var c = items[i];
                    var pos = c.region;
                    if(c.collapsed){
                        collapsed.push(c);
                    }
                    c.collapsed = false;
                    if(!c.rendered){
                        c.cls = c.cls ? c.cls +' x-border-panel' : 'x-border-panel';
                        c.render(target, i);
                    }
                    this[pos] = pos != 'center' && c.split ?
                        new Ext.layout.BorderLayout.SplitRegion(this, c.initialConfig, pos) :
                        new Ext.layout.BorderLayout.Region(this, c.initialConfig, pos);
                    this[pos].render(target, c);
                }
                this.rendered = true;
            }

            var size = target.getViewSize();
            if(size.width < 20 || size.height < 20){             if(collapsed){
                    this.restoreCollapsed = collapsed;
                }
                return;
            }else if(this.restoreCollapsed){
                collapsed = this.restoreCollapsed;
                delete this.restoreCollapsed;
            }

            var w = size.width, h = size.height;
            var centerW = w, centerH = h, centerY = 0, centerX = 0;

            var n = this.north, s = this.south, west = this.west, e = this.east, c = this.center;
            if(!c){
                throw 'No center region defined in BorderLayout ' + ct.id;
            }

            if(n && n.isVisible()){
                var b = n.getSize();
                var m = n.getMargins();
                b.width = w - (m.left+m.right);
                b.x = m.left;
                b.y = m.top;
                centerY = b.height + b.y + m.bottom;
                centerH -= centerY;
                n.applyLayout(b);
            }
            if(s && s.isVisible()){
                var b = s.getSize();
                var m = s.getMargins();
                b.width = w - (m.left+m.right);
                b.x = m.left;
                var totalHeight = (b.height + m.top + m.bottom);
                b.y = h - totalHeight + m.top;
                centerH -= totalHeight;
                s.applyLayout(b);
            }
            if(west && west.isVisible()){
                var b = west.getSize();
                var m = west.getMargins();
                b.height = centerH - (m.top+m.bottom);
                b.x = m.left;
                b.y = centerY + m.top;
                var totalWidth = (b.width + m.left + m.right);
                centerX += totalWidth;
                centerW -= totalWidth;
                west.applyLayout(b);
            }
            if(e && e.isVisible()){
                var b = e.getSize();
                var m = e.getMargins();
                b.height = centerH - (m.top+m.bottom);
                var totalWidth = (b.width + m.left + m.right);
                b.x = w - totalWidth + m.left;
                b.y = centerY + m.top;
                centerW -= totalWidth;
                e.applyLayout(b);
            }

            var m = c.getMargins();
            var centerBox = {
                x: centerX + m.left,
                y: centerY + m.top,
                width: centerW - (m.left+m.right),
                height: centerH - (m.top+m.bottom)
            };
            c.applyLayout(centerBox);

            if(collapsed){
                for(var i = 0, len = collapsed.length; i < len; i++){
                    collapsed[i].collapse(false);
                }
            }

            if(Ext.isIE && Ext.isStrict){             target.repaint();
            }
        }

    });

    Ext.layout.BorderLayout.Region = function(layout, config, pos){
        Ext.apply(this, config);
        this.layout = layout;
        this.position = pos;
        this.state = {};
        if(typeof this.margins == 'string'){
            this.margins = this.layout.parseMargins(this.margins);
        }
        this.margins = Ext.applyIf(this.margins || {}, this.defaultMargins);
        if(this.collapsible){
            if(typeof this.cmargins == 'string'){
                this.cmargins = this.layout.parseMargins(this.cmargins);
            }
            if(this.collapseMode == 'mini' && !this.cmargins){
                this.cmargins = {left:0,top:0,right:0,bottom:0};
            }else{
                this.cmargins = Ext.applyIf(this.cmargins || {},
                    pos == 'north' || pos == 'south' ? this.defaultNSCMargins : this.defaultEWCMargins);
            }
        }
    };

    Ext.layout.BorderLayout.Region.prototype = {

        collapsible : false,

        split:false,

        floatable: true,

        minWidth:50,

        minHeight:50,

            defaultMargins : {left:0,top:0,right:0,bottom:0},
            defaultNSCMargins : {left:5,top:5,right:5,bottom:5},
            defaultEWCMargins : {left:5,top:0,right:5,bottom:0},

        isCollapsed : false,

            render : function(ct, p){
            this.panel = p;
            p.el.enableDisplayMode();
            this.targetEl = ct;
            this.el = p.el;

            var gs = p.getState, ps = this.position;
            p.getState = function(){
                return Ext.apply(gs.call(p) || {}, this.state);
            }.createDelegate(this);

            if(ps != 'center'){
                p.allowQueuedExpand = false;
                p.on({
                    beforecollapse: this.beforeCollapse,
                    collapse: this.onCollapse,
                    beforeexpand: this.beforeExpand,
                    expand: this.onExpand,
                    hide: this.onHide,
                    show: this.onShow,
                    scope: this
                });
                if(this.collapsible){
                    p.collapseEl = 'el';
                    p.slideAnchor = this.getSlideAnchor();
                }
                if(p.tools && p.tools.toggle){
                    p.tools.toggle.addClass('x-tool-collapse-'+ps);
                    p.tools.toggle.addClassOnOver('x-tool-collapse-'+ps+'-over');
                }
            }
        },

            getCollapsedEl : function(){
            if(!this.collapsedEl){
                if(!this.toolTemplate){
                    var tt = new Ext.Template(
                         ' '
                    );
                    tt.disableFormats = true;
                    tt.compile();
                    Ext.layout.BorderLayout.Region.prototype.toolTemplate = tt;
                }
                this.collapsedEl = this.targetEl.createChild({
                    cls: "x-layout-collapsed x-layout-collapsed-"+this.position,
                    id: this.panel.id + '-xcollapsed'
                });
                this.collapsedEl.enableDisplayMode('block');

                if(this.collapseMode == 'mini'){
                    this.collapsedEl.addClass('x-layout-cmini-'+this.position);
                    this.miniCollapsedEl = this.collapsedEl.createChild({
                        cls: "x-layout-mini x-layout-mini-"+this.position, html: " "
                    });
                    this.miniCollapsedEl.addClassOnOver('x-layout-mini-over');
                    this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
                    this.collapsedEl.on('click', this.onExpandClick, this, {stopEvent:true});
                }else {
                    var t = this.toolTemplate.append(
                            this.collapsedEl.dom,
                            {id:'expand-'+this.position}, true);
                    t.addClassOnOver('x-tool-expand-'+this.position+'-over');
                    t.on('click', this.onExpandClick, this, {stopEvent:true});

                    if(this.floatable !== false){
                       this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
                       this.collapsedEl.on("click", this.collapseClick, this);
                    }
                }
            }
            return this.collapsedEl;
        },

            onExpandClick : function(e){
            if(this.isSlid){
                this.afterSlideIn();
                this.panel.expand(false);
            }else{
                this.panel.expand();
            }
        },

            onCollapseClick : function(e){
            this.panel.collapse();
        },

            beforeCollapse : function(p, animate){
            this.lastAnim = animate;
            if(this.splitEl){
                this.splitEl.hide();
            }
            this.getCollapsedEl().show();
            this.panel.el.setStyle('z-index', 100);
            this.isCollapsed = true;
            this.layout.layout();
        },

            onCollapse : function(animate){
            this.panel.el.setStyle('z-index', 1);
            if(this.lastAnim === false || this.panel.animCollapse === false){
                this.getCollapsedEl().dom.style.visibility = 'visible';
            }else{
                this.getCollapsedEl().slideIn(this.panel.slideAnchor, {duration:.2});
            }
            this.state.collapsed = true;
            this.panel.saveState();
        },

            beforeExpand : function(animate){
            var c = this.getCollapsedEl();
            this.el.show();
            if(this.position == 'east' || this.position == 'west'){
                this.panel.setSize(undefined, c.getHeight());
            }else{
                this.panel.setSize(c.getWidth(), undefined);
            }
            c.hide();
            c.dom.style.visibility = 'hidden';
            this.panel.el.setStyle('z-index', 100);
        },

            onExpand : function(){
            this.isCollapsed = false;
            if(this.splitEl){
                this.splitEl.show();
            }
            this.layout.layout();
            this.panel.el.setStyle('z-index', 1);
            this.state.collapsed = false;
            this.panel.saveState();
        },

            collapseClick : function(e){
            if(this.isSlid){
               e.stopPropagation();
               this.slideIn();
            }else{
               e.stopPropagation();
               this.slideOut();
            }
        },

            onHide : function(){
            if(this.isCollapsed){
                this.getCollapsedEl().hide();
            }else if(this.splitEl){
                this.splitEl.hide();
            }
        },

            onShow : function(){
            if(this.isCollapsed){
                this.getCollapsedEl().show();
            }else if(this.splitEl){
                this.splitEl.show();
            }
        },

        isVisible : function(){
            return !this.panel.hidden;
        },

        getMargins : function(){
            return this.isCollapsed && this.cmargins ? this.cmargins : this.margins;
        },

        getSize : function(){
            return this.isCollapsed ? this.getCollapsedEl().getSize() : this.panel.getSize();
        },

        setPanel : function(panel){
            this.panel = panel;
        },

        getMinWidth: function(){
            return this.minWidth;
        },

        getMinHeight: function(){
            return this.minHeight;
        },

            applyLayoutCollapsed : function(box){
            var ce = this.getCollapsedEl();
            ce.setLeftTop(box.x, box.y);
            ce.setSize(box.width, box.height);
        },

            applyLayout : function(box){
            if(this.isCollapsed){
                this.applyLayoutCollapsed(box);
            }else{
                this.panel.setPosition(box.x, box.y);
                this.panel.setSize(box.width, box.height);
            }
        },

            beforeSlide: function(){
            this.panel.beforeEffect();
        },

            afterSlide : function(){
            this.panel.afterEffect();
        },

            initAutoHide : function(){
            if(this.autoHide !== false){
                if(!this.autoHideHd){
                    var st = new Ext.util.DelayedTask(this.slideIn, this);
                    this.autoHideHd = {
                        "mouseout": function(e){
                            if(!e.within(this.el, true)){
                                st.delay(500);
                            }
                        },
                        "mouseover" : function(e){
                            st.cancel();
                        },
                        scope : this
                    };
                }
                this.el.on(this.autoHideHd);
            }
        },

            clearAutoHide : function(){
            if(this.autoHide !== false){
                this.el.un("mouseout", this.autoHideHd.mouseout);
                this.el.un("mouseover", this.autoHideHd.mouseover);
            }
        },

            clearMonitor : function(){
            Ext.getDoc().un("click", this.slideInIf, this);
        },

                slideOut : function(){
            if(this.isSlid || this.el.hasActiveFx()){
                return;
            }
            this.isSlid = true;
            var ts = this.panel.tools;
            if(ts && ts.toggle){
                ts.toggle.hide();
            }
            this.el.show();
            if(this.position == 'east' || this.position == 'west'){
                this.panel.setSize(undefined, this.collapsedEl.getHeight());
            }else{
                this.panel.setSize(this.collapsedEl.getWidth(), undefined);
            }
            this.restoreLT = [this.el.dom.style.left, this.el.dom.style.top];
            this.el.alignTo(this.collapsedEl, this.getCollapseAnchor());
            this.el.setStyle("z-index", 102);
            if(this.animFloat !== false){
                this.beforeSlide();
                this.el.slideIn(this.getSlideAnchor(), {
                    callback: function(){
                        this.afterSlide();
                        this.initAutoHide();
                        Ext.getDoc().on("click", this.slideInIf, this);
                    },
                    scope: this,
                    block: true
                });
            }else{
                this.initAutoHide();
                 Ext.getDoc().on("click", this.slideInIf, this);
            }
        },

            afterSlideIn : function(){
            this.clearAutoHide();
            this.isSlid = false;
            this.clearMonitor();
            this.el.setStyle("z-index", "");
            this.el.dom.style.left = this.restoreLT[0];
            this.el.dom.style.top = this.restoreLT[1];

            var ts = this.panel.tools;
            if(ts && ts.toggle){
                ts.toggle.show();
            }
        },

            slideIn : function(cb){
            if(!this.isSlid || this.el.hasActiveFx()){
                Ext.callback(cb);
                return;
            }
            this.isSlid = false;
            if(this.animFloat !== false){
                this.beforeSlide();
                this.el.slideOut(this.getSlideAnchor(), {
                    callback: function(){
                        this.el.hide();
                        this.afterSlide();
                        this.afterSlideIn();
                        Ext.callback(cb);
                    },
                    scope: this,
                    block: true
                });
            }else{
                this.el.hide();
                this.afterSlideIn();
            }
        },

            slideInIf : function(e){
            if(!e.within(this.el)){
                this.slideIn();
            }
        },

            anchors : {
            "west" : "left",
            "east" : "right",
            "north" : "top",
            "south" : "bottom"
        },

            sanchors : {
            "west" : "l",
            "east" : "r",
            "north" : "t",
            "south" : "b"
        },

            canchors : {
            "west" : "tl-tr",
            "east" : "tr-tl",
            "north" : "tl-bl",
            "south" : "bl-tl"
        },

            getAnchor : function(){
            return this.anchors[this.position];
        },

            getCollapseAnchor : function(){
            return this.canchors[this.position];
        },

            getSlideAnchor : function(){
            return this.sanchors[this.position];
        },

            getAlignAdj : function(){
            var cm = this.cmargins;
            switch(this.position){
                case "west":
                    return [0, 0];
                break;
                case "east":
                    return [0, 0];
                break;
                case "north":
                    return [0, 0];
                break;
                case "south":
                    return [0, 0];
                break;
            }
        },

            getExpandAdj : function(){
            var c = this.collapsedEl, cm = this.cmargins;
            switch(this.position){
                case "west":
                    return [-(cm.right+c.getWidth()+cm.left), 0];
                break;
                case "east":
                    return [cm.right+c.getWidth()+cm.left, 0];
                break;
                case "north":
                    return [0, -(cm.top+cm.bottom+c.getHeight())];
                break;
                case "south":
                    return [0, cm.top+cm.bottom+c.getHeight()];
                break;
            }
        }
    };

    Ext.layout.BorderLayout.SplitRegion = function(layout, config, pos){
        Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this, layout, config, pos);
            this.applyLayout = this.applyFns[pos];
    };

    Ext.extend(Ext.layout.BorderLayout.SplitRegion, Ext.layout.BorderLayout.Region, {

        splitTip : "Drag to resize.",

        collapsibleSplitTip : "Drag to resize. Double click to hide.",

        useSplitTips : false,

            splitSettings : {
            north : {
                orientation: Ext.SplitBar.VERTICAL,
                placement: Ext.SplitBar.TOP,
                maxFn : 'getVMaxSize',
                minProp: 'minHeight',
                maxProp: 'maxHeight'
            },
            south : {
                orientation: Ext.SplitBar.VERTICAL,
                placement: Ext.SplitBar.BOTTOM,
                maxFn : 'getVMaxSize',
                minProp: 'minHeight',
                maxProp: 'maxHeight'
            },
            east : {
                orientation: Ext.SplitBar.HORIZONTAL,
                placement: Ext.SplitBar.RIGHT,
                maxFn : 'getHMaxSize',
                minProp: 'minWidth',
                maxProp: 'maxWidth'
            },
            west : {
                orientation: Ext.SplitBar.HORIZONTAL,
                placement: Ext.SplitBar.LEFT,
                maxFn : 'getHMaxSize',
                minProp: 'minWidth',
                maxProp: 'maxWidth'
            }
        },

            applyFns : {
            west : function(box){
                if(this.isCollapsed){
                    return this.applyLayoutCollapsed(box);
                }
                var sd = this.splitEl.dom, s = sd.style;
                this.panel.setPosition(box.x, box.y);
                var sw = sd.offsetWidth;
                s.left = (box.x+box.width-sw)+'px';
                s.top = (box.y)+'px';
                s.height = Math.max(0, box.height)+'px';
                this.panel.setSize(box.width-sw, box.height);
            },
            east : function(box){
                if(this.isCollapsed){
                    return this.applyLayoutCollapsed(box);
                }
                var sd = this.splitEl.dom, s = sd.style;
                var sw = sd.offsetWidth;
                this.panel.setPosition(box.x+sw, box.y);
                s.left = (box.x)+'px';
                s.top = (box.y)+'px';
                s.height = Math.max(0, box.height)+'px';
                this.panel.setSize(box.width-sw, box.height);
            },
            north : function(box){
                if(this.isCollapsed){
                    return this.applyLayoutCollapsed(box);
                }
                var sd = this.splitEl.dom, s = sd.style;
                var sh = sd.offsetHeight;
                this.panel.setPosition(box.x, box.y);
                s.left = (box.x)+'px';
                s.top = (box.y+box.height-sh)+'px';
                s.width = Math.max(0, box.width)+'px';
                this.panel.setSize(box.width, box.height-sh);
            },
            south : function(box){
                if(this.isCollapsed){
                    return this.applyLayoutCollapsed(box);
                }
                var sd = this.splitEl.dom, s = sd.style;
                var sh = sd.offsetHeight;
                this.panel.setPosition(box.x, box.y+sh);
                s.left = (box.x)+'px';
                s.top = (box.y)+'px';
                s.width = Math.max(0, box.width)+'px';
                this.panel.setSize(box.width, box.height-sh);
            }
        },

            render : function(ct, p){
            Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this, ct, p);

            var ps = this.position;

            this.splitEl = ct.createChild({
                cls: "x-layout-split x-layout-split-"+ps, html: " ",
                id: this.panel.id + '-xsplit'
            });

            if(this.collapseMode == 'mini'){
                this.miniSplitEl = this.splitEl.createChild({
                    cls: "x-layout-mini x-layout-mini-"+ps, html: " "
                });
                this.miniSplitEl.addClassOnOver('x-layout-mini-over');
                this.miniSplitEl.on('click', this.onCollapseClick, this, {stopEvent:true});
            }

            var s = this.splitSettings[ps];

            this.split = new Ext.SplitBar(this.splitEl.dom, p.el, s.orientation);
            this.split.placement = s.placement;
            this.split.getMaximumSize = this[s.maxFn].createDelegate(this);
            this.split.minSize = this.minSize || this[s.minProp];
            this.split.on("beforeapply", this.onSplitMove, this);
            this.split.useShim = this.useShim === true;
            this.maxSize = this.maxSize || this[s.maxProp];

            if(p.hidden){
                this.splitEl.hide();
            }

            if(this.useSplitTips){
                this.splitEl.dom.title = this.collapsible ? this.collapsibleSplitTip : this.splitTip;
            }
            if(this.collapsible){
                this.splitEl.on("dblclick", this.onCollapseClick,  this);
            }
        },

            getSize : function(){
            if(this.isCollapsed){
                return this.collapsedEl.getSize();
            }
            var s = this.panel.getSize();
            if(this.position == 'north' || this.position == 'south'){
                s.height += this.splitEl.dom.offsetHeight;
            }else{
                s.width += this.splitEl.dom.offsetWidth;
            }
            return s;
        },

            getHMaxSize : function(){
             var cmax = this.maxSize || 10000;
             var center = this.layout.center;
             return Math.min(cmax, (this.el.getWidth()+center.el.getWidth())-center.getMinWidth());
        },

            getVMaxSize : function(){
            var cmax = this.maxSize || 10000;
            var center = this.layout.center;
            return Math.min(cmax, (this.el.getHeight()+center.el.getHeight())-center.getMinHeight());
        },

            onSplitMove : function(split, newSize){
            var s = this.panel.getSize();
            this.lastSplitSize = newSize;
            if(this.position == 'north' || this.position == 'south'){
                this.panel.setSize(s.width, newSize);
                this.state.height = newSize;
            }else{
                this.panel.setSize(newSize, s.height);
                this.state.width = newSize;
            }
            this.layout.layout();
            this.panel.saveState();
            return false;
        },

        getSplitBar : function(){
            return this.split;
        }
    });

    Ext.Container.LAYOUTS['border'] = Ext.layout.BorderLayout;

    Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {

        labelSeparator : ':',

            getAnchorViewSize : function(ct, target){
            return ct.body.getStyleSize();
        },

            setContainer : function(ct){
            Ext.layout.FormLayout.superclass.setContainer.call(this, ct);

            if(ct.labelAlign){
                ct.addClass('x-form-label-'+ct.labelAlign);
            }

            if(ct.hideLabels){
                this.labelStyle = "display:none";
                this.elementStyle = "padding-left:0;";
                this.labelAdjust = 0;
            }else{
                this.labelSeparator = ct.labelSeparator || this.labelSeparator;
                ct.labelWidth = ct.labelWidth || 100;
                if(typeof ct.labelWidth == 'number'){
                    var pad = (typeof ct.labelPad == 'number' ? ct.labelPad : 5);
                    this.labelAdjust = ct.labelWidth+pad;
                    this.labelStyle = "width:"+ct.labelWidth+"px;";
                    this.elementStyle = "padding-left:"+(ct.labelWidth+pad)+'px';
                }
                if(ct.labelAlign == 'top'){
                    this.labelStyle = "width:auto;";
                    this.labelAdjust = 0;
                    this.elementStyle = "padding-left:0;";
                }
            }

            if(!this.fieldTpl){
                            var t = new Ext.Template(
                    '',
                        '{1}{4}',
                        '',
                        '',
                    ''
                );
                t.disableFormats = true;
                t.compile();
                Ext.layout.FormLayout.prototype.fieldTpl = t;
            }
        },

            renderItem : function(c, position, target){
            if(c && !c.rendered && c.isFormField && c.inputType != 'hidden'){
                var args = [
                       c.id, c.fieldLabel,
                       c.labelStyle||this.labelStyle||'',
                       this.elementStyle||'',
                       typeof c.labelSeparator == 'undefined' ? this.labelSeparator : c.labelSeparator,
                       (c.itemCls||this.container.itemCls||'') + (c.hideLabel ? ' x-hide-label' : ''),
                       c.clearCls || 'x-form-clear-left'
                ];
                if(typeof position == 'number'){
                    position = target.dom.childNodes[position] || null;
                }
                if(position){
                    this.fieldTpl.insertBefore(position, args);
                }else{
                    this.fieldTpl.append(target, args);
                }
                c.render('x-form-el-'+c.id);
            }else {
                Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments);
            }
        },

            adjustWidthAnchor : function(value, comp){
            return value - (comp.isFormField  ? (comp.hideLabel ? 0 : this.labelAdjust) : 0);
        },

            isValidParent : function(c, target){
            return true;
        }

    });

    Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout;

    Ext.layout.Accordion = Ext.extend(Ext.layout.FitLayout, {

        fill : true,

        autoWidth : true,

        titleCollapse : true,

        hideCollapseTool : false,

        collapseFirst : false,

        animate : false,

        sequence : false,

        activeOnTop : false,

        renderItem : function(c){
            if(this.animate === false){
                c.animCollapse = false;
            }
            c.collapsible = true;
            if(this.autoWidth){
                c.autoWidth = true;
            }
            if(this.titleCollapse){
                c.titleCollapse = true;
            }
            if(this.hideCollapseTool){
                c.hideCollapseTool = true;
            }
            if(this.collapseFirst !== undefined){
                c.collapseFirst = this.collapseFirst;
            }
            if(!this.activeItem && !c.collapsed){
                this.activeItem = c;
            }else if(this.activeItem){
                c.collapsed = true;
            }
            Ext.layout.Accordion.superclass.renderItem.apply(this, arguments);
            c.header.addClass('x-accordion-hd');
            c.on('beforeexpand', this.beforeExpand, this);
        },

        beforeExpand : function(p, anim){
            var ai = this.activeItem;
            if(ai){
                if(this.sequence){
                    delete this.activeItem;
                    ai.collapse({callback:function(){
                        p.expand(anim || true);
                    }, scope: this});
                    return false;
                }else{
                    ai.collapse(this.animate);
                }
            }
            this.activeItem = p;
            if(this.activeOnTop){
                p.el.dom.parentNode.insertBefore(p.el.dom, p.el.dom.parentNode.firstChild);
            }
            this.layout();
        },

        setItemSize : function(item, size){
            if(this.fill && item){
                var items = this.container.items.items;
                var hh = 0;
                for(var i = 0, len = items.length; i < len; i++){
                    var p = items[i];
                    if(p != item){
                        hh += (p.getSize().height - p.bwrap.getHeight());
                    }
                }
                size.height -= hh;
                item.setSize(size);
            }
        }
    });
    Ext.Container.LAYOUTS['accordion'] = Ext.layout.Accordion;

    Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {

        monitorResize:false,

        setContainer : function(ct){
            Ext.layout.TableLayout.superclass.setContainer.call(this, ct);

            this.currentRow = 0;
            this.currentColumn = 0;
            this.cells = [];
        },

        onLayout : function(ct, target){
            var cs = ct.items.items, len = cs.length, c, i;

            if(!this.table){
                target.addClass('x-table-layout-ct');

                this.table = target.createChild(
                    {tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, null, true);

                this.renderAll(ct, target);
            }
        },

        getRow : function(index){
            var row = this.table.tBodies[0].childNodes[index];
            if(!row){
                row = document.createElement('tr');
                this.table.tBodies[0].appendChild(row);
            }
            return row;
        },

    	getNextCell : function(c){
    		var cell = this.getNextNonSpan(this.currentColumn, this.currentRow);
    		var curCol = this.currentColumn = cell[0], curRow = this.currentRow = cell[1];
    		for(var rowIndex = curRow; rowIndex < curRow + (c.rowspan || 1); rowIndex++){
    			if(!this.cells[rowIndex]){
    				this.cells[rowIndex] = [];
    			}
    			for(var colIndex = curCol; colIndex < curCol + (c.colspan || 1); colIndex++){
    				this.cells[rowIndex][colIndex] = true;
    			}
    		}
    		var td = document.createElement('td');
    		if(c.cellId){
    			td.id = c.cellId;
    		}
    		var cls = 'x-table-layout-cell';
    		if(c.cellCls){
    			cls += ' ' + c.cellCls;
    		}
    		td.className = cls;
    		if(c.colspan){
    			td.colSpan = c.colspan;
    		}
    		if(c.rowspan){
    			td.rowSpan = c.rowspan;
    		}
    		this.getRow(curRow).appendChild(td);
    		return td;
    	},

    	getNextNonSpan: function(colIndex, rowIndex){
    		var cols = this.columns;
    		while((cols && colIndex >= cols) || (this.cells[rowIndex] && this.cells[rowIndex][colIndex])) {
    			if(cols && colIndex >= cols){
    				rowIndex++;
    				colIndex = 0;
    			}else{
    				colIndex++;
    			}
    		}
    		return [colIndex, rowIndex];
    	},

        renderItem : function(c, position, target){
            if(c && !c.rendered){
                c.render(this.getNextCell(c));
            }
        },

        isValidParent : function(c, target){
            return true;
        }

    });

    Ext.Container.LAYOUTS['table'] = Ext.layout.TableLayout;

    Ext.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {
        extraCls: 'x-abs-layout-item',
        isForm: false,

        setContainer : function(ct){
            Ext.layout.AbsoluteLayout.superclass.setContainer.call(this, ct);
            if(ct.isXType('form')){
                this.isForm = true;
            }
        },

        onLayout : function(ct, target){
            if(this.isForm){ ct.body.position(); } else { target.position(); }
            Ext.layout.AbsoluteLayout.superclass.onLayout.call(this, ct, target);
        },

        getAnchorViewSize : function(ct, target){
            return this.isForm ? ct.body.getStyleSize() : Ext.layout.AbsoluteLayout.superclass.getAnchorViewSize.call(this, ct, target);
        },

        isValidParent : function(c, target){
            return this.isForm ? true : Ext.layout.AbsoluteLayout.superclass.isValidParent.call(this, c, target);
        },

        adjustWidthAnchor : function(value, comp){
            return value ? value - comp.getPosition(true)[0] : value;
        },

        adjustHeightAnchor : function(value, comp){
            return  value ? value - comp.getPosition(true)[1] : value;
        }

    });
    Ext.Container.LAYOUTS['absolute'] = Ext.layout.AbsoluteLayout;

    Ext.Viewport = Ext.extend(Ext.Container, {

        initComponent : function() {
            Ext.Viewport.superclass.initComponent.call(this);
            document.getElementsByTagName('html')[0].className += ' x-viewport';
            this.el = Ext.getBody();
            this.el.setHeight = Ext.emptyFn;
            this.el.setWidth = Ext.emptyFn;
            this.el.setSize = Ext.emptyFn;
            this.el.dom.scroll = 'no';
            this.allowDomMove = false;
            this.autoWidth = true;
            this.autoHeight = true;
            Ext.EventManager.onWindowResize(this.fireResize, this);
            this.renderTo = this.el;
        },

        fireResize : function(w, h){
            this.fireEvent('resize', this, w, h, w, h);
        }
    });
    Ext.reg('viewport', Ext.Viewport);

    Ext.Panel = Ext.extend(Ext.Container, {

        baseCls : 'x-panel',

        collapsedCls : 'x-panel-collapsed',

        maskDisabled: true,

        animCollapse: Ext.enableFx,

        headerAsText: true,

        buttonAlign: 'right',

        collapsed : false,

        collapseFirst: true,

        minButtonWidth:75,

        elements : 'body',

                    toolTarget : 'header',
        collapseEl : 'bwrap',
        slideAnchor : 't',

            deferHeight: true,
            expandDefaults: {
            duration:.25
        },
            collapseDefaults: {
            duration:.25
        },

            initComponent : function(){
            Ext.Panel.superclass.initComponent.call(this);

            this.addEvents(

                'bodyresize',

                'titlechange',

                'collapse',

                'expand',

                'beforecollapse',

                'beforeexpand',

                'beforeclose',

                'close',

                'activate',

                'deactivate'
            );

                    if(this.tbar){
                this.elements += ',tbar';
                if(typeof this.tbar == 'object'){
                    this.topToolbar = this.tbar;
                }
                delete this.tbar;
            }
            if(this.bbar){
                this.elements += ',bbar';
                if(typeof this.bbar == 'object'){
                    this.bottomToolbar = this.bbar;
                }
                delete this.bbar;
            }

            if(this.header === true){
                this.elements += ',header';
                delete this.header;
            }else if(this.title && this.header !== false){
                this.elements += ',header';
            }

            if(this.footer === true){
                this.elements += ',footer';
                delete this.footer;
            }

            if(this.buttons){
                var btns = this.buttons;

                this.buttons = [];
                for(var i = 0, len = btns.length; i < len; i++) {
                    if(btns[i].render){                     this.buttons.push(btns[i]);
                    }else{
                        this.addButton(btns[i]);
                    }
                }
            }
            if(this.autoLoad){
                this.on('render', this.doAutoLoad, this, {delay:10});
            }
        },

            createElement : function(name, pnode){
            if(this[name]){
                pnode.appendChild(this[name].dom);
                return;
            }

            if(name === 'bwrap' || this.elements.indexOf(name) != -1){
                if(this[name+'Cfg']){
                    this[name] = Ext.fly(pnode).createChild(this[name+'Cfg']);
                }else{
                    var el = document.createElement('div');
                    el.className = this[name+'Cls'];
                    this[name] = Ext.get(pnode.appendChild(el));
                }
            }
        },

            onRender : function(ct, position){
            Ext.Panel.superclass.onRender.call(this, ct, position);

            this.createClasses();

            if(this.el){             this.el.addClass(this.baseCls);
                this.header = this.el.down('.'+this.headerCls);
                this.bwrap = this.el.down('.'+this.bwrapCls);
                var cp = this.bwrap ? this.bwrap : this.el;
                this.tbar = cp.down('.'+this.tbarCls);
                this.body = cp.down('.'+this.bodyCls);
                this.bbar = cp.down('.'+this.bbarCls);
                this.footer = cp.down('.'+this.footerCls);
                this.fromMarkup = true;
            }else{
                this.el = ct.createChild({
                    id: this.id,
                    cls: this.baseCls
                }, position);
            }
            var el = this.el, d = el.dom;

            if(this.cls){
                this.el.addClass(this.cls);
            }

            if(this.buttons){
                this.elements += ',footer';
            }

                    if(this.frame){
                el.insertHtml('afterBegin', String.format(Ext.Element.boxMarkup, this.baseCls));

                this.createElement('header', d.firstChild.firstChild.firstChild);
                this.createElement('bwrap', d);

                            var bw = this.bwrap.dom;
                var ml = d.childNodes[1], bl = d.childNodes[2];
                bw.appendChild(ml);
                bw.appendChild(bl);

                var mc = bw.firstChild.firstChild.firstChild;
                this.createElement('tbar', mc);
                this.createElement('body', mc);
                this.createElement('bbar', mc);
                this.createElement('footer', bw.lastChild.firstChild.firstChild);

                if(!this.footer){
                    this.bwrap.dom.lastChild.className += ' x-panel-nofooter';
                }
            }else{
                this.createElement('header', d);
                this.createElement('bwrap', d);

                            var bw = this.bwrap.dom;
                this.createElement('tbar', bw);
                this.createElement('body', bw);
                this.createElement('bbar', bw);
                this.createElement('footer', bw);

                if(!this.header){
                    this.body.addClass(this.bodyCls + '-noheader');
                    if(this.tbar){
                        this.tbar.addClass(this.tbarCls + '-noheader');
                    }
                }
            }

            if(this.border === false){
                this.el.addClass(this.baseCls + '-noborder');
                this.body.addClass(this.bodyCls + '-noborder');
                if(this.header){
                    this.header.addClass(this.headerCls + '-noborder');
                }
                if(this.footer){
                    this.footer.addClass(this.footerCls + '-noborder');
                }
                if(this.tbar){
                    this.tbar.addClass(this.tbarCls + '-noborder');
                }
                if(this.bbar){
                    this.bbar.addClass(this.bbarCls + '-noborder');
                }
            }

            if(this.bodyBorder === false){
               this.body.addClass(this.bodyCls + '-noborder');
            }

            if(this.bodyStyle){
               this.body.applyStyles(this.bodyStyle);
            }

            this.bwrap.enableDisplayMode('block');

            if(this.header){
                this.header.unselectable();

                            if(this.headerAsText){
                    this.header.dom.innerHTML =
                        ''+this.header.dom.innerHTML+'';

                    if(this.iconCls){
                        this.setIconClass(this.iconCls);
                    }
                }
            }

            if(this.floating){
                this.makeFloating(this.floating);
            }

            if(this.collapsible){
                this.tools = this.tools ? this.tools.slice(0) : [];
                if(!this.hideCollapseTool){
                    this.tools[this.collapseFirst?'unshift':'push']({
                        id: 'toggle',
                        handler : this.toggleCollapse,
                        scope: this
                    });
                }
                if(this.titleCollapse && this.header){
                    this.header.on('click', this.toggleCollapse, this);
                    this.header.setStyle('cursor', 'pointer');
                }
            }
            if(this.tools){
                var ts = this.tools;
                this.tools = {};
                this.addTool.apply(this, ts);
            }else{
                this.tools = {};
            }

            if(this.buttons && this.buttons.length > 0){
                            var tb = this.footer.createChild({cls:'x-panel-btns-ct', cn: {
                    cls:"x-panel-btns x-panel-btns-"+this.buttonAlign,
                    html:''
                }}, null, true);
                var tr = tb.getElementsByTagName('tr')[0];
                for(var i = 0, len = this.buttons.length; i < len; i++) {
                    var b = this.buttons[i];
                    var td = document.createElement('td');
                    td.className = 'x-panel-btn-td';
                    b.render(tr.appendChild(td));
                }
            }

            if(this.tbar && this.topToolbar){
                if(Ext.isArray(this.topToolbar)){
                    this.topToolbar = new Ext.Toolbar(this.topToolbar);
                }
                this.topToolbar.render(this.tbar);
            }
            if(this.bbar && this.bottomToolbar){
                if(Ext.isArray(this.bottomToolbar)){
                    this.bottomToolbar = new Ext.Toolbar(this.bottomToolbar);
                }
                this.bottomToolbar.render(this.bbar);
            }
        },

        setIconClass : function(cls){
            var old = this.iconCls;
            this.iconCls = cls;
            if(this.rendered && this.header){
                if(this.frame){
                    this.header.addClass('x-panel-icon');
                    this.header.replaceClass(old, this.iconCls);
                }else{
                    var hd = this.header.dom;
                    var img = hd.firstChild && String(hd.firstChild.tagName).toLowerCase() == 'img' ? hd.firstChild : null;
                    if(img){
                        Ext.fly(img).replaceClass(old, this.iconCls);
                    }else{
                        Ext.DomHelper.insertBefore(hd.firstChild, {
                            tag:'img', src: Ext.BLANK_IMAGE_URL, cls:'x-panel-inline-icon '+this.iconCls
                        });
                     }
                }
            }
        },

            makeFloating : function(cfg){
            this.floating = true;
            this.el = new Ext.Layer(
                typeof cfg == 'object' ? cfg : {
                    shadow: this.shadow !== undefined ? this.shadow : 'sides',
                    shadowOffset: this.shadowOffset,
                    constrain:false,
                    shim: this.shim === false ? false : undefined
                }, this.el
            );
        },

        getTopToolbar : function(){
            return this.topToolbar;
        },

        getBottomToolbar : function(){
            return this.bottomToolbar;
        },

        addButton : function(config, handler, scope){
            var bc = {
                handler: handler,
                scope: scope,
                minWidth: this.minButtonWidth,
                hideParent:true
            };
            if(typeof config == "string"){
                bc.text = config;
            }else{
                Ext.apply(bc, config);
            }
            var btn = new Ext.Button(bc);
            btn.ownerCt = this;
            if(!this.buttons){
                this.buttons = [];
            }
            this.buttons.push(btn);
            return btn;
        },

            addTool : function(){
            if(!this[this.toolTarget]) {             return;
            }
            if(!this.toolTemplate){
                            var tt = new Ext.Template(
                     ' '
                );
                tt.disableFormats = true;
                tt.compile();
                Ext.Panel.prototype.toolTemplate = tt;
            }
            for(var i = 0, a = arguments, len = a.length; i < len; i++) {
                var tc = a[i], overCls = 'x-tool-'+tc.id+'-over';
                var t = this.toolTemplate.insertFirst(this[this.toolTarget], tc, true);
                this.tools[tc.id] = t;
                t.enableDisplayMode('block');
                t.on('click', this.createToolHandler(t, tc, overCls, this));
                if(tc.on){
                    t.on(tc.on);
                }
                if(tc.hidden){
                    t.hide();
                }
                if(tc.qtip){
                    if(typeof tc.qtip == 'object'){
                        Ext.QuickTips.register(Ext.apply({
                              target: t.id
                        }, tc.qtip));
                    } else {
                        t.dom.qtip = tc.qtip;
                    }
                }
                t.addClassOnOver(overCls);
            }
        },

            onShow : function(){
            if(this.floating){
                return this.el.show();
            }
            Ext.Panel.superclass.onShow.call(this);
        },

            onHide : function(){
            if(this.floating){
                return this.el.hide();
            }
            Ext.Panel.superclass.onHide.call(this);
        },

            createToolHandler : function(t, tc, overCls, panel){
            return function(e){
                t.removeClass(overCls);
                e.stopEvent();
                if(tc.handler){
                    tc.handler.call(tc.scope || t, e, t, panel);
                }
            };
        },

            afterRender : function(){
            if(this.fromMarkup && this.height === undefined && !this.autoHeight){
                this.height = this.el.getHeight();
            }
            if(this.floating && !this.hidden && !this.initHidden){
                this.el.show();
            }
            if(this.title){
                this.setTitle(this.title);
            }
    		this.setAutoScroll();
            if(this.html){
                this.body.update(typeof this.html == 'object' ?
                                 Ext.DomHelper.markup(this.html) :
                                 this.html);
                delete this.html;
            }
            if(this.contentEl){
                var ce = Ext.getDom(this.contentEl);
                Ext.fly(ce).removeClass(['x-hidden', 'x-hide-display']);
                this.body.dom.appendChild(ce);
            }
            if(this.collapsed){
                this.collapsed = false;
                this.collapse(false);
            }
            Ext.Panel.superclass.afterRender.call(this);         this.initEvents();
        },

            setAutoScroll : function(){
            if(this.rendered && this.autoScroll){
    			this.body.setOverflow('auto');
            }
        },

            getKeyMap : function(){
            if(!this.keyMap){
                this.keyMap = new Ext.KeyMap(this.el, this.keys);
            }
            return this.keyMap;
        },

            initEvents : function(){
            if(this.keys){
                this.getKeyMap();
            }
            if(this.draggable){
                this.initDraggable();
            }
        },

            initDraggable : function(){
            this.dd = new Ext.Panel.DD(this, typeof this.draggable == 'boolean' ? null : this.draggable);
        },

            beforeEffect : function(){
            if(this.floating){
                this.el.beforeAction();
            }
            this.el.addClass('x-panel-animated');
        },

            afterEffect : function(){
            this.syncShadow();
            this.el.removeClass('x-panel-animated');
        },

            createEffect : function(a, cb, scope){
            var o = {
                scope:scope,
                block:true
            };
            if(a === true){
                o.callback = cb;
                return o;
            }else if(!a.callback){
                o.callback = cb;
            }else {             o.callback = function(){
                    cb.call(scope);
                    Ext.callback(a.callback, a.scope);
                };
            }
            return Ext.applyIf(o, a);
        },

        collapse : function(animate){
            if(this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforecollapse', this, animate) === false){
                return;
            }
            var doAnim = animate === true || (animate !== false && this.animCollapse);
            this.beforeEffect();
            this.onCollapse(doAnim, animate);
            return this;
        },

            onCollapse : function(doAnim, animArg){
            if(doAnim){
                this[this.collapseEl].slideOut(this.slideAnchor,
                        Ext.apply(this.createEffect(animArg||true, this.afterCollapse, this),
                            this.collapseDefaults));
            }else{
                this[this.collapseEl].hide();
                this.afterCollapse();
            }
        },

            afterCollapse : function(){
            this.collapsed = true;
            this.el.addClass(this.collapsedCls);
            this.afterEffect();
            this.fireEvent('collapse', this);
        },

        expand : function(animate){
            if(!this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforeexpand', this, animate) === false){
                return;
            }
            var doAnim = animate === true || (animate !== false && this.animCollapse);
            this.el.removeClass(this.collapsedCls);
            this.beforeEffect();
            this.onExpand(doAnim, animate);
            return this;
        },

            onExpand : function(doAnim, animArg){
            if(doAnim){
                this[this.collapseEl].slideIn(this.slideAnchor,
                        Ext.apply(this.createEffect(animArg||true, this.afterExpand, this),
                            this.expandDefaults));
            }else{
                this[this.collapseEl].show();
                this.afterExpand();
            }
        },

            afterExpand : function(){
            this.collapsed = false;
            this.afterEffect();
            this.fireEvent('expand', this);
        },

        toggleCollapse : function(animate){
            this[this.collapsed ? 'expand' : 'collapse'](animate);
            return this;
        },

            onDisable : function(){
            if(this.rendered && this.maskDisabled){
                this.el.mask();
            }
            Ext.Panel.superclass.onDisable.call(this);
        },

            onEnable : function(){
            if(this.rendered && this.maskDisabled){
                this.el.unmask();
            }
            Ext.Panel.superclass.onEnable.call(this);
        },

            onResize : function(w, h){
            if(w !== undefined || h !== undefined){
                if(!this.collapsed){
                    if(typeof w == 'number'){
                        this.body.setWidth(
                                this.adjustBodyWidth(w - this.getFrameWidth()));
                    }else if(w == 'auto'){
                        this.body.setWidth(w);
                    }

                    if(typeof h == 'number'){
                        this.body.setHeight(
                                this.adjustBodyHeight(h - this.getFrameHeight()));
                    }else if(h == 'auto'){
                        this.body.setHeight(h);
                    }
                }else{
                    this.queuedBodySize = {width: w, height: h};
                    if(!this.queuedExpand && this.allowQueuedExpand !== false){
                        this.queuedExpand = true;
                        this.on('expand', function(){
                            delete this.queuedExpand;
                            this.onResize(this.queuedBodySize.width, this.queuedBodySize.height);
                            this.doLayout();
                        }, this, {single:true});
                    }
                }
                this.fireEvent('bodyresize', this, w, h);
            }
            this.syncShadow();
        },

            adjustBodyHeight : function(h){
            return h;
        },

            adjustBodyWidth : function(w){
            return w;
        },

            onPosition : function(){
            this.syncShadow();
        },

            onDestroy : function(){
            if(this.tools){
                for(var k in this.tools){
                    Ext.destroy(this.tools[k]);
                }
            }
            if(this.buttons){
                for(var b in this.buttons){
                    Ext.destroy(this.buttons[b]);
                }
            }
            Ext.destroy(
                this.topToolbar,
                this.bottomToolbar
            );
            Ext.Panel.superclass.onDestroy.call(this);
        },

        getFrameWidth : function(){
            var w = this.el.getFrameWidth('lr');

            if(this.frame){
                var l = this.bwrap.dom.firstChild;
                w += (Ext.fly(l).getFrameWidth('l') + Ext.fly(l.firstChild).getFrameWidth('r'));
                var mc = this.bwrap.dom.firstChild.firstChild.firstChild;
                w += Ext.fly(mc).getFrameWidth('lr');
            }
            return w;
        },

        getFrameHeight : function(){
            var h  = this.el.getFrameWidth('tb');
            h += (this.tbar ? this.tbar.getHeight() : 0) +
                 (this.bbar ? this.bbar.getHeight() : 0);

            if(this.frame){
                var hd = this.el.dom.firstChild;
                var ft = this.bwrap.dom.lastChild;
                h += (hd.offsetHeight + ft.offsetHeight);
                var mc = this.bwrap.dom.firstChild.firstChild.firstChild;
                h += Ext.fly(mc).getFrameWidth('tb');
            }else{
                h += (this.header ? this.header.getHeight() : 0) +
                    (this.footer ? this.footer.getHeight() : 0);
            }
            return h;
        },

        getInnerWidth : function(){
            return this.getSize().width - this.getFrameWidth();
        },

        getInnerHeight : function(){
            return this.getSize().height - this.getFrameHeight();
        },

            syncShadow : function(){
            if(this.floating){
                this.el.sync(true);
            }
        },

            getLayoutTarget : function(){
            return this.body;
        },

        setTitle : function(title, iconCls){
            this.title = title;
            if(this.header && this.headerAsText){
                this.header.child('span').update(title);
            }
            if(iconCls){
                this.setIconClass(iconCls);
            }
            this.fireEvent('titlechange', this, title);
            return this;
        },

        getUpdater : function(){
            return this.body.getUpdater();
        },

        load : function(){
            var um = this.body.getUpdater();
            um.update.apply(um, arguments);
            return this;
        },

            beforeDestroy : function(){
            Ext.Element.uncache(
                this.header,
                this.tbar,
                this.bbar,
                this.footer,
                this.body
            );
        },

            createClasses : function(){
            this.headerCls = this.baseCls + '-header';
            this.headerTextCls = this.baseCls + '-header-text';
            this.bwrapCls = this.baseCls + '-bwrap';
            this.tbarCls = this.baseCls + '-tbar';
            this.bodyCls = this.baseCls + '-body';
            this.bbarCls = this.baseCls + '-bbar';
            this.footerCls = this.baseCls + '-footer';
        },

            createGhost : function(cls, useShim, appendTo){
            var el = document.createElement('div');
            el.className = 'x-panel-ghost ' + (cls ? cls : '');
            if(this.header){
                el.appendChild(this.el.dom.firstChild.cloneNode(true));
            }
            Ext.fly(el.appendChild(document.createElement('ul'))).setHeight(this.bwrap.getHeight());
            el.style.width = this.el.dom.offsetWidth + 'px';;
            if(!appendTo){
                this.container.dom.appendChild(el);
            }else{
                Ext.getDom(appendTo).appendChild(el);
            }
            if(useShim !== false && this.el.useShim !== false){
                var layer = new Ext.Layer({shadow:false, useDisplay:true, constrain:false}, el);
                layer.show();
                return layer;
            }else{
                return new Ext.Element(el);
            }
        },

            doAutoLoad : function(){
            this.body.load(
                typeof this.autoLoad == 'object' ?
                    this.autoLoad : {url: this.autoLoad});
        }

    });
    Ext.reg('panel', Ext.Panel);

    Ext.Window = Ext.extend(Ext.Panel, {

        baseCls : 'x-window',

        resizable:true,

        draggable:true,

        closable : true,

        constrain:false,

        constrainHeader:false,

        plain:false,

        minimizable : false,

        maximizable : false,

        minHeight: 100,

        minWidth: 200,

        expandOnShow: true,

        closeAction: 'close',

            collapsible:false,

            initHidden : true,

        monitorResize : true,

        elements: 'header,body',

        frame:true,

        floating:true,

            initComponent : function(){
            Ext.Window.superclass.initComponent.call(this);
            this.addEvents(

                'resize',

                'maximize',

                'minimize',

                'restore'
            );
        },

            getState : function(){
            return Ext.apply(Ext.Window.superclass.getState.call(this) || {}, this.getBox());
        },

            onRender : function(ct, position){
            Ext.Window.superclass.onRender.call(this, ct, position);

            if(this.plain){
                this.el.addClass('x-window-plain');
            }

                    this.focusEl = this.el.createChild({
                        tag: "a", href:"#", cls:"x-dlg-focus",
                        tabIndex:"-1", html: " "});
            this.focusEl.swallowEvent('click', true);

            this.proxy = this.el.createProxy("x-window-proxy");
            this.proxy.enableDisplayMode('block');

            if(this.modal){
                this.mask = this.container.createChild({cls:"ext-el-mask"}, this.el.dom);
                this.mask.enableDisplayMode("block");
                this.mask.hide();
            }
        },

            initEvents : function(){
            Ext.Window.superclass.initEvents.call(this);
            if(this.animateTarget){
                this.setAnimateTarget(this.animateTarget);
            }

            if(this.resizable){
                this.resizer = new Ext.Resizable(this.el, {
                    minWidth: this.minWidth,
                    minHeight:this.minHeight,
                    handles: this.resizeHandles || "all",
                    pinned: true,
                    resizeElement : this.resizerAction
                });
                this.resizer.window = this;
                this.resizer.on("beforeresize", this.beforeResize, this);
            }

            if(this.draggable){
                this.header.addClass("x-window-draggable");
            }
            this.initTools();

            this.el.on("mousedown", this.toFront, this);
            this.manager = this.manager || Ext.WindowMgr;
            this.manager.register(this);
            this.hidden = true;
            if(this.maximized){
                this.maximized = false;
                this.maximize();
            }
            if(this.closable){
                var km = this.getKeyMap();
                km.on(27, this.onEsc, this);
                km.disable();
            }
        },

        initDraggable : function(){
            this.dd = new Ext.Window.DD(this);
        },

           onEsc : function(){
            this[this.closeAction]();
        },

            beforeDestroy : function(){
            Ext.destroy(
                this.resizer,
                this.dd,
                this.proxy,
                this.mask
            );
            Ext.Window.superclass.beforeDestroy.call(this);
        },

            onDestroy : function(){
            if(this.manager){
                this.manager.unregister(this);
            }
            Ext.Window.superclass.onDestroy.call(this);
        },

            initTools : function(){
            if(this.minimizable){
                this.addTool({
                    id: 'minimize',
                    handler: this.minimize.createDelegate(this, [])
                });
            }
            if(this.maximizable){
                this.addTool({
                    id: 'maximize',
                    handler: this.maximize.createDelegate(this, [])
                });
                this.addTool({
                    id: 'restore',
                    handler: this.restore.createDelegate(this, []),
                    hidden:true
                });
                this.header.on('dblclick', this.toggleMaximize, this);
            }
            if(this.closable){
                this.addTool({
                    id: 'close',
                    handler: this[this.closeAction].createDelegate(this, [])
                });
            }
        },

            resizerAction : function(){
            var box = this.proxy.getBox();
            this.proxy.hide();
            this.window.handleResize(box);
            return box;
        },

            beforeResize : function(){
            this.resizer.minHeight = Math.max(this.minHeight, this.getFrameHeight() + 40);         this.resizer.minWidth = Math.max(this.minWidth, this.getFrameWidth() + 40);
            this.resizeBox = this.el.getBox();
        },

            updateHandles : function(){
            if(Ext.isIE && this.resizer){
                this.resizer.syncHandleHeight();
                this.el.repaint();
            }
        },

            handleResize : function(box){
            var rz = this.resizeBox;
            if(rz.x != box.x || rz.y != box.y){
                this.updateBox(box);
            }else{
                this.setSize(box);
            }
            this.focus();
            this.updateHandles();
            this.saveState();
            this.fireEvent("resize", this, box.width, box.height);
        },

        focus : function(){
            var f = this.focusEl, db = this.defaultButton, t = typeof db;
            if(t != 'undefined'){
                if(t == 'number'){
                    f = this.buttons[db];
                }else if(t == 'string'){
                    f = Ext.getCmp(db);
                }else{
                    f = db;
                }
            }
            f.focus.defer(10, f);
        },

        setAnimateTarget : function(el){
            el = Ext.get(el);
            this.animateTarget = el;
        },

            beforeShow : function(){
            delete this.el.lastXY;
            delete this.el.lastLT;
            if(this.x === undefined || this.y === undefined){
                var xy = this.el.getAlignToXY(this.container, 'c-c');
                var pos = this.el.translatePoints(xy[0], xy[1]);
                this.x = this.x === undefined? pos.left : this.x;
                this.y = this.y === undefined? pos.top : this.y;
            }
            this.el.setLeftTop(this.x, this.y);

            if(this.expandOnShow){
                this.expand(false);
            }

            if(this.modal){
                Ext.getBody().addClass("x-body-masked");
                this.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
                this.mask.show();
            }
        },

        show : function(animateTarget, cb, scope){
            if(!this.rendered){
                this.render(Ext.getBody());
            }
            if(this.hidden === false){
                this.toFront();
                return;
            }
            if(this.fireEvent("beforeshow", this) === false){
                return;
            }
            if(cb){
                this.on('show', cb, scope, {single:true});
            }
            this.hidden = false;
            if(animateTarget !== undefined){
                this.setAnimateTarget(animateTarget);
            }
            this.beforeShow();
            if(this.animateTarget){
                this.animShow();
            }else{
                this.afterShow();
            }
        },

            afterShow : function(){
            this.proxy.hide();
            this.el.setStyle('display', 'block');
            this.el.show();
            if(this.maximized){
                this.fitContainer();
            }
            if(Ext.isMac && Ext.isGecko){         	this.cascade(this.setAutoScroll);
            }

            if(this.monitorResize || this.modal || this.constrain || this.constrainHeader){
                Ext.EventManager.onWindowResize(this.onWindowResize, this);
            }
            this.doConstrain();
            if(this.layout){
                this.doLayout();
            }
            if(this.keyMap){
                this.keyMap.enable();
            }
            this.toFront();
            this.updateHandles();
            this.fireEvent("show", this);
        },

            animShow : function(){
            this.proxy.show();
            this.proxy.setBox(this.animateTarget.getBox());
            this.proxy.setOpacity(0);
            var b = this.getBox(false);
            b.callback = this.afterShow;
            b.scope = this;
            b.duration = .25;
            b.easing = 'easeNone';
            b.opacity = .5;
            b.block = true;
            this.el.setStyle('display', 'none');
            this.proxy.shift(b);
        },

        hide : function(animateTarget, cb, scope){
            if(this.hidden || this.fireEvent("beforehide", this) === false){
                return;
            }
            if(cb){
                this.on('hide', cb, scope, {single:true});
            }
            this.hidden = true;
            if(animateTarget !== undefined){
                this.setAnimateTarget(animateTarget);
            }
            if(this.animateTarget){
                this.animHide();
            }else{
                this.el.hide();
                this.afterHide();
            }
        },

            afterHide : function(){
            this.proxy.hide();
            if(this.monitorResize || this.modal || this.constrain || this.constrainHeader){
                Ext.EventManager.removeResizeListener(this.onWindowResize, this);
            }
            if(this.modal){
                this.mask.hide();
                Ext.getBody().removeClass("x-body-masked");
            }
            if(this.keyMap){
                this.keyMap.disable();
            }
            this.fireEvent("hide", this);
        },

            animHide : function(){
            this.proxy.setOpacity(.5);
            this.proxy.show();
            var tb = this.getBox(false);
            this.proxy.setBox(tb);
            this.el.hide();
            var b = this.animateTarget.getBox();
            b.callback = this.afterHide;
            b.scope = this;
            b.duration = .25;
            b.easing = 'easeNone';
            b.block = true;
            b.opacity = 0;
            this.proxy.shift(b);
        },

            onWindowResize : function(){
            if(this.maximized){
                this.fitContainer();
            }
            if(this.modal){
                this.mask.setSize('100%', '100%');
                var force = this.mask.dom.offsetHeight;
                this.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
            }
            this.doConstrain();
        },

            doConstrain : function(){
            if(this.constrain || this.constrainHeader){
                var offsets;
                if(this.constrain){
                    offsets = {
                        right:this.el.shadowOffset,
                        left:this.el.shadowOffset,
                        bottom:this.el.shadowOffset
                    };
                }else {
                    var s = this.getSize();
                    offsets = {
                        right:-(s.width - 100),
                        bottom:-(s.height - 25)
                    };
                }

                var xy = this.el.getConstrainToXY(this.container, true, offsets);
                if(xy){
                    this.setPosition(xy[0], xy[1]);
                }
            }
        },

            ghost : function(cls){
            var ghost = this.createGhost(cls);
            var box = this.getBox(true);
            ghost.setLeftTop(box.x, box.y);
            ghost.setWidth(box.width);
            this.el.hide();
            this.activeGhost = ghost;
            return ghost;
        },

            unghost : function(show, matchPosition){
            if(show !== false){
                this.el.show();
                this.focus();
    	        if(Ext.isMac && Ext.isGecko){ 	        	this.cascade(this.setAutoScroll);
    	        }
            }
            if(matchPosition !== false){
                this.setPosition(this.activeGhost.getLeft(true), this.activeGhost.getTop(true));
            }
            this.activeGhost.hide();
            this.activeGhost.remove();
            delete this.activeGhost;
        },

        minimize : function(){
            this.fireEvent('minimize', this);
        },

        close : function(){
            if(this.fireEvent("beforeclose", this) !== false){
                this.hide(null, function(){
                    this.fireEvent('close', this);
                    this.destroy();
                }, this);
            }
        },

        maximize : function(){
            if(!this.maximized){
                this.expand(false);
                this.restoreSize = this.getSize();
                this.restorePos = this.getPosition(true);
                this.tools.maximize.hide();
                this.tools.restore.show();
                this.maximized = true;
                this.el.disableShadow();

                if(this.dd){
                    this.dd.lock();
                }
                if(this.collapsible){
                    this.tools.toggle.hide();
                }
                this.el.addClass('x-window-maximized');
                this.container.addClass('x-window-maximized-ct');

                this.setPosition(0, 0);
                this.fitContainer();
                this.fireEvent('maximize', this);
            }
        },

        restore : function(){
            if(this.maximized){
                this.el.removeClass('x-window-maximized');
                this.tools.restore.hide();
                this.tools.maximize.show();
                this.setPosition(this.restorePos[0], this.restorePos[1]);
                this.setSize(this.restoreSize.width, this.restoreSize.height);
                delete this.restorePos;
                delete this.restoreSize;
                this.maximized = false;
                this.el.enableShadow(true);

                if(this.dd){
                    this.dd.unlock();
                }
                if(this.collapsible){
                    this.tools.toggle.show();
                }
                this.container.removeClass('x-window-maximized-ct');

                this.doConstrain();
                this.fireEvent('restore', this);
            }
        },

        toggleMaximize : function(){
            this[this.maximized ? 'restore' : 'maximize']();
        },

            fitContainer : function(){
            var vs = this.container.getViewSize();
            this.setSize(vs.width, vs.height);
        },

                setZIndex : function(index){
            if(this.modal){
                this.mask.setStyle("z-index", index);
            }
            this.el.setZIndex(++index);
            index += 5;

            if(this.resizer){
                this.resizer.proxy.setStyle("z-index", ++index);
            }

            this.lastZIndex = index;
        },

        alignTo : function(element, position, offsets){
            var xy = this.el.getAlignToXY(element, position, offsets);
            this.setPagePosition(xy[0], xy[1]);
            return this;
        },

        anchorTo : function(el, alignment, offsets, monitorScroll, _pname){
            var action = function(){
                this.alignTo(el, alignment, offsets);
            };
            Ext.EventManager.onWindowResize(action, this);
            var tm = typeof monitorScroll;
            if(tm != 'undefined'){
                Ext.EventManager.on(window, 'scroll', action, this,
                    {buffer: tm == 'number' ? monitorScroll : 50});
            }
            action.call(this);
            this[_pname] = action;
            return this;
        },

        toFront : function(){
            if(this.manager.bringToFront(this)){
                this.focus();
            }
            return this;
        },

        setActive : function(active){
            if(active){
                if(!this.maximized){
                    this.el.enableShadow(true);
                }
                this.fireEvent('activate', this);
            }else{
                this.el.disableShadow();
                this.fireEvent('deactivate', this);
            }
        },

        toBack : function(){
            this.manager.sendToBack(this);
            return this;
        },

        center : function(){
            var xy = this.el.getAlignToXY(this.container, 'c-c');
            this.setPagePosition(xy[0], xy[1]);
            return this;
        }
    });
    Ext.reg('window', Ext.Window);

    Ext.Window.DD = function(win){
        this.win = win;
        Ext.Window.DD.superclass.constructor.call(this, win.el.id, 'WindowDD-'+win.id);
        this.setHandleElId(win.header.id);
        this.scroll = false;
    };

    Ext.extend(Ext.Window.DD, Ext.dd.DD, {
        moveOnly:true,
        headerOffsets:[100, 25],
        startDrag : function(){
            var w = this.win;
            this.proxy = w.ghost();
            if(w.constrain !== false){
                var so = w.el.shadowOffset;
                this.constrainTo(w.container, {right: so, left: so, bottom: so});
            }else if(w.constrainHeader !== false){
                var s = this.proxy.getSize();
                this.constrainTo(w.container, {right: -(s.width-this.headerOffsets[0]), bottom: -(s.height-this.headerOffsets[1])});
            }
        },
        b4Drag : Ext.emptyFn,

        onDrag : function(e){
            this.alignElWithMouse(this.proxy, e.getPageX(), e.getPageY());
        },

        endDrag : function(e){
            this.win.unghost();
            this.win.saveState();
        }
    });

    Ext.WindowGroup = function(){
        var list = {};
        var accessList = [];
        var front = null;

            var sortWindows = function(d1, d2){
            return (!d1._lastAccess || d1._lastAccess < d2._lastAccess) ? -1 : 1;
        };

            var orderWindows = function(){
            var a = accessList, len = a.length;
            if(len > 0){
                a.sort(sortWindows);
                var seed = a[0].manager.zseed;
                for(var i = 0; i < len; i++){
                    var win = a[i];
                    if(win && !win.hidden){
                        win.setZIndex(seed + (i*10));
                    }
                }
            }
            activateLast();
        };

            var setActiveWin = function(win){
            if(win != front){
                if(front){
                    front.setActive(false);
                }
                front = win;
                if(win){
                    win.setActive(true);
                }
            }
        };

            var activateLast = function(){
            for(var i = accessList.length-1; i >=0; --i) {
                if(!accessList[i].hidden){
                    setActiveWin(accessList[i]);
                    return;
                }
            }
                    setActiveWin(null);
        };

        return {

            zseed : 9000,

                    register : function(win){
                list[win.id] = win;
                accessList.push(win);
                win.on('hide', activateLast);
            },

                    unregister : function(win){
                delete list[win.id];
                win.un('hide', activateLast);
                accessList.remove(win);
            },

            get : function(id){
                return typeof id == "object" ? id : list[id];
            },

            bringToFront : function(win){
                win = this.get(win);
                if(win != front){
                    win._lastAccess = new Date().getTime();
                    orderWindows();
                    return true;
                }
                return false;
            },

            sendToBack : function(win){
                win = this.get(win);
                win._lastAccess = -(new Date().getTime());
                orderWindows();
                return win;
            },

            hideAll : function(){
                for(var id in list){
                    if(list[id] && typeof list[id] != "function" && list[id].isVisible()){
                        list[id].hide();
                    }
                }
            },

            getActive : function(){
                return front;
            },

            getBy : function(fn, scope){
                var r = [];
                for(var i = accessList.length-1; i >=0; --i) {
                    var win = accessList[i];
                    if(fn.call(scope||win, win) !== false){
                        r.push(win);
                    }
                }
                return r;
            },

            each : function(fn, scope){
                for(var id in list){
                    if(list[id] && typeof list[id] != "function"){
                        if(fn.call(scope || list[id], list[id]) === false){
                            return;
                        }
                    }
                }
            }
        };
    };

    Ext.WindowMgr = new Ext.WindowGroup();

    Ext.dd.PanelProxy = function(panel, config){
        this.panel = panel;
        this.id = this.panel.id +'-ddproxy';
        Ext.apply(this, config);
    };

    Ext.dd.PanelProxy.prototype = {

        insertProxy : true,

        setStatus : Ext.emptyFn,
        reset : Ext.emptyFn,
        update : Ext.emptyFn,
        stop : Ext.emptyFn,
        sync: Ext.emptyFn,

        getEl : function(){
            return this.ghost;
        },

        getGhost : function(){
            return this.ghost;
        },

        getProxy : function(){
            return this.proxy;
        },

        hide : function(){
            if(this.ghost){
                if(this.proxy){
                    this.proxy.remove();
                    delete this.proxy;
                }
                this.panel.el.dom.style.display = '';
                this.ghost.remove();
                delete this.ghost;
            }
        },

        show : function(){
            if(!this.ghost){
                this.ghost = this.panel.createGhost(undefined, undefined, Ext.getBody());
                this.ghost.setXY(this.panel.el.getXY())
                if(this.insertProxy){
                    this.proxy = this.panel.el.insertSibling({cls:'x-panel-dd-spacer'});
                    this.proxy.setSize(this.panel.getSize());
                }
                this.panel.el.dom.style.display = 'none';
            }
        },

        repair : function(xy, callback, scope){
            this.hide();
            if(typeof callback == "function"){
                callback.call(scope || this);
            }
        },

        moveProxy : function(parentNode, before){
            if(this.proxy){
                parentNode.insertBefore(this.proxy.dom, before);
            }
        }
    };

    Ext.Panel.DD = function(panel, cfg){
        this.panel = panel;
        this.dragData = {panel: panel};
        this.proxy = new Ext.dd.PanelProxy(panel, cfg);
        Ext.Panel.DD.superclass.constructor.call(this, panel.el, cfg);
        this.setHandleElId(panel.header.id);
        panel.header.setStyle('cursor', 'move');
        this.scroll = false;
    };

    Ext.extend(Ext.Panel.DD, Ext.dd.DragSource, {
        showFrame: Ext.emptyFn,
        startDrag: Ext.emptyFn,
        b4StartDrag: function(x, y) {
            this.proxy.show();
        },
        b4MouseDown: function(e) {
            var x = e.getPageX();
            var y = e.getPageY();
            this.autoOffset(x, y);
        },
        onInitDrag : function(x, y){
            this.onStartDrag(x, y);
            return true;
        },
        createFrame : Ext.emptyFn,
        getDragEl : function(e){
            return this.proxy.ghost.dom;
        },
        endDrag : function(e){
            this.proxy.hide();
            this.panel.saveState();
        },

        autoOffset : function(x, y) {
            x -= this.startPageX;
            y -= this.startPageY;
            this.setDelta(x, y);
        }
    });

    Ext.state.Provider = function(){

        this.addEvents("statechange");
        this.state = {};
        Ext.state.Provider.superclass.constructor.call(this);
    };
    Ext.extend(Ext.state.Provider, Ext.util.Observable, {

        get : function(name, defaultValue){
            return typeof this.state[name] == "undefined" ?
                defaultValue : this.state[name];
        },

        clear : function(name){
            delete this.state[name];
            this.fireEvent("statechange", this, name, null);
        },

        set : function(name, value){
            this.state[name] = value;

            this.fireEvent("statechange", this, name, value);
        },

        decodeValue : function(cookie){
            var re = /^(a|n|d|b|s|o)\:(.*)$/;
            var matches = re.exec(unescape(cookie));
            if(!matches || !matches[1]) return;
            var type = matches[1];
            var v = matches[2];
            switch(type){
                case "n":
                    return parseFloat(v);
                case "d":
                    return new Date(Date.parse(v));
                case "b":
                    return (v == "1");
                case "a":
                    var all = [];
                    var values = v.split("^");
                    for(var i = 0, len = values.length; i < len; i++){
                        all.push(this.decodeValue(values[i]));
                    }
                    return all;
               case "o":
                    var all = {};
                    var values = v.split("^");
                    for(var i = 0, len = values.length; i < len; i++){
                        var kv = values[i].split("=");
                        all[kv[0]] = this.decodeValue(kv[1]);
                    }
                    return all;
               default:
                    return v;
            }
        },

        encodeValue : function(v){
            var enc;
            if(typeof v == "number"){
                enc = "n:" + v;
            }else if(typeof v == "boolean"){
                enc = "b:" + (v ? "1" : "0");
            }else if(Ext.isDate(v)){
                enc = "d:" + v.toGMTString();
            }else if(Ext.isArray(v)){
                var flat = "";
                for(var i = 0, len = v.length; i < len; i++){
                    flat += this.encodeValue(v[i]);
                    if(i != len-1) flat += "^";
                }
                enc = "a:" + flat;
            }else if(typeof v == "object"){
                var flat = "";
                for(var key in v){
                    if(typeof v[key] != "function" && v[key] !== undefined){
                        flat += key + "=" + this.encodeValue(v[key]) + "^";
                    }
                }
                enc = "o:" + flat.substring(0, flat.length-1);
            }else{
                enc = "s:" + v;
            }
            return escape(enc);
        }
    });

    Ext.state.Manager = function(){
        var provider = new Ext.state.Provider();

        return {

            setProvider : function(stateProvider){
                provider = stateProvider;
            },

            get : function(key, defaultValue){
                return provider.get(key, defaultValue);
            },

             set : function(key, value){
                provider.set(key, value);
            },

            clear : function(key){
                provider.clear(key);
            },

            getProvider : function(){
                return provider;
            }
        };
    }();

    Ext.state.CookieProvider = function(config){
        Ext.state.CookieProvider.superclass.constructor.call(this);
        this.path = "/";
        this.expires = new Date(new Date().getTime()+(1000*60*60*24*7));
        this.domain = null;
        this.secure = false;
        Ext.apply(this, config);
        this.state = this.readCookies();
    };

    Ext.extend(Ext.state.CookieProvider, Ext.state.Provider, {

        set : function(name, value){
            if(typeof value == "undefined" || value === null){
                this.clear(name);
                return;
            }
            this.setCookie(name, value);
            Ext.state.CookieProvider.superclass.set.call(this, name, value);
        },

        clear : function(name){
            this.clearCookie(name);
            Ext.state.CookieProvider.superclass.clear.call(this, name);
        },

        readCookies : function(){
            var cookies = {};
            var c = document.cookie + ";";
            var re = /\s?(.*?)=(.*?);/g;
        	var matches;
        	while((matches = re.exec(c)) != null){
                var name = matches[1];
                var value = matches[2];
                if(name && name.substring(0,3) == "ys-"){
                    cookies[name.substr(3)] = this.decodeValue(value);
                }
            }
            return cookies;
        },

        setCookie : function(name, value){
            document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
               ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
               ((this.path == null) ? "" : ("; path=" + this.path)) +
               ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
               ((this.secure == true) ? "; secure" : "");
        },

        clearCookie : function(name){
            document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
               ((this.path == null) ? "" : ("; path=" + this.path)) +
               ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
               ((this.secure == true) ? "; secure" : "");
        }
    });

    Ext.DataView = Ext.extend(Ext.BoxComponent, {

        selectedClass : "x-view-selected",

        emptyText : "",

        last: false,

        initComponent : function(){
            Ext.DataView.superclass.initComponent.call(this);
            if(typeof this.tpl == "string"){
                this.tpl = new Ext.XTemplate(this.tpl);
            }

            this.addEvents(

                "beforeclick",

                "click",

                "containerclick",

                "dblclick",

                "contextmenu",

                "selectionchange",

                "beforeselect"
            );

            this.all = new Ext.CompositeElementLite();
            this.selected = new Ext.CompositeElementLite();
        },

        onRender : function(){
            if(!this.el){
                this.el = document.createElement('div');
            }
            Ext.DataView.superclass.onRender.apply(this, arguments);
        },

        afterRender : function(){
            Ext.DataView.superclass.afterRender.call(this);

            this.el.on({
                "click": this.onClick,
                "dblclick": this.onDblClick,
                "contextmenu": this.onContextMenu,
                scope:this
            });

            if(this.overClass){
                this.el.on({
                    "mouseover": this.onMouseOver,
                    "mouseout": this.onMouseOut,
                    scope:this
                });
            }

            if(this.store){
                this.setStore(this.store, true);
            }
        },

        refresh : function(){
            this.clearSelections(false, true);
            this.el.update("");
            var html = [];
            var records = this.store.getRange();
            if(records.length < 1){
                this.el.update(this.emptyText);
                this.all.clear();
                return;
            }
            this.tpl.overwrite(this.el, this.collectData(records, 0));
            this.all.fill(Ext.query(this.itemSelector, this.el.dom));
            this.updateIndexes(0);
        },

        prepareData : function(data){
            return data;
        },

        collectData : function(records, startIndex){
            var r = [];
            for(var i = 0, len = records.length; i < len; i++){
                r[r.length] = this.prepareData(records[i].data, startIndex+i, records[i]);
            }
            return r;
        },

        bufferRender : function(records){
            var div = document.createElement('div');
            this.tpl.overwrite(div, this.collectData(records));
            return Ext.query(this.itemSelector, div);
        },

        onUpdate : function(ds, record){
            var index = this.store.indexOf(record);
            var sel = this.isSelected(index);
            var original = this.all.elements[index];
            var node = this.bufferRender([record], index)[0];

            this.all.replaceElement(index, node, true);
            if(sel){
                this.selected.replaceElement(original, node);
                this.all.item(index).addClass(this.selectedClass);
            }
            this.updateIndexes(index, index);
        },

        onAdd : function(ds, records, index){
            if(this.all.getCount() == 0){
                this.refresh();
                return;
            }
            var nodes = this.bufferRender(records, index), n;
            if(index < this.all.getCount()){
                n = this.all.item(index).insertSibling(nodes, 'before', true);
                this.all.elements.splice(index, 0, n);
            }else{
                n = this.all.last().insertSibling(nodes, 'after', true);
                this.all.elements.push(n);
            }
            this.updateIndexes(index);
        },

        onRemove : function(ds, record, index){
            this.deselect(index);
            this.all.removeElement(index, true);
            this.updateIndexes(index);
        },

        refreshNode : function(index){
            this.onUpdate(this.store, this.store.getAt(index));
        },

        updateIndexes : function(startIndex, endIndex){
            var ns = this.all.elements;
            startIndex = startIndex || 0;
            endIndex = endIndex || ((endIndex === 0) ? 0 : (ns.length - 1));
            for(var i = startIndex; i <= endIndex; i++){
                ns[i].viewIndex = i;
            }
        },

        setStore : function(store, initial){
            if(!initial && this.store){
                this.store.un("beforeload", this.onBeforeLoad, this);
                this.store.un("datachanged", this.refresh, this);
                this.store.un("add", this.onAdd, this);
                this.store.un("remove", this.onRemove, this);
                this.store.un("update", this.onUpdate, this);
                this.store.un("clear", this.refresh, this);
            }
            if(store){
                store = Ext.StoreMgr.lookup(store);
                store.on("beforeload", this.onBeforeLoad, this);
                store.on("datachanged", this.refresh, this);
                store.on("add", this.onAdd, this);
                store.on("remove", this.onRemove, this);
                store.on("update", this.onUpdate, this);
                store.on("clear", this.refresh, this);
            }
            this.store = store;
            if(store){
                this.refresh();
            }
        },

        findItemFromChild : function(node){
            return Ext.fly(node).findParent(this.itemSelector, this.el);
        },

        onClick : function(e){
            var item = e.getTarget(this.itemSelector, this.el);
            if(item){
                var index = this.indexOf(item);
                if(this.onItemClick(item, index, e) !== false){
                    this.fireEvent("click", this, index, item, e);
                }
            }else{
                if(this.fireEvent("containerclick", this, e) !== false){
                    this.clearSelections();
                }
            }
        },

        onContextMenu : function(e){
            var item = e.getTarget(this.itemSelector, this.el);
            if(item){
                this.fireEvent("contextmenu", this, this.indexOf(item), item, e);
            }
        },

        onDblClick : function(e){
            var item = e.getTarget(this.itemSelector, this.el);
            if(item){
                this.fireEvent("dblclick", this, this.indexOf(item), item, e);
            }
        },

        onMouseOver : function(e){
            var item = e.getTarget(this.itemSelector, this.el);
            if(item && item !== this.lastItem){
                this.lastItem = item;
                Ext.fly(item).addClass(this.overClass);
            }
        },

        onMouseOut : function(e){
            if(this.lastItem){
                if(!e.within(this.lastItem, true)){
                    Ext.fly(this.lastItem).removeClass(this.overClass);
                    delete this.lastItem;
                }
            }
        },

        onItemClick : function(item, index, e){
            if(this.fireEvent("beforeclick", this, index, item, e) === false){
                return false;
            }
            if(this.multiSelect){
                this.doMultiSelection(item, index, e);
                e.preventDefault();
            }else if(this.singleSelect){
                this.doSingleSelection(item, index, e);
                e.preventDefault();
            }
            return true;
        },

        doSingleSelection : function(item, index, e){
            if(e.ctrlKey && this.isSelected(index)){
                this.deselect(index);
            }else{
                this.select(index, false);
            }
        },

        doMultiSelection : function(item, index, e){
            if(e.shiftKey && this.last !== false){
                var last = this.last;
                this.selectRange(last, index, e.ctrlKey);
                this.last = last;
            }else{
                if((e.ctrlKey||this.simpleSelect) && this.isSelected(index)){
                    this.deselect(index);
                }else{
                    this.select(index, e.ctrlKey || e.shiftKey || this.simpleSelect);
                }
            }
        },

        getSelectionCount : function(){
            return this.selected.getCount()
        },

        getSelectedNodes : function(){
            return this.selected.elements;
        },

        getSelectedIndexes : function(){
            var indexes = [], s = this.selected.elements;
            for(var i = 0, len = s.length; i < len; i++){
                indexes.push(s[i].viewIndex);
            }
            return indexes;
        },

        getSelectedRecords : function(){
            var r = [], s = this.selected.elements;
            for(var i = 0, len = s.length; i < len; i++){
                r[r.length] = this.store.getAt(s[i].viewIndex);
            }
            return r;
        },

        getRecords : function(nodes){
            var r = [], s = nodes;
            for(var i = 0, len = s.length; i < len; i++){
                r[r.length] = this.store.getAt(s[i].viewIndex);
            }
            return r;
        },

        getRecord : function(node){
            return this.store.getAt(node.viewIndex);
        },

        clearSelections : function(suppressEvent, skipUpdate){
            if(this.multiSelect || this.singleSelect){
                if(!skipUpdate){
                    this.selected.removeClass(this.selectedClass);
                }
                this.selected.clear();
                this.last = false;
                if(!suppressEvent){
                    this.fireEvent("selectionchange", this, this.selected.elements);
                }
            }
        },

        isSelected : function(node){
            return this.selected.contains(this.getNode(node));
        },

        deselect : function(node){
            if(this.isSelected(node)){
                var node = this.getNode(node);
                this.selected.removeElement(node);
                if(this.last == node.viewIndex){
                    this.last = false;
                }
                Ext.fly(node).removeClass(this.selectedClass);
                this.fireEvent("selectionchange", this, this.selected.elements);
            }
        },

        select : function(nodeInfo, keepExisting, suppressEvent){
            if(Ext.isArray(nodeInfo)){
                if(!keepExisting){
                    this.clearSelections(true);
                }
                for(var i = 0, len = nodeInfo.length; i < len; i++){
                    this.select(nodeInfo[i], true, true);
                }
            } else{
                var node = this.getNode(nodeInfo);
                if(!keepExisting){
                    this.clearSelections(true);
                }
                if(node && !this.isSelected(node)){
                    if(this.fireEvent("beforeselect", this, node, this.selected.elements) !== false){
                        Ext.fly(node).addClass(this.selectedClass);
                        this.selected.add(node);
                        this.last = node.viewIndex;
                        if(!suppressEvent){
                            this.fireEvent("selectionchange", this, this.selected.elements);
                        }
                    }
                }
            }
        },

        selectRange : function(start, end, keepExisting){
            if(!keepExisting){
                this.clearSelections(true);
            }
            this.select(this.getNodes(start, end), true);
        },

        getNode : function(nodeInfo){
            if(typeof nodeInfo == "string"){
                return document.getElementById(nodeInfo);
            }else if(typeof nodeInfo == "number"){
                return this.all.elements[nodeInfo];
            }
            return nodeInfo;
        },

        getNodes : function(start, end){
            var ns = this.all.elements;
            start = start || 0;
            end = typeof end == "undefined" ? ns.length - 1 : end;
            var nodes = [], i;
            if(start <= end){
                for(i = start; i <= end; i++){
                    nodes.push(ns[i]);
                }
            } else{
                for(i = start; i >= end; i--){
                    nodes.push(ns[i]);
                }
            }
            return nodes;
        },

        indexOf : function(node){
            node = this.getNode(node);
            if(typeof node.viewIndex == "number"){
                return node.viewIndex;
            }
            return this.all.indexOf(node);
        },

        onBeforeLoad : function(){
            if(this.loadingText){
                this.clearSelections(false, true);
                this.el.update(''+this.loadingText+'');
                this.all.clear();
            }
        }
    });

    Ext.reg('dataview', Ext.DataView);

    Ext.ColorPalette = function(config){
        Ext.ColorPalette.superclass.constructor.call(this, config);
        this.addEvents(

            'select'
        );

        if(this.handler){
            this.on("select", this.handler, this.scope, true);
        }
    };
    Ext.extend(Ext.ColorPalette, Ext.Component, {

        itemCls : "x-color-palette",

        value : null,
        clickEvent:'click',
            ctype: "Ext.ColorPalette",

        allowReselect : false,

        colors : [
            "000000", "993300", "333300", "003300", "003366", "000080", "333399", "333333",
            "800000", "FF6600", "808000", "008000", "008080", "0000FF", "666699", "808080",
            "FF0000", "FF9900", "99CC00", "339966", "33CCCC", "3366FF", "800080", "969696",
            "FF00FF", "FFCC00", "FFFF00", "00FF00", "00FFFF", "00CCFF", "993366", "C0C0C0",
            "FF99CC", "FFCC99", "FFFF99", "CCFFCC", "CCFFFF", "99CCFF", "CC99FF", "FFFFFF"
        ],

            onRender : function(container, position){
            var t = this.tpl || new Ext.XTemplate(
                ' '
            );
            var el = document.createElement("div");
            el.className = this.itemCls;
            t.overwrite(el, this.colors);
            container.dom.insertBefore(el, position);
            this.el = Ext.get(el);
            this.el.on(this.clickEvent, this.handleClick,  this, {delegate: "a"});
            if(this.clickEvent != 'click'){
                this.el.on('click', Ext.emptyFn,  this, {delegate: "a", preventDefault:true});
            }
        },

            afterRender : function(){
            Ext.ColorPalette.superclass.afterRender.call(this);
            if(this.value){
                var s = this.value;
                this.value = null;
                this.select(s);
            }
        },

            handleClick : function(e, t){
            e.preventDefault();
            if(!this.disabled){
                var c = t.className.match(/(?:^|\s)color-(.{6})(?:\s|$)/)[1];
                this.select(c.toUpperCase());
            }
        },

        select : function(color){
            color = color.replace("#", "");
            if(color != this.value || this.allowReselect){
                var el = this.el;
                if(this.value){
                    el.child("a.color-"+this.value).removeClass("x-color-palette-sel");
                }
                el.child("a.color-"+color).addClass("x-color-palette-sel");
                this.value = color;
                this.fireEvent("select", this, color);
            }
        }

    });
    Ext.reg('colorpalette', Ext.ColorPalette);

    Ext.DatePicker = Ext.extend(Ext.Component, {

        todayText : "Today",

        okText : " OK ",

        cancelText : "Cancel",

        todayTip : "{0} (Spacebar)",

        minDate : null,

        maxDate : null,

        minText : "This date is before the minimum date",

        maxText : "This date is after the maximum date",

        format : "m/d/y",

        disabledDays : null,

        disabledDaysText : "",

        disabledDatesRE : null,

        disabledDatesText : "",

        constrainToViewport : true,

        monthNames : Date.monthNames,

        dayNames : Date.dayNames,

        nextText: 'Next Month (Control+Right)',

        prevText: 'Previous Month (Control+Left)',

        monthYearText: 'Choose a month (Control+Up/Down to move years)',

        startDay : 0,

        initComponent : function(){
            Ext.DatePicker.superclass.initComponent.call(this);

            this.value = this.value ?
                     this.value.clearTime() : new Date().clearTime();

            this.addEvents(

                'select'
            );

            if(this.handler){
                this.on("select", this.handler,  this.scope || this);
            }

            this.initDisabledDays();
        },

        initDisabledDays : function(){
            if(!this.disabledDatesRE && this.disabledDates){
                var dd = this.disabledDates;
                var re = "(?:";
                for(var i = 0; i < dd.length; i++){
                    re += dd[i];
                    if(i != dd.length-1) re += "|";
                }
                this.disabledDatesRE = new RegExp(re + ")");
            }
        },

        setValue : function(value){
            var old = this.value;
            this.value = value.clearTime(true);
            if(this.el){
                this.update(this.value);
            }
        },

        getValue : function(){
            return this.value;
        },

        focus : function(){
            if(this.el){
                this.update(this.activeDate);
            }
        },

        onRender : function(container, position){
            var m = [
                 '',
                    '  ',
                    ''];
            var dn = this.dayNames;
            for(var i = 0; i < 7; i++){
                var d = this.startDay+i;
                if(d > 6){
                    d = d-7;
                }
                m.push("", dn[d].substr(0,1), "");
            }
            m[m.length] = "";
            for(var i = 0; i < 42; i++) {
                if(i % 7 == 0 && i != 0){
                    m[m.length] = "";
                }
                m[m.length] = '';
            }
            m[m.length] = '';

            var el = document.createElement("div");
            el.className = "x-date-picker";
            el.innerHTML = m.join("");

            container.dom.insertBefore(el, position);

            this.el = Ext.get(el);
            this.eventEl = Ext.get(el.firstChild);

            new Ext.util.ClickRepeater(this.el.child("td.x-date-left a"), {
                handler: this.showPrevMonth,
                scope: this,
                preventDefault:true,
                stopDefault:true
            });

            new Ext.util.ClickRepeater(this.el.child("td.x-date-right a"), {
                handler: this.showNextMonth,
                scope: this,
                preventDefault:true,
                stopDefault:true
            });

            this.eventEl.on("mousewheel", this.handleMouseWheel,  this);

            this.monthPicker = this.el.down('div.x-date-mp');
            this.monthPicker.enableDisplayMode('block');

            var kn = new Ext.KeyNav(this.eventEl, {
                "left" : function(e){
                    e.ctrlKey ?
                        this.showPrevMonth() :
                        this.update(this.activeDate.add("d", -1));
                },

                "right" : function(e){
                    e.ctrlKey ?
                        this.showNextMonth() :
                        this.update(this.activeDate.add("d", 1));
                },

                "up" : function(e){
                    e.ctrlKey ?
                        this.showNextYear() :
                        this.update(this.activeDate.add("d", -7));
                },

                "down" : function(e){
                    e.ctrlKey ?
                        this.showPrevYear() :
                        this.update(this.activeDate.add("d", 7));
                },

                "pageUp" : function(e){
                    this.showNextMonth();
                },

                "pageDown" : function(e){
                    this.showPrevMonth();
                },

                "enter" : function(e){
                    e.stopPropagation();
                    return true;
                },

                scope : this
            });

            this.eventEl.on("click", this.handleDateClick,  this, {delegate: "a.x-date-date"});

            this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday,  this);

            this.el.unselectable();

            this.cells = this.el.select("table.x-date-inner tbody td");
            this.textNodes = this.el.query("table.x-date-inner tbody span");

            this.mbtn = new Ext.Button({
                text: " ",
                tooltip: this.monthYearText,
                renderTo: this.el.child("td.x-date-middle", true)
            });

            this.mbtn.on('click', this.showMonthPicker, this);
            this.mbtn.el.child(this.mbtn.menuClassTarget).addClass("x-btn-with-menu");

            var today = (new Date()).dateFormat(this.format);
            this.todayBtn = new Ext.Button({
                renderTo: this.el.child("td.x-date-bottom", true),
                text: String.format(this.todayText, today),
                tooltip: String.format(this.todayTip, today),
                handler: this.selectToday,
                scope: this
            });

            if(Ext.isIE){
                this.el.repaint();
            }
            this.update(this.value);
        },

        createMonthPicker : function(){
            if(!this.monthPicker.dom.firstChild){
                var buf = [''];
                for(var i = 0; i < 6; i++){
                    buf.push(
                        '', this.monthNames[i].substr(0, 3), '',
                        '', this.monthNames[i+6].substr(0, 3), '',
                        i == 0 ?
                        '' :
                        ''
                    );
                }
                buf.push(
                    '',
                    ''
                );
                this.monthPicker.update(buf.join(''));
                this.monthPicker.on('click', this.onMonthClick, this);
                this.monthPicker.on('dblclick', this.onMonthDblClick, this);

                this.mpMonths = this.monthPicker.select('td.x-date-mp-month');
                this.mpYears = this.monthPicker.select('td.x-date-mp-year');

                this.mpMonths.each(function(m, a, i){
                    i += 1;
                    if((i%2) == 0){
                        m.dom.xmonth = 5 + Math.round(i * .5);
                    }else{
                        m.dom.xmonth = Math.round((i-1) * .5);
                    }
                });
            }
        },

        showMonthPicker : function(){
            this.createMonthPicker();
            var size = this.el.getSize();
            this.monthPicker.setSize(size);
            this.monthPicker.child('table').setSize(size);

            this.mpSelMonth = (this.activeDate || this.value).getMonth();
            this.updateMPMonth(this.mpSelMonth);
            this.mpSelYear = (this.activeDate || this.value).getFullYear();
            this.updateMPYear(this.mpSelYear);

            this.monthPicker.slideIn('t', {duration:.2});
        },

        updateMPYear : function(y){
            this.mpyear = y;
            var ys = this.mpYears.elements;
            for(var i = 1; i <= 10; i++){
                var td = ys[i-1], y2;
                if((i%2) == 0){
                    y2 = y + Math.round(i * .5);
                    td.firstChild.innerHTML = y2;
                    td.xyear = y2;
                }else{
                    y2 = y - (5-Math.round(i * .5));
                    td.firstChild.innerHTML = y2;
                    td.xyear = y2;
                }
                this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');
            }
        },

        updateMPMonth : function(sm){
            this.mpMonths.each(function(m, a, i){
                m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');
            });
        },

        selectMPMonth: function(m){

        },

        onMonthClick : function(e, t){
            e.stopEvent();
            var el = new Ext.Element(t), pn;
            if(el.is('button.x-date-mp-cancel')){
                this.hideMonthPicker();
            }
            else if(el.is('button.x-date-mp-ok')){
                this.update(new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
                this.hideMonthPicker();
            }
            else if(pn = el.up('td.x-date-mp-month', 2)){
                this.mpMonths.removeClass('x-date-mp-sel');
                pn.addClass('x-date-mp-sel');
                this.mpSelMonth = pn.dom.xmonth;
            }
            else if(pn = el.up('td.x-date-mp-year', 2)){
                this.mpYears.removeClass('x-date-mp-sel');
                pn.addClass('x-date-mp-sel');
                this.mpSelYear = pn.dom.xyear;
            }
            else if(el.is('a.x-date-mp-prev')){
                this.updateMPYear(this.mpyear-10);
            }
            else if(el.is('a.x-date-mp-next')){
                this.updateMPYear(this.mpyear+10);
            }
        },

        onMonthDblClick : function(e, t){
            e.stopEvent();
            var el = new Ext.Element(t), pn;
            if(pn = el.up('td.x-date-mp-month', 2)){
                this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));
                this.hideMonthPicker();
            }
            else if(pn = el.up('td.x-date-mp-year', 2)){
                this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
                this.hideMonthPicker();
            }
        },

        hideMonthPicker : function(disableAnim){
            if(this.monthPicker){
                if(disableAnim === true){
                    this.monthPicker.hide();
                }else{
                    this.monthPicker.slideOut('t', {duration:.2});
                }
            }
        },

        showPrevMonth : function(e){
            this.update(this.activeDate.add("mo", -1));
        },

        showNextMonth : function(e){
            this.update(this.activeDate.add("mo", 1));
        },

        showPrevYear : function(){
            this.update(this.activeDate.add("y", -1));
        },

        showNextYear : function(){
            this.update(this.activeDate.add("y", 1));
        },

        handleMouseWheel : function(e){
            var delta = e.getWheelDelta();
            if(delta > 0){
                this.showPrevMonth();
                e.stopEvent();
            } else if(delta < 0){
                this.showNextMonth();
                e.stopEvent();
            }
        },

        handleDateClick : function(e, t){
            e.stopEvent();
            if(t.dateValue && !Ext.fly(t.parentNode).hasClass("x-date-disabled")){
                this.setValue(new Date(t.dateValue));
                this.fireEvent("select", this, this.value);
            }
        },

        selectToday : function(){
            this.setValue(new Date().clearTime());
            this.fireEvent("select", this, this.value);
        },

        update : function(date){
            var vd = this.activeDate;
            this.activeDate = date;
            if(vd && this.el){
                var t = date.getTime();
                if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
                    this.cells.removeClass("x-date-selected");
                    this.cells.each(function(c){
                       if(c.dom.firstChild.dateValue == t){
                           c.addClass("x-date-selected");
                           setTimeout(function(){
                                try{c.dom.firstChild.focus();}catch(e){}
                           }, 50);
                           return false;
                       }
                    });
                    return;
                }
            }
            var days = date.getDaysInMonth();
            var firstOfMonth = date.getFirstDateOfMonth();
            var startingPos = firstOfMonth.getDay()-this.startDay;

            if(startingPos <= this.startDay){
                startingPos += 7;
            }

            var pm = date.add("mo", -1);
            var prevStart = pm.getDaysInMonth()-startingPos;

            var cells = this.cells.elements;
            var textEls = this.textNodes;
            days += startingPos;

            var day = 86400000;
            var d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart)).clearTime();
            var today = new Date().clearTime().getTime();
            var sel = date.clearTime().getTime();
            var min = this.minDate ? this.minDate.clearTime() : Number.NEGATIVE_INFINITY;
            var max = this.maxDate ? this.maxDate.clearTime() : Number.POSITIVE_INFINITY;
            var ddMatch = this.disabledDatesRE;
            var ddText = this.disabledDatesText;
            var ddays = this.disabledDays ? this.disabledDays.join("") : false;
            var ddaysText = this.disabledDaysText;
            var format = this.format;

            var setCellClass = function(cal, cell){
                cell.title = "";
                var t = d.getTime();
                cell.firstChild.dateValue = t;
                if(t == today){
                    cell.className += " x-date-today";
                    cell.title = cal.todayText;
                }
                if(t == sel){
                    cell.className += " x-date-selected";
                    setTimeout(function(){
                        try{cell.firstChild.focus();}catch(e){}
                    }, 50);
                }

                if(t < min) {
                    cell.className = " x-date-disabled";
                    cell.title = cal.minText;
                    return;
                }
                if(t > max) {
                    cell.className = " x-date-disabled";
                    cell.title = cal.maxText;
                    return;
                }
                if(ddays){
                    if(ddays.indexOf(d.getDay()) != -1){
                        cell.title = ddaysText;
                        cell.className = " x-date-disabled";
                    }
                }
                if(ddMatch && format){
                    var fvalue = d.dateFormat(format);
                    if(ddMatch.test(fvalue)){
                        cell.title = ddText.replace("%0", fvalue);
                        cell.className = " x-date-disabled";
                    }
                }
            };

            var i = 0;
            for(; i < startingPos; i++) {
                textEls[i].innerHTML = (++prevStart);
                d.setDate(d.getDate()+1);
                cells[i].className = "x-date-prevday";
                setCellClass(this, cells[i]);
            }
            for(; i < days; i++){
                intDay = i - startingPos + 1;
                textEls[i].innerHTML = (intDay);
                d.setDate(d.getDate()+1);
                cells[i].className = "x-date-active";
                setCellClass(this, cells[i]);
            }
            var extraDays = 0;
            for(; i < 42; i++) {
                 textEls[i].innerHTML = (++extraDays);
                 d.setDate(d.getDate()+1);
                 cells[i].className = "x-date-nextday";
                 setCellClass(this, cells[i]);
            }

            this.mbtn.setText(this.monthNames[date.getMonth()] + " " + date.getFullYear());

            if(!this.internalRender){
                var main = this.el.dom.firstChild;
                var w = main.offsetWidth;
                this.el.setWidth(w + this.el.getBorderWidth("lr"));
                Ext.fly(main).setWidth(w);
                this.internalRender = true;

                if(Ext.isOpera && !this.secondPass){
                    main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + "px";
                    this.secondPass = true;
                    this.update.defer(10, this, [date]);
                }
            }
        },

        beforeDestroy : function() {
            this.mbtn.destroy();
            this.todayBtn.destroy();
        }

    });
    Ext.reg('datepicker', Ext.DatePicker);

    Ext.TabPanel = Ext.extend(Ext.Panel,  {

        monitorResize : true,

        deferredRender : true,

        tabWidth: 120,

        minTabWidth: 30,

        resizeTabs:false,

        enableTabScroll: false,

        scrollIncrement : 0,

        scrollRepeatInterval : 400,

        scrollDuration : .35,

        animScroll : true,

        tabPosition: 'top',

        baseCls: 'x-tab-panel',

        autoTabs : false,

        autoTabSelector:'div.x-tab',

        activeTab : null,

        tabMargin : 2,

        plain: false,

        wheelIncrement : 20,

        idDelimiter : '__',

            itemCls : 'x-tab-item',

            elements: 'body',
        headerAsText: false,
        frame: false,
        hideBorders:true,

            initComponent : function(){
            this.frame = false;
            Ext.TabPanel.superclass.initComponent.call(this);
            this.addEvents(

                'beforetabchange',

                'tabchange',

                'contextmenu'
            );
            this.setLayout(new Ext.layout.CardLayout({
                deferredRender: this.deferredRender
            }));
            if(this.tabPosition == 'top'){
                this.elements += ',header';
                this.stripTarget = 'header';
            }else {
                this.elements += ',footer';
                this.stripTarget = 'footer';
            }
            if(!this.stack){
                this.stack = Ext.TabPanel.AccessStack();
            }
            this.initItems();
        },

            render : function(){
            Ext.TabPanel.superclass.render.apply(this, arguments);
            if(this.activeTab !== undefined){
                var item = this.activeTab;
                delete this.activeTab;
                this.setActiveTab(item);
            }
        },

            onRender : function(ct, position){
            Ext.TabPanel.superclass.onRender.call(this, ct, position);

            if(this.plain){
                var pos = this.tabPosition == 'top' ? 'header' : 'footer';
                this[pos].addClass('x-tab-panel-'+pos+'-plain');
            }

            var st = this[this.stripTarget];

            this.stripWrap = st.createChild({cls:'x-tab-strip-wrap', cn:{
                tag:'ul', cls:'x-tab-strip x-tab-strip-'+this.tabPosition}});
            this.stripSpacer = st.createChild({cls:'x-tab-strip-spacer'});
            this.strip = new Ext.Element(this.stripWrap.dom.firstChild);

            this.edge = this.strip.createChild({tag:'li', cls:'x-tab-edge'});
            this.strip.createChild({cls:'x-clear'});

            this.body.addClass('x-tab-panel-body-'+this.tabPosition);

            if(!this.itemTpl){
                var tt = new Ext.Template(
                     '',
                     '',
                     '{text}',
                     ''
                );
                tt.disableFormats = true;
                tt.compile();
                Ext.TabPanel.prototype.itemTpl = tt;
            }

            this.items.each(this.initTab, this);
        },

            afterRender : function(){
            Ext.TabPanel.superclass.afterRender.call(this);
            if(this.autoTabs){
                this.readTabs(false);
            }
        },

            initEvents : function(){
            Ext.TabPanel.superclass.initEvents.call(this);
            this.on('add', this.onAdd, this);
            this.on('remove', this.onRemove, this);

            this.strip.on('mousedown', this.onStripMouseDown, this);
            this.strip.on('click', this.onStripClick, this);
            this.strip.on('contextmenu', this.onStripContextMenu, this);
            if(this.enableTabScroll){
                this.strip.on('mousewheel', this.onWheel, this);
            }
        },

            findTargets : function(e){
            var item = null;
            var itemEl = e.getTarget('li', this.strip);
            if(itemEl){
                item = this.getComponent(itemEl.id.split(this.idDelimiter)[1]);
                if(item.disabled){
                    return {
                        close : null,
                        item : null,
                        el : null
                    };
                }
            }
            return {
                close : e.getTarget('.x-tab-strip-close', this.strip),
                item : item,
                el : itemEl
            };
        },

            onStripMouseDown : function(e){
            e.preventDefault();
            if(e.button != 0){
                return;
            }
            var t = this.findTargets(e);
            if(t.close){
                this.remove(t.item);
                return;
            }
            if(t.item && t.item != this.activeTab){
                this.setActiveTab(t.item);
            }
        },

            onStripClick : function(e){
            var t = this.findTargets(e);
            if(!t.close && t.item && t.item != this.activeTab){
                this.setActiveTab(t.item);
            }
        },

            onStripContextMenu : function(e){
            e.preventDefault();
            var t = this.findTargets(e);
            if(t.item){
                this.fireEvent('contextmenu', this, t.item, e);
            }
        },

        readTabs : function(removeExisting){
            if(removeExisting === true){
                this.items.each(function(item){
                    this.remove(item);
                }, this);
            }
            var tabs = this.el.query(this.autoTabSelector);
            for(var i = 0, len = tabs.length; i < len; i++){
                var tab = tabs[i];
                var title = tab.getAttribute('title');
                tab.removeAttribute('title');
                this.add({
                    title: title,
                    el: tab
                });
            }
        },

            initTab : function(item, index){
            var before = this.strip.dom.childNodes[index];
            var cls = item.closable ? 'x-tab-strip-closable' : '';
            if(item.disabled){
                cls += ' x-item-disabled';
            }
            if(item.iconCls){
                cls += ' x-tab-with-icon';
            }
            if(item.tabCls){
                cls += ' ' + item.tabCls;
            }

            var p = {
                id: this.id + this.idDelimiter + item.getItemId(),
                text: item.title,
                cls: cls,
                iconCls: item.iconCls || ''
            };
            var el = before ?
                     this.itemTpl.insertBefore(before, p) :
                     this.itemTpl.append(this.strip, p);

            Ext.fly(el).addClassOnOver('x-tab-strip-over');

            if(item.tabTip){
                Ext.fly(el).child('span.x-tab-strip-text', true).qtip = item.tabTip;
            }
            item.on('disable', this.onItemDisabled, this);
            item.on('enable', this.onItemEnabled, this);
            item.on('titlechange', this.onItemTitleChanged, this);
            item.on('beforeshow', this.onBeforeShowItem, this);
        },

            onAdd : function(tp, item, index){
            this.initTab(item, index);
            if(this.items.getCount() == 1){
                this.syncSize();
            }
            this.delegateUpdates();
        },

            onBeforeAdd : function(item){
            var existing = item.events ? (this.items.containsKey(item.getItemId()) ? item : null) : this.items.get(item);
            if(existing){
                this.setActiveTab(item);
                return false;
            }
            Ext.TabPanel.superclass.onBeforeAdd.apply(this, arguments);
            var es = item.elements;
            item.elements = es ? es.replace(',header', '') : es;
            item.border = (item.border === true);
        },

            onRemove : function(tp, item){
            Ext.removeNode(this.getTabEl(item));
            this.stack.remove(item);
            if(item == this.activeTab){
                var next = this.stack.next();
                if(next){
                    this.setActiveTab(next);
                }else{
                    this.setActiveTab(0);
                }
            }
            this.delegateUpdates();
        },

            onBeforeShowItem : function(item){
            if(item != this.activeTab){
                this.setActiveTab(item);
                return false;
            }
        },

            onItemDisabled : function(item){
            var el = this.getTabEl(item);
            if(el){
                Ext.fly(el).addClass('x-item-disabled');
            }
            this.stack.remove(item);
        },

            onItemEnabled : function(item){
            var el = this.getTabEl(item);
            if(el){
                Ext.fly(el).removeClass('x-item-disabled');
            }
        },

            onItemTitleChanged : function(item){
            var el = this.getTabEl(item);
            if(el){
                Ext.fly(el).child('span.x-tab-strip-text', true).innerHTML = item.title;
            }
        },

        getTabEl : function(item){
            var itemId = (typeof item === 'number')?this.items.items[item].getItemId() : item.getItemId();
            return document.getElementById(this.id+this.idDelimiter+itemId);
        },

            onResize : function(){
            Ext.TabPanel.superclass.onResize.apply(this, arguments);
            this.delegateUpdates();
        },

        beginUpdate : function(){
            this.suspendUpdates = true;
        },

        endUpdate : function(){
            this.suspendUpdates = false;
            this.delegateUpdates();
        },

        hideTabStripItem : function(item){
            item = this.getComponent(item);
            var el = this.getTabEl(item);
            if(el){
                el.style.display = 'none';
                this.delegateUpdates();
            }
        },

        unhideTabStripItem : function(item){
            item = this.getComponent(item);
            var el = this.getTabEl(item);
            if(el){
                el.style.display = '';
                this.delegateUpdates();
            }
        },

            delegateUpdates : function(){
            if(this.suspendUpdates){
                return;
            }
            if(this.resizeTabs && this.rendered){
                this.autoSizeTabs();
            }
            if(this.enableTabScroll && this.rendered){
                this.autoScrollTabs();
            }
        },

            autoSizeTabs : function(){
            var count = this.items.length;
            var ce = this.tabPosition != 'bottom' ? 'header' : 'footer';
            var ow = this[ce].dom.offsetWidth;
            var aw = this[ce].dom.clientWidth;

            if(!this.resizeTabs || count < 1 || !aw){             return;
            }

            var each = Math.max(Math.min(Math.floor((aw-4) / count) - this.tabMargin, this.tabWidth), this.minTabWidth);         this.lastTabWidth = each;
            var lis = this.stripWrap.dom.getElementsByTagName('li');
            for(var i = 0, len = lis.length-1; i < len; i++) {             var li = lis[i];
                var inner = li.childNodes[1].firstChild.firstChild;
                var tw = li.offsetWidth;
                var iw = inner.offsetWidth;
                inner.style.width = (each - (tw-iw)) + 'px';
            }
        },

            adjustBodyWidth : function(w){
            if(this.header){
                this.header.setWidth(w);
            }
            if(this.footer){
                this.footer.setWidth(w);
            }
            return w;
        },

        setActiveTab : function(item){
            item = this.getComponent(item);
            if(!item || this.fireEvent('beforetabchange', this, item, this.activeTab) === false){
                return;
            }
            if(!this.rendered){
                this.activeTab = item;
                return;
            }
            if(this.activeTab != item){
                if(this.activeTab){
                    var oldEl = this.getTabEl(this.activeTab);
                    if(oldEl){
                        Ext.fly(oldEl).removeClass('x-tab-strip-active');
                    }
                    this.activeTab.fireEvent('deactivate', this.activeTab);
                }
                var el = this.getTabEl(item);
                Ext.fly(el).addClass('x-tab-strip-active');
                this.activeTab = item;
                this.stack.add(item);

                this.layout.setActiveItem(item);
                if(this.layoutOnTabChange && item.doLayout){
                    item.doLayout();
                }
                if(this.scrolling){
                    this.scrollToTab(item, this.animScroll);
                }

                item.fireEvent('activate', item);
                this.fireEvent('tabchange', this, item);
            }
        },

        getActiveTab : function(){
            return this.activeTab || null;
        },

        getItem : function(item){
            return this.getComponent(item);
        },

            autoScrollTabs : function(){
            var count = this.items.length;
            var ow = this.header.dom.offsetWidth;
            var tw = this.header.dom.clientWidth;

            var wrap = this.stripWrap;
            var wd = wrap.dom;
            var cw = wd.offsetWidth;
            var pos = this.getScrollPos();
            var l = this.edge.getOffsetsTo(this.stripWrap)[0] + pos;

            if(!this.enableTabScroll || count < 1 || cw < 20){             return;
            }
            if(l <= tw){
                wd.scrollLeft = 0;
                wrap.setWidth(tw);
                if(this.scrolling){
                    this.scrolling = false;
                    this.header.removeClass('x-tab-scrolling');
                    this.scrollLeft.hide();
                    this.scrollRight.hide();
                    if(Ext.isAir){
                        wd.style.marginLeft = '';
                        wd.style.marginRight = '';
                    }
                }
            }else{
                if(!this.scrolling){
                    this.header.addClass('x-tab-scrolling');
                    if(Ext.isAir){
                        wd.style.marginLeft = '18px';
                        wd.style.marginRight = '18px';
                    }
                }
                tw -= wrap.getMargins('lr');
                wrap.setWidth(tw > 20 ? tw : 20);
                if(!this.scrolling){
                    if(!this.scrollLeft){
                        this.createScrollers();
                    }else{
                        this.scrollLeft.show();
                        this.scrollRight.show();
                    }
                }
                this.scrolling = true;
                if(pos > (l-tw)){                 wd.scrollLeft = l-tw;
                }else{                 this.scrollToTab(this.activeTab, false);
                }
                this.updateScrollButtons();
            }
        },

            createScrollers : function(){
            var h = this.stripWrap.dom.offsetHeight;

                    var sl = this.header.insertFirst({
                cls:'x-tab-scroller-left'
            });
            sl.setHeight(h);
            sl.addClassOnOver('x-tab-scroller-left-over');
            this.leftRepeater = new Ext.util.ClickRepeater(sl, {
                interval : this.scrollRepeatInterval,
                handler: this.onScrollLeft,
                scope: this
            });
            this.scrollLeft = sl;

                    var sr = this.header.insertFirst({
                cls:'x-tab-scroller-right'
            });
            sr.setHeight(h);
            sr.addClassOnOver('x-tab-scroller-right-over');
            this.rightRepeater = new Ext.util.ClickRepeater(sr, {
                interval : this.scrollRepeatInterval,
                handler: this.onScrollRight,
                scope: this
            });
            this.scrollRight = sr;
        },

            getScrollWidth : function(){
            return this.edge.getOffsetsTo(this.stripWrap)[0] + this.getScrollPos();
        },

            getScrollPos : function(){
            return parseInt(this.stripWrap.dom.scrollLeft, 10) || 0;
        },

            getScrollArea : function(){
            return parseInt(this.stripWrap.dom.clientWidth, 10) || 0;
        },

            getScrollAnim : function(){
            return {duration:this.scrollDuration, callback: this.updateScrollButtons, scope: this};
        },

            getScrollIncrement : function(){
            return this.scrollIncrement || (this.resizeTabs ? this.lastTabWidth+2 : 100);
        },

        scrollToTab : function(item, animate){
            if(!item){ return; }
            var el = this.getTabEl(item);
            var pos = this.getScrollPos(), area = this.getScrollArea();
            var left = Ext.fly(el).getOffsetsTo(this.stripWrap)[0] + pos;
            var right = left + el.offsetWidth;
            if(left < pos){
                this.scrollTo(left, animate);
            }else if(right > (pos + area)){
                this.scrollTo(right - area, animate);
            }
        },

            scrollTo : function(pos, animate){
            this.stripWrap.scrollTo('left', pos, animate ? this.getScrollAnim() : false);
            if(!animate){
                this.updateScrollButtons();
            }
        },

        onWheel : function(e){
            var d = e.getWheelDelta()*this.wheelIncrement*-1;
            e.stopEvent();

            var pos = this.getScrollPos();
            var newpos = pos + d;
            var sw = this.getScrollWidth()-this.getScrollArea();

            var s = Math.max(0, Math.min(sw, newpos));
            if(s != pos){
                this.scrollTo(s, false);
            }
        },

            onScrollRight : function(){
            var sw = this.getScrollWidth()-this.getScrollArea();
            var pos = this.getScrollPos();
            var s = Math.min(sw, pos + this.getScrollIncrement());
            if(s != pos){
                this.scrollTo(s, this.animScroll);
            }
        },

            onScrollLeft : function(){
            var pos = this.getScrollPos();
            var s = Math.max(0, pos - this.getScrollIncrement());
            if(s != pos){
                this.scrollTo(s, this.animScroll);
            }
        },

            updateScrollButtons : function(){
            var pos = this.getScrollPos();
            this.scrollLeft[pos == 0 ? 'addClass' : 'removeClass']('x-tab-scroller-left-disabled');
            this.scrollRight[pos >= (this.getScrollWidth()-this.getScrollArea()) ? 'addClass' : 'removeClass']('x-tab-scroller-right-disabled');
        }

    });
    Ext.reg('tabpanel', Ext.TabPanel);

    Ext.TabPanel.prototype.activate = Ext.TabPanel.prototype.setActiveTab;

    Ext.TabPanel.AccessStack = function(){
        var items = [];
        return {
            add : function(item){
                items.push(item);
                if(items.length > 10){
                    items.shift();
                }
            },

            remove : function(item){
                var s = [];
                for(var i = 0, len = items.length; i < len; i++) {
                    if(items[i] != item){
                        s.push(items[i]);
                    }
                }
                items = s;
            },

            next : function(){
                return items.pop();
            }
        };
    };

    Ext.Button = Ext.extend(Ext.Component, {

        hidden : false,

        disabled : false,

        pressed : false,

        enableToggle: false,

        menuAlign : "tl-bl?",

        type : 'button',

            menuClassTarget: 'tr',

        clickEvent : 'click',

        handleMouseEvents : true,

        tooltipType : 'qtip',

        buttonSelector : "button:first",

        initComponent : function(){
            Ext.Button.superclass.initComponent.call(this);

            this.addEvents(

                "click",

                "toggle",

                'mouseover',

                'mouseout',

                'menushow',

                'menuhide',

                'menutriggerover',

                'menutriggerout'
            );
            if(this.menu){
                this.menu = Ext.menu.MenuMgr.get(this.menu);
            }
            if(typeof this.toggleGroup === 'string'){
                this.enableToggle = true;
            }
        },

            onRender : function(ct, position){
            if(!this.template){
                if(!Ext.Button.buttonTemplate){
                                    Ext.Button.buttonTemplate = new Ext.Template(
                        '',
                        '  ',
                        "");
                }
                this.template = Ext.Button.buttonTemplate;
            }
            var btn, targs = [this.text || ' ', this.type];

            if(position){
                btn = this.template.insertBefore(position, targs, true);
            }else{
                btn = this.template.append(ct, targs, true);
            }
            var btnEl = btn.child(this.buttonSelector);
            btnEl.on('focus', this.onFocus, this);
            btnEl.on('blur', this.onBlur, this);

            this.initButtonEl(btn, btnEl);

            if(this.menu){
                this.el.child(this.menuClassTarget).addClass("x-btn-with-menu");
            }
            Ext.ButtonToggleMgr.register(this);
        },

            initButtonEl : function(btn, btnEl){

            this.el = btn;
            btn.addClass("x-btn");

            if(this.icon){
                btnEl.setStyle('background-image', 'url(' +this.icon +')');
            }
            if(this.iconCls){
                btnEl.addClass(this.iconCls);
                if(!this.cls){
                    btn.addClass(this.text ? 'x-btn-text-icon' : 'x-btn-icon');
                }
            }
            if(this.tabIndex !== undefined){
                btnEl.dom.tabIndex = this.tabIndex;
            }
            if(this.tooltip){
                if(typeof this.tooltip == 'object'){
                    Ext.QuickTips.register(Ext.apply({
                          target: btnEl.id
                    }, this.tooltip));
                } else {
                    btnEl.dom[this.tooltipType] = this.tooltip;
                }
            }

            if(this.pressed){
                this.el.addClass("x-btn-pressed");
            }

            if(this.handleMouseEvents){
                btn.on("mouseover", this.onMouseOver, this);
                                        btn.on("mousedown", this.onMouseDown, this);
            }

            if(this.menu){
                this.menu.on("show", this.onMenuShow, this);
                this.menu.on("hide", this.onMenuHide, this);
            }

            if(this.id){
                this.el.dom.id = this.el.id = this.id;
            }

            if(this.repeat){
                var repeater = new Ext.util.ClickRepeater(btn,
                    typeof this.repeat == "object" ? this.repeat : {}
                );
                repeater.on("click", this.onClick,  this);
            }

            btn.on(this.clickEvent, this.onClick, this);
        },

            afterRender : function(){
            Ext.Button.superclass.afterRender.call(this);
            if(Ext.isIE6){
                this.autoWidth.defer(1, this);
            }else{
                this.autoWidth();
            }
        },

        setIconClass : function(cls){
            if(this.el){
                this.el.child(this.buttonSelector).replaceClass(this.iconCls, cls);
            }
            this.iconCls = cls;
        },

            beforeDestroy: function(){
        	if(this.rendered){
    	        var btn = this.el.child(this.buttonSelector);
    	        if(btn){
    	            btn.removeAllListeners();
    	        }
    	    }
            if(this.menu){
                Ext.destroy(this.menu);
            }
        },

            onDestroy : function(){
            if(this.rendered){
                Ext.ButtonToggleMgr.unregister(this);
            }
        },

            autoWidth : function(){
            if(this.el){
                this.el.setWidth("auto");
                if(Ext.isIE7 && Ext.isStrict){
                    var ib = this.el.child(this.buttonSelector);
                    if(ib && ib.getWidth() > 20){
                        ib.clip();
                        ib.setWidth(Ext.util.TextMetrics.measure(ib, this.text).width+ib.getFrameWidth('lr'));
                    }
                }
                if(this.minWidth){
                    if(this.el.getWidth() < this.minWidth){
                        this.el.setWidth(this.minWidth);
                    }
                }
            }
        },

        setHandler : function(handler, scope){
            this.handler = handler;
            this.scope = scope;
        },

        setText : function(text){
            this.text = text;
            if(this.el){
                this.el.child("td.x-btn-center " + this.buttonSelector).update(text);
            }
            this.autoWidth();
        },

        getText : function(){
            return this.text;
        },

        toggle : function(state){
            state = state === undefined ? !this.pressed : state;
            if(state != this.pressed){
                if(state){
                    this.el.addClass("x-btn-pressed");
                    this.pressed = true;
                    this.fireEvent("toggle", this, true);
                }else{
                    this.el.removeClass("x-btn-pressed");
                    this.pressed = false;
                    this.fireEvent("toggle", this, false);
                }
                if(this.toggleHandler){
                    this.toggleHandler.call(this.scope || this, this, state);
                }
            }
        },

        focus : function(){
            this.el.child(this.buttonSelector).focus();
        },

            onDisable : function(){
            if(this.el){
                if(!Ext.isIE6 || !this.text){
                    this.el.addClass(this.disabledClass);
                }
                this.el.dom.disabled = true;
            }
            this.disabled = true;
        },

            onEnable : function(){
            if(this.el){
                if(!Ext.isIE6 || !this.text){
                    this.el.removeClass(this.disabledClass);
                }
                this.el.dom.disabled = false;
            }
            this.disabled = false;
        },

        showMenu : function(){
            if(this.menu){
                this.menu.show(this.el, this.menuAlign);
            }
            return this;
        },

        hideMenu : function(){
            if(this.menu){
                this.menu.hide();
            }
            return this;
        },

        hasVisibleMenu : function(){
            return this.menu && this.menu.isVisible();
        },

            onClick : function(e){
            if(e){
                e.preventDefault();
            }
            if(e.button != 0){
                return;
            }
            if(!this.disabled){
                if(this.enableToggle && (this.allowDepress !== false || !this.pressed)){
                    this.toggle();
                }
                if(this.menu && !this.menu.isVisible() && !this.ignoreNextClick){
                    this.showMenu();
                }
                this.fireEvent("click", this, e);
                if(this.handler){
                                    this.handler.call(this.scope || this, this, e);
                }
            }
        },

            isMenuTriggerOver : function(e, internal){
            return this.menu && !internal;
        },

            isMenuTriggerOut : function(e, internal){
            return this.menu && !internal;
        },

            onMouseOver : function(e){
            if(!this.disabled){
                var internal = e.within(this.el,  true);
                if(!internal){
                    this.el.addClass("x-btn-over");
                    Ext.getDoc().on('mouseover', this.monitorMouseOver, this);
                    this.fireEvent('mouseover', this, e);
                }
                if(this.isMenuTriggerOver(e, internal)){
                    this.fireEvent('menutriggerover', this, this.menu, e);
                }
            }
        },

            monitorMouseOver : function(e){
            if(e.target != this.el.dom && !e.within(this.el)){
                Ext.getDoc().un('mouseover', this.monitorMouseOver, this);
                this.onMouseOut(e);
            }
        },

            onMouseOut : function(e){
            var internal = e.within(this.el) && e.target != this.el.dom;
            this.el.removeClass("x-btn-over");
            this.fireEvent('mouseout', this, e);
            if(this.isMenuTriggerOut(e, internal)){
                this.fireEvent('menutriggerout', this, this.menu, e);
            }
        },
            onFocus : function(e){
            if(!this.disabled){
                this.el.addClass("x-btn-focus");
            }
        },
            onBlur : function(e){
            this.el.removeClass("x-btn-focus");
        },

            getClickEl : function(e, isUp){
           return this.el;
        },

            onMouseDown : function(e){
            if(!this.disabled && e.button == 0){
                this.getClickEl(e).addClass("x-btn-click");
                Ext.getDoc().on('mouseup', this.onMouseUp, this);
            }
        },
            onMouseUp : function(e){
            if(e.button == 0){
                this.getClickEl(e, true).removeClass("x-btn-click");
                Ext.getDoc().un('mouseup', this.onMouseUp, this);
            }
        },
            onMenuShow : function(e){
            this.ignoreNextClick = 0;
            this.el.addClass("x-btn-menu-active");
            this.fireEvent('menushow', this, this.menu);
        },
            onMenuHide : function(e){
            this.el.removeClass("x-btn-menu-active");
            this.ignoreNextClick = this.restoreClick.defer(250, this);
            this.fireEvent('menuhide', this, this.menu);
        },

            restoreClick : function(){
            this.ignoreNextClick = 0;
        }

    });
    Ext.reg('button', Ext.Button);

    Ext.ButtonToggleMgr = function(){
       var groups = {};

       function toggleGroup(btn, state){
           if(state){
               var g = groups[btn.toggleGroup];
               for(var i = 0, l = g.length; i < l; i++){
                   if(g[i] != btn){
                       g[i].toggle(false);
                   }
               }
           }
       }

       return {
           register : function(btn){
               if(!btn.toggleGroup){
                   return;
               }
               var g = groups[btn.toggleGroup];
               if(!g){
                   g = groups[btn.toggleGroup] = [];
               }
               g.push(btn);
               btn.on("toggle", toggleGroup);
           },

           unregister : function(btn){
               if(!btn.toggleGroup){
                   return;
               }
               var g = groups[btn.toggleGroup];
               if(g){
                   g.remove(btn);
                   btn.un("toggle", toggleGroup);
               }
           }
       };
    }();

    Ext.SplitButton = Ext.extend(Ext.Button, {

        arrowSelector : 'button:last',

        initComponent : function(){
            Ext.SplitButton.superclass.initComponent.call(this);

            this.addEvents("arrowclick");
        },

        onRender : function(ct, position){

            var tpl = new Ext.Template(
                '',
                '',
                ' ',
                "",
                '',
                ' ',
                ""
            );
            var btn, targs = [this.text || ' ', this.type];
            if(position){
                btn = tpl.insertBefore(position, targs, true);
            }else{
                btn = tpl.append(ct, targs, true);
            }
            var btnEl = btn.child(this.buttonSelector);

            this.initButtonEl(btn, btnEl);
            this.arrowBtnTable = btn.child("table:last");
            if(this.arrowTooltip){
                btn.child(this.arrowSelector).dom[this.tooltipType] = this.arrowTooltip;
            }
        },

        autoWidth : function(){
            if(this.el){
                var tbl = this.el.child("table:first");
                var tbl2 = this.el.child("table:last");
                this.el.setWidth("auto");
                tbl.setWidth("auto");
                if(Ext.isIE7 && Ext.isStrict){
                    var ib = this.el.child(this.buttonSelector);
                    if(ib && ib.getWidth() > 20){
                        ib.clip();
                        ib.setWidth(Ext.util.TextMetrics.measure(ib, this.text).width+ib.getFrameWidth('lr'));
                    }
                }
                if(this.minWidth){
                    if((tbl.getWidth()+tbl2.getWidth()) < this.minWidth){
                        tbl.setWidth(this.minWidth-tbl2.getWidth());
                    }
                }
                this.el.setWidth(tbl.getWidth()+tbl2.getWidth());
            }
        },

        setArrowHandler : function(handler, scope){
            this.arrowHandler = handler;
            this.scope = scope;
        },

        onClick : function(e){
            e.preventDefault();
            if(!this.disabled){
                if(e.getTarget(".x-btn-menu-arrow-wrap")){
                    if(this.menu && !this.menu.isVisible() && !this.ignoreNextClick){
                        this.showMenu();
                    }
                    this.fireEvent("arrowclick", this, e);
                    if(this.arrowHandler){
                        this.arrowHandler.call(this.scope || this, this, e);
                    }
                }else{
                    if(this.enableToggle){
                        this.toggle();
                    }
                    this.fireEvent("click", this, e);
                    if(this.handler){
                        this.handler.call(this.scope || this, this, e);
                    }
                }
            }
        },

        getClickEl : function(e, isUp){
            if(!isUp){
                return (this.lastClickEl = e.getTarget("table", 10, true));
            }
            return this.lastClickEl;
        },

        onDisable : function(){
            if(this.el){
                if(!Ext.isIE6){
                    this.el.addClass("x-item-disabled");
                }
                this.el.child(this.buttonSelector).dom.disabled = true;
                this.el.child(this.arrowSelector).dom.disabled = true;
            }
            this.disabled = true;
        },

        onEnable : function(){
            if(this.el){
                if(!Ext.isIE6){
                    this.el.removeClass("x-item-disabled");
                }
                this.el.child(this.buttonSelector).dom.disabled = false;
                this.el.child(this.arrowSelector).dom.disabled = false;
            }
            this.disabled = false;
        },

        isMenuTriggerOver : function(e){
            return this.menu && e.within(this.arrowBtnTable) && !e.within(this.arrowBtnTable, true);
        },

        isMenuTriggerOut : function(e, internal){
            return this.menu && !e.within(this.arrowBtnTable);
        },

        onDestroy : function(){
            Ext.destroy(this.arrowBtnTable);
            Ext.SplitButton.superclass.onDestroy.call(this);
        }
    });

    Ext.MenuButton = Ext.SplitButton;

    Ext.reg('splitbutton', Ext.SplitButton);

    Ext.CycleButton = Ext.extend(Ext.SplitButton, {

        getItemText : function(item){
            if(item && this.showText === true){
                var text = '';
                if(this.prependText){
                    text += this.prependText;
                }
                text += item.text;
                return text;
            }
            return undefined;
        },

        setActiveItem : function(item, suppressEvent){
            if(typeof item != 'object'){
                item = this.menu.items.get(item);
            }
            if(item){
                if(!this.rendered){
                    this.text = this.getItemText(item);
                    this.iconCls = item.iconCls;
                }else{
                    var t = this.getItemText(item);
                    if(t){
                        this.setText(t);
                    }
                    this.setIconClass(item.iconCls);
                }
                this.activeItem = item;
                if(!item.checked){
                    item.setChecked(true, true);
                }
                if(this.forceIcon){
                    this.setIconClass(this.forceIcon);
                }
                if(!suppressEvent){
                    this.fireEvent('change', this, item);
                }
            }
        },

        getActiveItem : function(){
            return this.activeItem;
        },

        initComponent : function(){
            this.addEvents(

                "change"
            );

            if(this.changeHandler){
                this.on('change', this.changeHandler, this.scope||this);
                delete this.changeHandler;
            }

            this.itemCount = this.items.length;

            this.menu = {cls:'x-cycle-menu', items:[]};
            var checked;
            for(var i = 0, len = this.itemCount; i < len; i++){
                var item = this.items[i];
                item.group = item.group || this.id;
                item.itemIndex = i;
                item.checkHandler = this.checkHandler;
                item.scope = this;
                item.checked = item.checked || false;
                this.menu.items.push(item);
                if(item.checked){
                    checked = item;
                }
            }
            this.setActiveItem(checked, true);
            Ext.CycleButton.superclass.initComponent.call(this);

            this.on('click', this.toggleSelected, this);
        },

        checkHandler : function(item, pressed){
            if(pressed){
                this.setActiveItem(item);
            }
        },

        toggleSelected : function(){
            this.menu.render();

    		var nextIdx, checkItem;
    		for (var i = 1; i < this.itemCount; i++) {
    			nextIdx = (this.activeItem.itemIndex + i) % this.itemCount;

    			checkItem = this.menu.items.itemAt(nextIdx);

    			if (!checkItem.disabled) {
    				checkItem.setChecked(true);
    				break;
    			}
    		}
        }
    });
    Ext.reg('cycle', Ext.CycleButton);

     Ext.Toolbar = function(config){
        if(Ext.isArray(config)){
            config = {buttons:config};
        }
        Ext.Toolbar.superclass.constructor.call(this, config);
    };

    (function(){

    var T = Ext.Toolbar;

    Ext.extend(T, Ext.BoxComponent, {

        trackMenus : true,

        initComponent : function(){
            T.superclass.initComponent.call(this);

            if(this.items){
                this.buttons = this.items;
            }

            this.items = new Ext.util.MixedCollection(false, function(o){
                return o.itemId || o.id || Ext.id();
            });
        },

        autoCreate: {
            cls:'x-toolbar x-small-editor',
            html:''
        },

        onRender : function(ct, position){
            this.el = ct.createChild(Ext.apply({ id: this.id },this.autoCreate), position);
            this.tr = this.el.child("tr", true);
        },

        afterRender : function(){
            T.superclass.afterRender.call(this);
            if(this.buttons){
                this.add.apply(this, this.buttons);
                delete this.buttons;
            }
        },

        add : function(){
            var a = arguments, l = a.length;
            for(var i = 0; i < l; i++){
                var el = a[i];
                if(el.isFormField){
                    this.addField(el);
                }else if(el.render){
                    this.addItem(el);
                }else if(typeof el == "string"){
                    if(el == "separator" || el == "-"){
                        this.addSeparator();
                    }else if(el == " "){
                        this.addSpacer();
                    }else if(el == "->"){
                        this.addFill();
                    }else{
                        this.addText(el);
                    }
                }else if(el.tagName){
                    this.addElement(el);
                }else if(typeof el == "object"){
                    if(el.xtype){
                        this.addField(Ext.ComponentMgr.create(el, 'button'));
                    }else{
                        this.addButton(el);
                    }
                }
            }
        },

        addSeparator : function(){
            return this.addItem(new T.Separator());
        },

        addSpacer : function(){
            return this.addItem(new T.Spacer());
        },

        addFill : function(){
            return this.addItem(new T.Fill());
        },

        addElement : function(el){
            return this.addItem(new T.Item(el));
        },

        addItem : function(item){
            var td = this.nextBlock();
            this.initMenuTracking(item);
            item.render(td);
            this.items.add(item);
            return item;
        },

        addButton : function(config){
            if(Ext.isArray(config)){
                var buttons = [];
                for(var i = 0, len = config.length; i < len; i++) {
                    buttons.push(this.addButton(config[i]));
                }
                return buttons;
            }
            var b = config;
            if(!(config instanceof T.Button)){
                b = config.split ?
                    new T.SplitButton(config) :
                    new T.Button(config);
            }
            var td = this.nextBlock();
            this.initMenuTracking(b);
            b.render(td);
            this.items.add(b);
            return b;
        },

        initMenuTracking : function(item){
            if(this.trackMenus && item.menu){
                item.on({
                    'menutriggerover' : this.onButtonTriggerOver,
                    'menushow' : this.onButtonMenuShow,
                    'menuhide' : this.onButtonMenuHide,
                    scope: this
                })
            }
        },

        addText : function(text){
            return this.addItem(new T.TextItem(text));
        },

        insertButton : function(index, item){
            if(Ext.isArray(item)){
                var buttons = [];
                for(var i = 0, len = item.length; i < len; i++) {
                   buttons.push(this.insertButton(index + i, item[i]));
                }
                return buttons;
            }
            if (!(item instanceof T.Button)){
               item = new T.Button(item);
            }
            var td = document.createElement("td");
            this.tr.insertBefore(td, this.tr.childNodes[index]);
            this.initMenuTracking(item);
            item.render(td);
            this.items.insert(index, item);
            return item;
        },

        addDom : function(config, returnEl){
            var td = this.nextBlock();
            Ext.DomHelper.overwrite(td, config);
            var ti = new T.Item(td.firstChild);
            ti.render(td);
            this.items.add(ti);
            return ti;
        },

        addField : function(field){
            var td = this.nextBlock();
            field.render(td);
            var ti = new T.Item(td.firstChild);
            ti.render(td);
            this.items.add(ti);
            return ti;
        },

        nextBlock : function(){
            var td = document.createElement("td");
            this.tr.appendChild(td);
            return td;
        },

        onDestroy : function(){
            Ext.Toolbar.superclass.onDestroy.call(this);
            if(this.rendered){
                if(this.items){
                    Ext.destroy.apply(Ext, this.items.items);
                }
                Ext.Element.uncache(this.tr);
            }
        },

        onDisable : function(){
            this.items.each(function(item){
                 if(item.disable){
                     item.disable();
                 }
            });
        },

        onEnable : function(){
            this.items.each(function(item){
                 if(item.enable){
                     item.enable();
                 }
            });
        },

        onButtonTriggerOver : function(btn){
            if(this.activeMenuBtn && this.activeMenuBtn != btn){
                this.activeMenuBtn.hideMenu();
                btn.showMenu();
                this.activeMenuBtn = btn;
            }
        },

        onButtonMenuShow : function(btn){
            this.activeMenuBtn = btn;
        },

        onButtonMenuHide : function(btn){
            delete this.activeMenuBtn;
        }

    });
    Ext.reg('toolbar', Ext.Toolbar);

    T.Item = function(el){
        this.el = Ext.getDom(el);
        this.id = Ext.id(this.el);
        this.hidden = false;
    };

    T.Item.prototype = {

        getEl : function(){
           return this.el;
        },

        render : function(td){
            this.td = td;
            td.appendChild(this.el);
        },

        destroy : function(){
            if(this.td && this.td.parentNode){
                this.td.parentNode.removeChild(this.td);
            }
        },

        show: function(){
            this.hidden = false;
            this.td.style.display = "";
        },

        hide: function(){
            this.hidden = true;
            this.td.style.display = "none";
        },

        setVisible: function(visible){
            if(visible) {
                this.show();
            }else{
                this.hide();
            }
        },

        focus : function(){
            Ext.fly(this.el).focus();
        },

        disable : function(){
            Ext.fly(this.td).addClass("x-item-disabled");
            this.disabled = true;
            this.el.disabled = true;
        },

        enable : function(){
            Ext.fly(this.td).removeClass("x-item-disabled");
            this.disabled = false;
            this.el.disabled = false;
        }
    };
    Ext.reg('tbitem', T.Item);

    T.Separator = function(){
        var s = document.createElement("span");
        s.className = "xtb-sep";
        T.Separator.superclass.constructor.call(this, s);
    };
    Ext.extend(T.Separator, T.Item, {
        enable:Ext.emptyFn,
        disable:Ext.emptyFn,
        focus:Ext.emptyFn
    });
    Ext.reg('tbseparator', T.Separator);

    T.Spacer = function(){
        var s = document.createElement("div");
        s.className = "xtb-spacer";
        T.Spacer.superclass.constructor.call(this, s);
    };
    Ext.extend(T.Spacer, T.Item, {
        enable:Ext.emptyFn,
        disable:Ext.emptyFn,
        focus:Ext.emptyFn
    });

    Ext.reg('tbspacer', T.Spacer);

    T.Fill = Ext.extend(T.Spacer, {

        render : function(td){
            td.style.width = '100%';
            T.Fill.superclass.render.call(this, td);
        }
    });
    Ext.reg('tbfill', T.Fill);

    T.TextItem = function(t){
        var s = document.createElement("span");
        s.className = "xtb-text";
        s.innerHTML = t.text ? t.text : t;
        T.TextItem.superclass.constructor.call(this, s);
    };
    Ext.extend(T.TextItem, T.Item, {
        enable:Ext.emptyFn,
        disable:Ext.emptyFn,
        focus:Ext.emptyFn
    });
    Ext.reg('tbtext', T.TextItem);

    T.Button = Ext.extend(Ext.Button, {
        hideParent : true,

        onDestroy : function(){
            T.Button.superclass.onDestroy.call(this);
            if(this.container){
                this.container.remove();
            }
        }
    });
    Ext.reg('tbbutton', T.Button);

    T.SplitButton = Ext.extend(Ext.SplitButton, {
        hideParent : true,

        onDestroy : function(){
            T.SplitButton.superclass.onDestroy.call(this);
            if(this.container){
                this.container.remove();
            }
        }
    });

    Ext.reg('tbsplit', T.SplitButton);

    T.MenuButton = T.SplitButton;

    })();

    Ext.PagingToolbar = Ext.extend(Ext.Toolbar, {

        pageSize: 20,

        displayMsg : 'Displaying {0} - {1} of {2}',

        emptyMsg : 'No data to display',

        beforePageText : "Page",

        afterPageText : "of {0}",

        firstText : "First Page",

        prevText : "Previous Page",

        nextText : "Next Page",

        lastText : "Last Page",

        refreshText : "Refresh",

        paramNames : {start: 'start', limit: 'limit'},

        initComponent : function(){
            Ext.PagingToolbar.superclass.initComponent.call(this);
            this.cursor = 0;
            this.bind(this.store);
        },

            onRender : function(ct, position){
            Ext.PagingToolbar.superclass.onRender.call(this, ct, position);
            this.first = this.addButton({
                tooltip: this.firstText,
                iconCls: "x-tbar-page-first",
                disabled: true,
                handler: this.onClick.createDelegate(this, ["first"])
            });
            this.prev = this.addButton({
                tooltip: this.prevText,
                iconCls: "x-tbar-page-prev",
                disabled: true,
                handler: this.onClick.createDelegate(this, ["prev"])
            });
            this.addSeparator();
            this.add(this.beforePageText);
            this.field = Ext.get(this.addDom({
               tag: "input",
               type: "text",
               size: "3",
               value: "1",
               cls: "x-tbar-page-number"
            }).el);
            this.field.on("keydown", this.onPagingKeydown, this);
            this.field.on("focus", function(){this.dom.select();});
            this.afterTextEl = this.addText(String.format(this.afterPageText, 1));
            this.field.setHeight(18);
            this.addSeparator();
            this.next = this.addButton({
                tooltip: this.nextText,
                iconCls: "x-tbar-page-next",
                disabled: true,
                handler: this.onClick.createDelegate(this, ["next"])
            });
            this.last = this.addButton({
                tooltip: this.lastText,
                iconCls: "x-tbar-page-last",
                disabled: true,
                handler: this.onClick.createDelegate(this, ["last"])
            });
            this.addSeparator();
            this.loading = this.addButton({
                tooltip: this.refreshText,
                iconCls: "x-tbar-loading",
                handler: this.onClick.createDelegate(this, ["refresh"])
            });

            if(this.displayInfo){
                this.displayEl = Ext.fly(this.el.dom).createChild({cls:'x-paging-info'});
            }
            if(this.dsLoaded){
                this.onLoad.apply(this, this.dsLoaded);
            }
        },

            updateInfo : function(){
            if(this.displayEl){
                var count = this.store.getCount();
                var msg = count == 0 ?
                    this.emptyMsg :
                    String.format(
                        this.displayMsg,
                        this.cursor+1, this.cursor+count, this.store.getTotalCount()
                    );
                this.displayEl.update(msg);
            }
        },

            onLoad : function(store, r, o){
            if(!this.rendered){
                this.dsLoaded = [store, r, o];
                return;
            }
           this.cursor = o.params ? o.params[this.paramNames.start] : 0;
           var d = this.getPageData(), ap = d.activePage, ps = d.pages;

           this.afterTextEl.el.innerHTML = String.format(this.afterPageText, d.pages);
           this.field.dom.value = ap;
           this.first.setDisabled(ap == 1);
           this.prev.setDisabled(ap == 1);
           this.next.setDisabled(ap == ps);
           this.last.setDisabled(ap == ps);
           this.loading.enable();
           this.updateInfo();
        },

            getPageData : function(){
            var total = this.store.getTotalCount();
            return {
                total : total,
                activePage : Math.ceil((this.cursor+this.pageSize)/this.pageSize),
                pages :  total < this.pageSize ? 1 : Math.ceil(total/this.pageSize)
            };
        },

            onLoadError : function(){
            if(!this.rendered){
                return;
            }
            this.loading.enable();
        },

        readPage : function(d){
            var v = this.field.dom.value, pageNum;
            if (!v || isNaN(pageNum = parseInt(v, 10))) {
                this.field.dom.value = d.activePage;
                return false;
            }
            return pageNum;
        },

            onPagingKeydown : function(e){
            var k = e.getKey(), d = this.getPageData(), pageNum;
            if (k == e.RETURN) {
                e.stopEvent();
                if(pageNum = this.readPage(d)){
                    pageNum = Math.min(Math.max(1, pageNum), d.pages) - 1;
                    this.doLoad(pageNum * this.pageSize);
                }
            }else if (k == e.HOME || k == e.END){
                e.stopEvent();
                pageNum = k == e.HOME ? 1 : d.pages;
                this.field.dom.value = pageNum;
            }else if (k == e.UP || k == e.PAGEUP || k == e.DOWN || k == e.PAGEDOWN){
                e.stopEvent();
                if(pageNum = this.readPage(d)){
                    var increment = e.shiftKey ? 10 : 1;
                    if(k == e.DOWN || k == e.PAGEDOWN){
                        increment *= -1;
                    }
                    pageNum += increment;
                    if(pageNum >= 1 & pageNum <= d.pages){
                        this.field.dom.value = pageNum;
                    }
                }
            }
        },

            beforeLoad : function(){
            if(this.rendered && this.loading){
                this.loading.disable();
            }
        },

        doLoad : function(start){
            var o = {}, pn = this.paramNames;
            o[pn.start] = start;
            o[pn.limit] = this.pageSize;
            this.store.load({params:o});
        },

            onClick : function(which){
            var store = this.store;
            switch(which){
                case "first":
                    this.doLoad(0);
                break;
                case "prev":
                    this.doLoad(Math.max(0, this.cursor-this.pageSize));
                break;
                case "next":
                    this.doLoad(this.cursor+this.pageSize);
                break;
                case "last":
                    var total = store.getTotalCount();
                    var extra = total % this.pageSize;
                    var lastStart = extra ? (total - extra) : total-this.pageSize;
                    this.doLoad(lastStart);
                break;
                case "refresh":
                    this.doLoad(this.cursor);
                break;
            }
        },

        unbind : function(store){
            store = Ext.StoreMgr.lookup(store);
            store.un("beforeload", this.beforeLoad, this);
            store.un("load", this.onLoad, this);
            store.un("loadexception", this.onLoadError, this);
            this.store = undefined;
        },

        bind : function(store){
            store = Ext.StoreMgr.lookup(store);
            store.on("beforeload", this.beforeLoad, this);
            store.on("load", this.onLoad, this);
            store.on("loadexception", this.onLoadError, this);
            this.store = store;
        }
    });
    Ext.reg('paging', Ext.PagingToolbar);

    Ext.Resizable = function(el, config){
        this.el = Ext.get(el);

        if(config && config.wrap){
            config.resizeChild = this.el;
            this.el = this.el.wrap(typeof config.wrap == "object" ? config.wrap : {cls:"xresizable-wrap"});
            this.el.id = this.el.dom.id = config.resizeChild.id + "-rzwrap";
            this.el.setStyle("overflow", "hidden");
            this.el.setPositioning(config.resizeChild.getPositioning());
            config.resizeChild.clearPositioning();
            if(!config.width || !config.height){
                var csize = config.resizeChild.getSize();
                this.el.setSize(csize.width, csize.height);
            }
            if(config.pinned && !config.adjustments){
                config.adjustments = "auto";
            }
        }

        this.proxy = this.el.createProxy({tag: "div", cls: "x-resizable-proxy", id: this.el.id + "-rzproxy"});
        this.proxy.unselectable();
        this.proxy.enableDisplayMode('block');

        Ext.apply(this, config);

        if(this.pinned){
            this.disableTrackOver = true;
            this.el.addClass("x-resizable-pinned");
        }

        var position = this.el.getStyle("position");
        if(position != "absolute" && position != "fixed"){
            this.el.setStyle("position", "relative");
        }
        if(!this.handles){
            this.handles = 's,e,se';
            if(this.multiDirectional){
                this.handles += ',n,w';
            }
        }
        if(this.handles == "all"){
            this.handles = "n s e w ne nw se sw";
        }
        var hs = this.handles.split(/\s*?[,;]\s*?| /);
        var ps = Ext.Resizable.positions;
        for(var i = 0, len = hs.length; i < len; i++){
            if(hs[i] && ps[hs[i]]){
                var pos = ps[hs[i]];
                this[pos] = new Ext.Resizable.Handle(this, pos, this.disableTrackOver, this.transparent);
            }
        }

        this.corner = this.southeast;

        if(this.handles.indexOf("n") != -1 || this.handles.indexOf("w") != -1){
            this.updateBox = true;
        }

        this.activeHandle = null;

        if(this.resizeChild){
            if(typeof this.resizeChild == "boolean"){
                this.resizeChild = Ext.get(this.el.dom.firstChild, true);
            }else{
                this.resizeChild = Ext.get(this.resizeChild, true);
            }
        }

        if(this.adjustments == "auto"){
            var rc = this.resizeChild;
            var hw = this.west, he = this.east, hn = this.north, hs = this.south;
            if(rc && (hw || hn)){
                rc.position("relative");
                rc.setLeft(hw ? hw.el.getWidth() : 0);
                rc.setTop(hn ? hn.el.getHeight() : 0);
            }
            this.adjustments = [
                (he ? -he.el.getWidth() : 0) + (hw ? -hw.el.getWidth() : 0),
                (hn ? -hn.el.getHeight() : 0) + (hs ? -hs.el.getHeight() : 0) -1
            ];
        }

        if(this.draggable){
            this.dd = this.dynamic ?
                this.el.initDD(null) : this.el.initDDProxy(null, {dragElId: this.proxy.id});
            this.dd.setHandleElId(this.resizeChild ? this.resizeChild.id : this.el.id);
        }

        this.addEvents(
            "beforeresize",
            "resize"
        );

        if(this.width !== null && this.height !== null){
            this.resizeTo(this.width, this.height);
        }else{
            this.updateChildSize();
        }
        if(Ext.isIE){
            this.el.dom.style.zoom = 1;
        }
        Ext.Resizable.superclass.constructor.call(this);
    };

    Ext.extend(Ext.Resizable, Ext.util.Observable, {
            resizeChild : false,
            adjustments : [0, 0],
            minWidth : 5,
            minHeight : 5,
            maxWidth : 10000,
            maxHeight : 10000,
            enabled : true,
            animate : false,
            duration : .35,
            dynamic : false,
            handles : false,
            multiDirectional : false,
            disableTrackOver : false,
            easing : 'easeOutStrong',
            widthIncrement : 0,
            heightIncrement : 0,
            pinned : false,
            width : null,
            height : null,
            preserveRatio : false,
            transparent: false,
            minX: 0,
            minY: 0,
            draggable: false,

        resizeTo : function(width, height){
            this.el.setSize(width, height);
            this.updateChildSize();
            this.fireEvent("resize", this, width, height, null);
        },

        startSizing : function(e, handle){
            this.fireEvent("beforeresize", this, e);
            if(this.enabled){

                if(!this.overlay){
                    this.overlay = this.el.createProxy({tag: "div", cls: "x-resizable-overlay", html: " "}, Ext.getBody());
                    this.overlay.unselectable();
                    this.overlay.enableDisplayMode("block");
                    this.overlay.on("mousemove", this.onMouseMove, this);
                    this.overlay.on("mouseup", this.onMouseUp, this);
                }
                this.overlay.setStyle("cursor", handle.el.getStyle("cursor"));

                this.resizing = true;
                this.startBox = this.el.getBox();
                this.startPoint = e.getXY();
                this.offsets = [(this.startBox.x + this.startBox.width) - this.startPoint[0],
                                (this.startBox.y + this.startBox.height) - this.startPoint[1]];

                this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
                this.overlay.show();

                if(this.constrainTo) {
                    var ct = Ext.get(this.constrainTo);
                    this.resizeRegion = ct.getRegion().adjust(
                        ct.getFrameWidth('t'),
                        ct.getFrameWidth('l'),
                        -ct.getFrameWidth('b'),
                        -ct.getFrameWidth('r')
                    );
                }

                this.proxy.setStyle('visibility', 'hidden');
                this.proxy.show();
                this.proxy.setBox(this.startBox);
                if(!this.dynamic){
                    this.proxy.setStyle('visibility', 'visible');
                }
            }
        },

        onMouseDown : function(handle, e){
            if(this.enabled){
                e.stopEvent();
                this.activeHandle = handle;
                this.startSizing(e, handle);
            }
        },

        onMouseUp : function(e){
            var size = this.resizeElement();
            this.resizing = false;
            this.handleOut();
            this.overlay.hide();
            this.proxy.hide();
            this.fireEvent("resize", this, size.width, size.height, e);
        },

        updateChildSize : function(){
            if(this.resizeChild){
                var el = this.el;
                var child = this.resizeChild;
                var adj = this.adjustments;
                if(el.dom.offsetWidth){
                    var b = el.getSize(true);
                    child.setSize(b.width+adj[0], b.height+adj[1]);
                }

                if(Ext.isIE){
                    setTimeout(function(){
                        if(el.dom.offsetWidth){
                            var b = el.getSize(true);
                            child.setSize(b.width+adj[0], b.height+adj[1]);
                        }
                    }, 10);
                }
            }
        },

        snap : function(value, inc, min){
            if(!inc || !value) return value;
            var newValue = value;
            var m = value % inc;
            if(m > 0){
                if(m > (inc/2)){
                    newValue = value + (inc-m);
                }else{
                    newValue = value - m;
                }
            }
            return Math.max(min, newValue);
        },

        resizeElement : function(){
            var box = this.proxy.getBox();
            if(this.updateBox){
                this.el.setBox(box, false, this.animate, this.duration, null, this.easing);
            }else{
                this.el.setSize(box.width, box.height, this.animate, this.duration, null, this.easing);
            }
            this.updateChildSize();
            if(!this.dynamic){
                this.proxy.hide();
            }
            return box;
        },

        constrain : function(v, diff, m, mx){
            if(v - diff < m){
                diff = v - m;
            }else if(v - diff > mx){
                diff = mx - v;
            }
            return diff;
        },

        onMouseMove : function(e){
            if(this.enabled){
                try{

                if(this.resizeRegion && !this.resizeRegion.contains(e.getPoint())) {
                	return;
                }

                var curSize = this.curSize || this.startBox;
                var x = this.startBox.x, y = this.startBox.y;
                var ox = x, oy = y;
                var w = curSize.width, h = curSize.height;
                var ow = w, oh = h;
                var mw = this.minWidth, mh = this.minHeight;
                var mxw = this.maxWidth, mxh = this.maxHeight;
                var wi = this.widthIncrement;
                var hi = this.heightIncrement;

                var eventXY = e.getXY();
                var diffX = -(this.startPoint[0] - Math.max(this.minX, eventXY[0]));
                var diffY = -(this.startPoint[1] - Math.max(this.minY, eventXY[1]));

                var pos = this.activeHandle.position;

                switch(pos){
                    case "east":
                        w += diffX;
                        w = Math.min(Math.max(mw, w), mxw);
                        break;
                    case "south":
                        h += diffY;
                        h = Math.min(Math.max(mh, h), mxh);
                        break;
                    case "southeast":
                        w += diffX;
                        h += diffY;
                        w = Math.min(Math.max(mw, w), mxw);
                        h = Math.min(Math.max(mh, h), mxh);
                        break;
                    case "north":
                        diffY = this.constrain(h, diffY, mh, mxh);
                        y += diffY;
                        h -= diffY;
                        break;
                    case "west":
                        diffX = this.constrain(w, diffX, mw, mxw);
                        x += diffX;
                        w -= diffX;
                        break;
                    case "northeast":
                        w += diffX;
                        w = Math.min(Math.max(mw, w), mxw);
                        diffY = this.constrain(h, diffY, mh, mxh);
                        y += diffY;
                        h -= diffY;
                        break;
                    case "northwest":
                        diffX = this.constrain(w, diffX, mw, mxw);
                        diffY = this.constrain(h, diffY, mh, mxh);
                        y += diffY;
                        h -= diffY;
                        x += diffX;
                        w -= diffX;
                        break;
                   case "southwest":
                        diffX = this.constrain(w, diffX, mw, mxw);
                        h += diffY;
                        h = Math.min(Math.max(mh, h), mxh);
                        x += diffX;
                        w -= diffX;
                        break;
                }

                var sw = this.snap(w, wi, mw);
                var sh = this.snap(h, hi, mh);
                if(sw != w || sh != h){
                    switch(pos){
                        case "northeast":
                            y -= sh - h;
                        break;
                        case "north":
                            y -= sh - h;
                            break;
                        case "southwest":
                            x -= sw - w;
                        break;
                        case "west":
                            x -= sw - w;
                            break;
                        case "northwest":
                            x -= sw - w;
                            y -= sh - h;
                        break;
                    }
                    w = sw;
                    h = sh;
                }

                if(this.preserveRatio){
                    switch(pos){
                        case "southeast":
                        case "east":
                            h = oh * (w/ow);
                            h = Math.min(Math.max(mh, h), mxh);
                            w = ow * (h/oh);
                           break;
                        case "south":
                            w = ow * (h/oh);
                            w = Math.min(Math.max(mw, w), mxw);
                            h = oh * (w/ow);
                            break;
                        case "northeast":
                            w = ow * (h/oh);
                            w = Math.min(Math.max(mw, w), mxw);
                            h = oh * (w/ow);
                        break;
                        case "north":
                            var tw = w;
                            w = ow * (h/oh);
                            w = Math.min(Math.max(mw, w), mxw);
                            h = oh * (w/ow);
                            x += (tw - w) / 2;
                            break;
                        case "southwest":
                            h = oh * (w/ow);
                            h = Math.min(Math.max(mh, h), mxh);
                            var tw = w;
                            w = ow * (h/oh);
                            x += tw - w;
                            break;
                        case "west":
                            var th = h;
                            h = oh * (w/ow);
                            h = Math.min(Math.max(mh, h), mxh);
                            y += (th - h) / 2;
                            var tw = w;
                            w = ow * (h/oh);
                            x += tw - w;
                           break;
                        case "northwest":
                            var tw = w;
                            var th = h;
                            h = oh * (w/ow);
                            h = Math.min(Math.max(mh, h), mxh);
                            w = ow * (h/oh);
                            y += th - h;
                             x += tw - w;
                           break;

                    }
                }
                this.proxy.setBounds(x, y, w, h);
                if(this.dynamic){
                    this.resizeElement();
                }
                }catch(e){}
            }
        },

        handleOver : function(){
            if(this.enabled){
                this.el.addClass("x-resizable-over");
            }
        },

        handleOut : function(){
            if(!this.resizing){
                this.el.removeClass("x-resizable-over");
            }
        },

        getEl : function(){
            return this.el;
        },

        getResizeChild : function(){
            return this.resizeChild;
        },

        destroy : function(removeEl){
            this.proxy.remove();
            if(this.overlay){
                this.overlay.removeAllListeners();
                this.overlay.remove();
            }
            var ps = Ext.Resizable.positions;
            for(var k in ps){
                if(typeof ps[k] != "function" && this[ps[k]]){
                    var h = this[ps[k]];
                    h.el.removeAllListeners();
                    h.el.remove();
                }
            }
            if(removeEl){
                this.el.update("");
                this.el.remove();
            }
        },

        syncHandleHeight : function(){
            var h = this.el.getHeight(true);
            if(this.west){
                this.west.el.setHeight(h);
            }
            if(this.east){
                this.east.el.setHeight(h);
            }
        }
    });

    Ext.Resizable.positions = {
        n: "north", s: "south", e: "east", w: "west", se: "southeast", sw: "southwest", nw: "northwest", ne: "northeast"
    };

    Ext.Resizable.Handle = function(rz, pos, disableTrackOver, transparent){
        if(!this.tpl){

            var tpl = Ext.DomHelper.createTemplate(
                {tag: "div", cls: "x-resizable-handle x-resizable-handle-{0}"}
            );
            tpl.compile();
            Ext.Resizable.Handle.prototype.tpl = tpl;
        }
        this.position = pos;
        this.rz = rz;
        this.el = this.tpl.append(rz.el.dom, [this.position], true);
        this.el.unselectable();
        if(transparent){
            this.el.setOpacity(0);
        }
        this.el.on("mousedown", this.onMouseDown, this);
        if(!disableTrackOver){
            this.el.on("mouseover", this.onMouseOver, this);
            this.el.on("mouseout", this.onMouseOut, this);
        }
    };

    Ext.Resizable.Handle.prototype = {
        afterResize : function(rz){

        },

        onMouseDown : function(e){
            this.rz.onMouseDown(this, e);
        },

        onMouseOver : function(e){
            this.rz.handleOver(this, e);
        },

        onMouseOut : function(e){
            this.rz.handleOut(this, e);
        }
    };

    Ext.Editor = function(field, config){
        this.field = field;
        Ext.Editor.superclass.constructor.call(this, config);
    };

    Ext.extend(Ext.Editor, Ext.Component, {

        value : "",

        alignment: "c-c?",

        shadow : "frame",

        constrain : false,

        swallowKeys : true,

        completeOnEnter : false,

        cancelOnEsc : false,

        updateEl : false,

        initComponent : function(){
            Ext.Editor.superclass.initComponent.call(this);
            this.addEvents(

                "beforestartedit",

                "startedit",

                "beforecomplete",

                "complete",

                "specialkey"
            );
        },

            onRender : function(ct, position){
            this.el = new Ext.Layer({
                shadow: this.shadow,
                cls: "x-editor",
                parentEl : ct,
                shim : this.shim,
                shadowOffset:4,
                id: this.id,
                constrain: this.constrain
            });
            this.el.setStyle("overflow", Ext.isGecko ? "auto" : "hidden");
            if(this.field.msgTarget != 'title'){
                this.field.msgTarget = 'qtip';
            }
            this.field.inEditor = true;
            this.field.render(this.el);
            if(Ext.isGecko){
                this.field.el.dom.setAttribute('autocomplete', 'off');
            }
            this.field.on("specialkey", this.onSpecialKey, this);
            if(this.swallowKeys){
                this.field.el.swallowEvent(['keydown','keypress']);
            }
            this.field.show();
            this.field.on("blur", this.onBlur, this);
            if(this.field.grow){
                this.field.on("autosize", this.el.sync,  this.el, {delay:1});
            }
        },

        onSpecialKey : function(field, e){
            if(this.completeOnEnter && e.getKey() == e.ENTER){
                e.stopEvent();
                this.completeEdit();
            }else if(this.cancelOnEsc && e.getKey() == e.ESC){
                this.cancelEdit();
            }else{
                this.fireEvent('specialkey', field, e);
            }
        },

        startEdit : function(el, value){
            if(this.editing){
                this.completeEdit();
            }
            this.boundEl = Ext.get(el);
            var v = value !== undefined ? value : this.boundEl.dom.innerHTML;
            if(!this.rendered){
                this.render(this.parentEl || document.body);
            }
            if(this.fireEvent("beforestartedit", this, this.boundEl, v) === false){
                return;
            }
            this.startValue = v;
            this.field.setValue(v);
            this.doAutoSize();
            this.el.alignTo(this.boundEl, this.alignment);
            this.editing = true;
            this.show();
        },

            doAutoSize : function(){
            if(this.autoSize){
                var sz = this.boundEl.getSize();
                switch(this.autoSize){
                    case "width":
                        this.setSize(sz.width,  "");
                    break;
                    case "height":
                        this.setSize("",  sz.height);
                    break;
                    default:
                        this.setSize(sz.width,  sz.height);
                }
            }
        },

        setSize : function(w, h){
            delete this.field.lastSize;
            this.field.setSize(w, h);
            if(this.el){
                this.el.sync();
            }
        },

        realign : function(){
            this.el.alignTo(this.boundEl, this.alignment);
        },

        completeEdit : function(remainVisible){
            if(!this.editing){
                return;
            }
            var v = this.getValue();
            if(this.revertInvalid !== false && !this.field.isValid()){
                v = this.startValue;
                this.cancelEdit(true);
            }
            if(String(v) === String(this.startValue) && this.ignoreNoChange){
                this.editing = false;
                this.hide();
                return;
            }
            if(this.fireEvent("beforecomplete", this, v, this.startValue) !== false){
                this.editing = false;
                if(this.updateEl && this.boundEl){
                    this.boundEl.update(v);
                }
                if(remainVisible !== true){
                    this.hide();
                }
                this.fireEvent("complete", this, v, this.startValue);
            }
        },

            onShow : function(){
            this.el.show();
            if(this.hideEl !== false){
                this.boundEl.hide();
            }
            this.field.show();
            if(Ext.isIE && !this.fixIEFocus){             this.fixIEFocus = true;
                this.deferredFocus.defer(50, this);
            }else{
                this.field.focus();
            }
            this.fireEvent("startedit", this.boundEl, this.startValue);
        },

        deferredFocus : function(){
            if(this.editing){
                this.field.focus();
            }
        },

        cancelEdit : function(remainVisible){
            if(this.editing){
                this.setValue(this.startValue);
                if(remainVisible !== true){
                    this.hide();
                }
            }
        },

            onBlur : function(){
            if(this.allowBlur !== true && this.editing){
                this.completeEdit();
            }
        },

            onHide : function(){
            if(this.editing){
                this.completeEdit();
                return;
            }
            this.field.blur();
            if(this.field.collapse){
                this.field.collapse();
            }
            this.el.hide();
            if(this.hideEl !== false){
                this.boundEl.show();
            }
        },

        setValue : function(v){
            this.field.setValue(v);
        },

        getValue : function(){
            return this.field.getValue();
        },

        beforeDestroy : function(){
            this.field.destroy();
            this.field = null;
        }
    });
    Ext.reg('editor', Ext.Editor);

    Ext.MessageBox = function(){
        var dlg, opt, mask, waitTimer;
        var bodyEl, msgEl, textboxEl, textareaEl, progressBar, pp, iconEl, spacerEl;
        var buttons, activeTextEl, bwidth, iconCls = '';

        var handleButton = function(button){
            dlg.hide();
            Ext.callback(opt.fn, opt.scope||window, [button, activeTextEl.dom.value], 1);
        };

        var handleHide = function(){
            if(opt && opt.cls){
                dlg.el.removeClass(opt.cls);
            }
            progressBar.reset();
        };

        var handleEsc = function(d, k, e){
            if(opt && opt.closable !== false){
                dlg.hide();
            }
            if(e){
                e.stopEvent();
            }
        };

        var updateButtons = function(b){
            var width = 0;
            if(!b){
                buttons["ok"].hide();
                buttons["cancel"].hide();
                buttons["yes"].hide();
                buttons["no"].hide();
                return width;
            }
            dlg.footer.dom.style.display = '';
            for(var k in buttons){
                if(typeof buttons[k] != "function"){
                    if(b[k]){
                        buttons[k].show();
                        buttons[k].setText(typeof b[k] == "string" ? b[k] : Ext.MessageBox.buttonText[k]);
                        width += buttons[k].el.getWidth()+15;
                    }else{
                        buttons[k].hide();
                    }
                }
            }
            return width;
        };

        return {

            getDialog : function(titleText){
               if(!dlg){
                    dlg = new Ext.Window({
                        autoCreate : true,
                        title:titleText,
                        resizable:false,
                        constrain:true,
                        constrainHeader:true,
                        minimizable : false,
                        maximizable : false,
                        stateful: false,
                        modal: true,
                        shim:true,
                        buttonAlign:"center",
                        width:400,
                        height:100,
                        minHeight: 80,
                        plain:true,
                        footer:true,
                        closable:true,
                        close : function(){
                            if(opt && opt.buttons && opt.buttons.no && !opt.buttons.cancel){
                                handleButton("no");
                            }else{
                                handleButton("cancel");
                            }
                        }
                    });
                    buttons = {};
                    var bt = this.buttonText;

                    buttons["ok"] = dlg.addButton(bt["ok"], handleButton.createCallback("ok"));
                    buttons["yes"] = dlg.addButton(bt["yes"], handleButton.createCallback("yes"));
                    buttons["no"] = dlg.addButton(bt["no"], handleButton.createCallback("no"));
                    buttons["cancel"] = dlg.addButton(bt["cancel"], handleButton.createCallback("cancel"));
                    buttons["ok"].hideMode = buttons["yes"].hideMode = buttons["no"].hideMode = buttons["cancel"].hideMode = 'offsets';
                    dlg.render(document.body);
                    dlg.getEl().addClass('x-window-dlg');
                    mask = dlg.mask;
                    bodyEl = dlg.body.createChild({
                        html:'
    '
                    });
                    iconEl = Ext.get(bodyEl.dom.firstChild);
                    var contentEl = bodyEl.dom.childNodes[1];
                    msgEl = Ext.get(contentEl.firstChild);
                    textboxEl = Ext.get(contentEl.childNodes[2]);
                    textboxEl.enableDisplayMode();
                    textboxEl.addKeyListener([10,13], function(){
                        if(dlg.isVisible() && opt && opt.buttons){
                            if(opt.buttons.ok){
                                handleButton("ok");
                            }else if(opt.buttons.yes){
                                handleButton("yes");
                            }
                        }
                    });
                    textareaEl = Ext.get(contentEl.childNodes[3]);
                    textareaEl.enableDisplayMode();
                    progressBar = new Ext.ProgressBar({
                        renderTo:bodyEl
                    });
                   bodyEl.createChild({cls:'x-clear'});
                }
                return dlg;
            },

            updateText : function(text){
                if(!dlg.isVisible() && !opt.width){
                    dlg.setSize(this.maxWidth, 100);
                }
                msgEl.update(text || ' ');

                var iw = iconCls != '' ? (iconEl.getWidth() + iconEl.getMargins('lr')) : 0;
                var mw = msgEl.getWidth() + msgEl.getMargins('lr');
                var fw = dlg.getFrameWidth('lr');
                var bw = dlg.body.getFrameWidth('lr');
                if (Ext.isIE && iw > 0){

                    iw += 3;
                }
                var w = Math.max(Math.min(opt.width || iw+mw+fw+bw, this.maxWidth),
                            Math.max(opt.minWidth || this.minWidth, bwidth || 0));

                if(opt.prompt === true){
                    activeTextEl.setWidth(w-iw-fw-bw);
                }
                if(opt.progress === true || opt.wait === true){
                    progressBar.setSize(w-iw-fw-bw);
                }
                dlg.setSize(w, 'auto').center();
                return this;
            },

            updateProgress : function(value, progressText, msg){
                progressBar.updateProgress(value, progressText);
                if(msg){
                    this.updateText(msg);
                }
                return this;
            },

            isVisible : function(){
                return dlg && dlg.isVisible();
            },

            hide : function(){
                if(this.isVisible()){
                    dlg.hide();
                    handleHide();
                }
                return this;
            },

            show : function(options){
                if(this.isVisible()){
                    this.hide();
                }
                opt = options;
                var d = this.getDialog(opt.title || " ");

                d.setTitle(opt.title || " ");
                var allowClose = (opt.closable !== false && opt.progress !== true && opt.wait !== true);
                d.tools.close.setDisplayed(allowClose);
                activeTextEl = textboxEl;
                opt.prompt = opt.prompt || (opt.multiline ? true : false);
                if(opt.prompt){
                    if(opt.multiline){
                        textboxEl.hide();
                        textareaEl.show();
                        textareaEl.setHeight(typeof opt.multiline == "number" ?
                            opt.multiline : this.defaultTextHeight);
                        activeTextEl = textareaEl;
                    }else{
                        textboxEl.show();
                        textareaEl.hide();
                    }
                }else{
                    textboxEl.hide();
                    textareaEl.hide();
                }
                activeTextEl.dom.value = opt.value || "";
                if(opt.prompt){
                    d.focusEl = activeTextEl;
                }else{
                    var bs = opt.buttons;
                    var db = null;
                    if(bs && bs.ok){
                        db = buttons["ok"];
                    }else if(bs && bs.yes){
                        db = buttons["yes"];
                    }
                    if (db){
                        d.focusEl = db;
                    }
                }
                this.setIcon(opt.icon);
                bwidth = updateButtons(opt.buttons);
                progressBar.setVisible(opt.progress === true || opt.wait === true);
                this.updateProgress(0, opt.progressText);
                this.updateText(opt.msg);
                if(opt.cls){
                    d.el.addClass(opt.cls);
                }
                d.proxyDrag = opt.proxyDrag === true;
                d.modal = opt.modal !== false;
                d.mask = opt.modal !== false ? mask : false;
                if(!d.isVisible()){

                    document.body.appendChild(dlg.el.dom);
                    d.setAnimateTarget(opt.animEl);
                    d.show(opt.animEl);
                }

                d.on('show', function(){
                    if(allowClose === true){
                        d.keyMap.enable();
                    }else{
                        d.keyMap.disable();
                    }
                }, this, {single:true});

                if(opt.wait === true){
                    progressBar.wait(opt.waitConfig);
                }
                return this;
            },

            setIcon : function(icon){
                if(icon && icon != ''){
                    iconEl.removeClass('x-hidden');
                    iconEl.replaceClass(iconCls, icon);
                    iconCls = icon;
                }else{
                    iconEl.replaceClass(iconCls, 'x-hidden');
                    iconCls = '';
                }
                return this;
            },

            progress : function(title, msg, progressText){
                this.show({
                    title : title,
                    msg : msg,
                    buttons: false,
                    progress:true,
                    closable:false,
                    minWidth: this.minProgressWidth,
                    progressText: progressText
                });
                return this;
            },

            wait : function(msg, title, config){
                this.show({
                    title : title,
                    msg : msg,
                    buttons: false,
                    closable:false,
                    wait:true,
                    modal:true,
                    minWidth: this.minProgressWidth,
                    waitConfig: config
                });
                return this;
            },

            alert : function(title, msg, fn, scope){
                this.show({
                    title : title,
                    msg : msg,
                    buttons: this.OK,
                    fn: fn,
                    scope : scope
                });
                return this;
            },

            confirm : function(title, msg, fn, scope){
                this.show({
                    title : title,
                    msg : msg,
                    buttons: this.YESNO,
                    fn: fn,
                    scope : scope,
                    icon: this.QUESTION
                });
                return this;
            },

            prompt : function(title, msg, fn, scope, multiline){
                this.show({
                    title : title,
                    msg : msg,
                    buttons: this.OKCANCEL,
                    fn: fn,
                    minWidth:250,
                    scope : scope,
                    prompt:true,
                    multiline: multiline
                });
                return this;
            },

            OK : {ok:true},

            CANCEL : {cancel:true},

            OKCANCEL : {ok:true, cancel:true},

            YESNO : {yes:true, no:true},

            YESNOCANCEL : {yes:true, no:true, cancel:true},

            INFO : 'ext-mb-info',

            WARNING : 'ext-mb-warning',

            QUESTION : 'ext-mb-question',

            ERROR : 'ext-mb-error',

            defaultTextHeight : 75,

            maxWidth : 600,

            minWidth : 100,

            minProgressWidth : 250,

            buttonText : {
                ok : "OK",
                cancel : "Cancel",
                yes : "Yes",
                no : "No"
            }
        };
    }();

    Ext.Msg = Ext.MessageBox;

    Ext.Tip = Ext.extend(Ext.Panel, {

        minWidth : 40,

        maxWidth : 300,

        shadow : "sides",

        defaultAlign : "tl-bl?",
        autoRender: true,
        quickShowInterval : 250,

        frame:true,
        hidden:true,
        baseCls: 'x-tip',
        floating:{shadow:true,shim:true,useDisplay:true,constrain:false},
        autoHeight:true,

        initComponent : function(){
            Ext.Tip.superclass.initComponent.call(this);
            if(this.closable && !this.title){
                this.elements += ',header';
            }
        },

        afterRender : function(){
            Ext.Tip.superclass.afterRender.call(this);
            if(this.closable){
                this.addTool({
                    id: 'close',
                    handler: this.hide,
                    scope: this
                });
            }
        },

        showAt : function(xy){
            Ext.Tip.superclass.show.call(this);
            if(this.measureWidth !== false && (!this.initialConfig || typeof this.initialConfig.width != 'number')){
                var bw = this.body.getTextWidth();
                if(this.title){
                    bw = Math.max(bw, this.header.child('span').getTextWidth(this.title));
                }
                bw += this.getFrameWidth() + (this.closable ? 20 : 0) + this.body.getPadding("lr");
                this.setWidth(bw.constrain(this.minWidth, this.maxWidth));
            }
            if(this.constrainPosition){
                xy = this.el.adjustForConstraints(xy);
            }
            this.setPagePosition(xy[0], xy[1]);
        },

        showBy : function(el, pos){
            if(!this.rendered){
                this.render(Ext.getBody());
            }
            this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign));
        },

        initDraggable : function(){
            this.dd = new Ext.Tip.DD(this, typeof this.draggable == 'boolean' ? null : this.draggable);
            this.header.addClass('x-tip-draggable');
        }
    });

    Ext.Tip.DD = function(tip, config){
        Ext.apply(this, config);
        this.tip = tip;
        Ext.Tip.DD.superclass.constructor.call(this, tip.el.id, 'WindowDD-'+tip.id);
        this.setHandleElId(tip.header.id);
        this.scroll = false;
    };

    Ext.extend(Ext.Tip.DD, Ext.dd.DD, {
        moveOnly:true,
        scroll:false,
        headerOffsets:[100, 25],
        startDrag : function(){
            this.tip.el.disableShadow();
        },
        endDrag : function(e){
            this.tip.el.enableShadow(true);
        }
    });

    Ext.ToolTip = Ext.extend(Ext.Tip, {

        showDelay: 500,

        hideDelay: 200,

        dismissDelay: 5000,

        mouseOffset: [15,18],

        trackMouse : false,
        constrainPosition: true,

        initComponent: function(){
            Ext.ToolTip.superclass.initComponent.call(this);
            this.lastActive = new Date();
            this.initTarget();
        },

        initTarget : function(){
            if(this.target){
                this.target = Ext.get(this.target);
                this.target.on('mouseover', this.onTargetOver, this);
                this.target.on('mouseout', this.onTargetOut, this);
                this.target.on('mousemove', this.onMouseMove, this);
            }
        },

        onMouseMove : function(e){
            this.targetXY = e.getXY();
            if(!this.hidden && this.trackMouse){
                this.setPagePosition(this.getTargetXY());
            }
        },

        getTargetXY : function(){
            return [this.targetXY[0]+this.mouseOffset[0], this.targetXY[1]+this.mouseOffset[1]];
        },

        onTargetOver : function(e){
            if(this.disabled || e.within(this.target.dom, true)){
                return;
            }
            this.clearTimer('hide');
            this.targetXY = e.getXY();
            this.delayShow();
        },

        delayShow : function(){
            if(this.hidden && !this.showTimer){
                if(this.lastActive.getElapsed() < this.quickShowInterval){
                    this.show();
                }else{
                    this.showTimer = this.show.defer(this.showDelay, this);
                }
            }else if(!this.hidden && this.autoHide !== false){
                this.show();
            }
        },

        onTargetOut : function(e){
            if(this.disabled || e.within(this.target.dom, true)){
                return;
            }
            this.clearTimer('show');
            if(this.autoHide !== false){
                this.delayHide();
            }
        },

        delayHide : function(){
            if(!this.hidden && !this.hideTimer){
                this.hideTimer = this.hide.defer(this.hideDelay, this);
            }
        },

        hide: function(){
            this.clearTimer('dismiss');
            this.lastActive = new Date();
            Ext.ToolTip.superclass.hide.call(this);
        },

        show : function(){
            this.showAt(this.getTargetXY());
        },

        showAt : function(xy){
            this.lastActive = new Date();
            this.clearTimers();
            Ext.ToolTip.superclass.showAt.call(this, xy);
            if(this.dismissDelay && this.autoHide !== false){
                this.dismissTimer = this.hide.defer(this.dismissDelay, this);
            }
        },

        clearTimer : function(name){
            name = name + 'Timer';
            clearTimeout(this[name]);
            delete this[name];
        },

        clearTimers : function(){
            this.clearTimer('show');
            this.clearTimer('dismiss');
            this.clearTimer('hide');
        },

        onShow : function(){
            Ext.ToolTip.superclass.onShow.call(this);
            Ext.getDoc().on('mousedown', this.onDocMouseDown, this);
        },

        onHide : function(){
            Ext.ToolTip.superclass.onHide.call(this);
            Ext.getDoc().un('mousedown', this.onDocMouseDown, this);
        },

        onDocMouseDown : function(e){
            if(this.autoHide !== false && !e.within(this.el.dom)){
                this.disable();
                this.enable.defer(100, this);
            }
        },

        onDisable : function(){
            this.clearTimers();
            this.hide();
        },

        adjustPosition : function(x, y){

            var ay = this.targetXY[1], h = this.getSize().height;
            if(this.constrainPosition && y <= ay && (y+h) >= ay){
                y = ay-h-5;
            }
            return {x : x, y: y};
        },

        onDestroy : function(){
            Ext.ToolTip.superclass.onDestroy.call(this);
            if(this.target){
                this.target.un('mouseover', this.onTargetOver, this);
                this.target.un('mouseout', this.onTargetOut, this);
                this.target.un('mousemove', this.onMouseMove, this);
            }
        }
    });

    Ext.QuickTip = Ext.extend(Ext.ToolTip, {

        interceptTitles : false,

        tagConfig : {
            namespace : "ext",
            attribute : "qtip",
            width : "qwidth",
            target : "target",
            title : "qtitle",
            hide : "hide",
            cls : "qclass",
            align : "qalign"
        },

        initComponent : function(){
            this.target = this.target || Ext.getDoc();
            this.targets = this.targets || {};
            Ext.QuickTip.superclass.initComponent.call(this);
        },

        register : function(config){
            var cs = Ext.isArray(config) ? config : arguments;
            for(var i = 0, len = cs.length; i < len; i++){
                var c = cs[i];
                var target = c.target;
                if(target){
                    if(Ext.isArray(target)){
                        for(var j = 0, jlen = target.length; j < jlen; j++){
                            this.targets[Ext.id(target[j])] = c;
                        }
                    } else{
                        this.targets[Ext.id(target)] = c;
                    }
                }
            }
        },

        unregister : function(el){
            delete this.targets[Ext.id(el)];
        },

        onTargetOver : function(e){
            if(this.disabled){
                return;
            }
            this.targetXY = e.getXY();
            var t = e.getTarget();
            if(!t || t.nodeType !== 1 || t == document || t == document.body){
                return;
            }
            if(this.activeTarget && t == this.activeTarget.el){
                this.clearTimer('hide');
                this.show();
                return;
            }
            if(t && this.targets[t.id]){
                this.activeTarget = this.targets[t.id];
                this.activeTarget.el = t;
                this.delayShow();
                return;
            }
            var ttp, et = Ext.fly(t), cfg = this.tagConfig;
            var ns = cfg.namespace;
            if(this.interceptTitles && t.title){
                ttp = t.title;
                t.qtip = ttp;
                t.removeAttribute("title");
                e.preventDefault();
            } else{
                ttp = t.qtip || et.getAttributeNS(ns, cfg.attribute);
            }
            if(ttp){
                var autoHide = et.getAttributeNS(ns, cfg.hide);
                this.activeTarget = {
                    el: t,
                    text: ttp,
                    width: et.getAttributeNS(ns, cfg.width),
                    autoHide: autoHide != "user" && autoHide !== 'false',
                    title: et.getAttributeNS(ns, cfg.title),
                    cls: et.getAttributeNS(ns, cfg.cls),
                    align: et.getAttributeNS(ns, cfg.align)
                };
                this.delayShow();
            }
        },

        onTargetOut : function(e){
            this.clearTimer('show');
            if(this.autoHide !== false){
                this.delayHide();
            }
        },

        showAt : function(xy){
            var t = this.activeTarget;
            if(t){
                if(!this.rendered){
                    this.render(Ext.getBody());
                    this.activeTarget = t;
                }
                if(t.width){
                    this.setWidth(t.width);
                    this.body.setWidth(this.adjustBodyWidth(t.width - this.getFrameWidth()));
                    this.measureWidth = false;
                } else{
                    this.measureWidth = true;
                }
                this.setTitle(t.title || '');
                this.body.update(t.text);
                this.autoHide = t.autoHide;
                this.dismissDelay = t.dismissDelay || this.dismissDelay;
                if(this.lastCls){
                    this.el.removeClass(this.lastCls);
                    delete this.lastCls;
                }
                if(t.cls){
                    this.el.addClass(t.cls);
                    this.lastCls = t.cls;
                }
                if(t.align){
                    xy = this.el.getAlignToXY(t.el, t.align);
                    this.constrainPosition = false;
                } else{
                    this.constrainPosition = true;
                }
            }
            Ext.QuickTip.superclass.showAt.call(this, xy);
        },

        hide: function(){
            delete this.activeTarget;
            Ext.QuickTip.superclass.hide.call(this);
        }
    });

    Ext.QuickTips = function(){
        var tip, locks = [];
        return {

            init : function(){
                if(!tip){
                    tip = new Ext.QuickTip({elements:'header,body'});
                }
            },

            enable : function(){
                if(tip){
                    locks.pop();
                    if(locks.length < 1){
                        tip.enable();
                    }
                }
            },

            disable : function(){
                if(tip){
                    tip.disable();
                }
                locks.push(1);
            },

            isEnabled : function(){
                return tip && !tip.disabled;
            },

            getQuickTip : function(){
                return tip;
            },

            register : function(){
                tip.register.apply(tip, arguments);
            },

            unregister : function(){
                tip.unregister.apply(tip, arguments);
            },

            tips :function(){
                tip.register.apply(tip, arguments);
            }
        }
    }();

    Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
        rootVisible : true,
        animate: Ext.enableFx,
        lines : true,
        enableDD : false,
        hlDrop : Ext.enableFx,
        pathSeparator: "/",

        initComponent : function(){
            Ext.tree.TreePanel.superclass.initComponent.call(this);

            if(!this.eventModel){
                this.eventModel = new Ext.tree.TreeEventModel(this);
            }

            this.nodeHash = {};

            if(this.root){
               this.setRootNode(this.root);
            }

            this.addEvents(

               "append",

               "remove",

               "movenode",

               "insert",

               "beforeappend",

               "beforeremove",

               "beforemovenode",

                "beforeinsert",

                "beforeload",

                "load",

                "textchange",

                "beforeexpandnode",

                "beforecollapsenode",

                "expandnode",

                "disabledchange",

                "collapsenode",

                "beforeclick",

                "click",

                "checkchange",

                "dblclick",

                "contextmenu",

                "beforechildrenrendered",

                "startdrag",

                "enddrag",

                "dragdrop",

                "beforenodedrop",

                "nodedrop",

                "nodedragover"
            );
            if(this.singleExpand){
                this.on("beforeexpandnode", this.restrictExpand, this);
            }
        },

        proxyNodeEvent : function(ename, a1, a2, a3, a4, a5, a6){
            if(ename == 'collapse' || ename == 'expand' || ename == 'beforecollapse' || ename == 'beforeexpand' || ename == 'move' || ename == 'beforemove'){
                ename = ename+'node';
            }

            return this.fireEvent(ename, a1, a2, a3, a4, a5, a6);
        },

        getRootNode : function(){
            return this.root;
        },

        setRootNode : function(node){
            this.root = node;
            node.ownerTree = this;
            node.isRoot = true;
            this.registerNode(node);
            if(!this.rootVisible){
            	var uiP = node.attributes.uiProvider;
            	node.ui = uiP ? new uiP(node) : new Ext.tree.RootTreeNodeUI(node);
            }
            return node;
        },

        getNodeById : function(id){
            return this.nodeHash[id];
        },

        registerNode : function(node){
            this.nodeHash[node.id] = node;
        },

        unregisterNode : function(node){
            delete this.nodeHash[node.id];
        },

        toString : function(){
            return "[Tree"+(this.id?" "+this.id:"")+"]";
        },

        restrictExpand : function(node){
            var p = node.parentNode;
            if(p){
                if(p.expandedChild && p.expandedChild.parentNode == p){
                    p.expandedChild.collapse();
                }
                p.expandedChild = node;
            }
        },

        getChecked : function(a, startNode){
            startNode = startNode || this.root;
            var r = [];
            var f = function(){
                if(this.attributes.checked){
                    r.push(!a ? this : (a == 'id' ? this.id : this.attributes[a]));
                }
            }
            startNode.cascade(f);
            return r;
        },

        getEl : function(){
            return this.el;
        },

        getLoader : function(){
            return this.loader;
        },

        expandAll : function(){
            this.root.expand(true);
        },

        collapseAll : function(){
            this.root.collapse(true);
        },

        getSelectionModel : function(){
            if(!this.selModel){
                this.selModel = new Ext.tree.DefaultSelectionModel();
            }
            return this.selModel;
        },

        expandPath : function(path, attr, callback){
            attr = attr || "id";
            var keys = path.split(this.pathSeparator);
            var curNode = this.root;
            if(curNode.attributes[attr] != keys[1]){
                if(callback){
                    callback(false, null);
                }
                return;
            }
            var index = 1;
            var f = function(){
                if(++index == keys.length){
                    if(callback){
                        callback(true, curNode);
                    }
                    return;
                }
                var c = curNode.findChild(attr, keys[index]);
                if(!c){
                    if(callback){
                        callback(false, curNode);
                    }
                    return;
                }
                curNode = c;
                c.expand(false, false, f);
            };
            curNode.expand(false, false, f);
        },

        selectPath : function(path, attr, callback){
            attr = attr || "id";
            var keys = path.split(this.pathSeparator);
            var v = keys.pop();
            if(keys.length > 0){
                var f = function(success, node){
                    if(success && node){
                        var n = node.findChild(attr, v);
                        if(n){
                            n.select();
                            if(callback){
                                callback(true, n);
                            }
                        }else if(callback){
                            callback(false, n);
                        }
                    }else{
                        if(callback){
                            callback(false, n);
                        }
                    }
                };
                this.expandPath(keys.join(this.pathSeparator), attr, f);
            }else{
                this.root.select();
                if(callback){
                    callback(true, this.root);
                }
            }
        },

        getTreeEl : function(){
            return this.body;
        },

        onRender : function(ct, position){
            Ext.tree.TreePanel.superclass.onRender.call(this, ct, position);
            this.el.addClass('x-tree');
            this.innerCt = this.body.createChild({tag:"ul",
                   cls:"x-tree-root-ct " +
                   (this.useArrows ? 'x-tree-arrows' : this.lines ? "x-tree-lines" : "x-tree-no-lines")});
        },

        initEvents : function(){
            Ext.tree.TreePanel.superclass.initEvents.call(this);

            if(this.containerScroll){
                Ext.dd.ScrollManager.register(this.body);
            }
            if((this.enableDD || this.enableDrop) && !this.dropZone){

                 this.dropZone = new Ext.tree.TreeDropZone(this, this.dropConfig || {
                   ddGroup: this.ddGroup || "TreeDD", appendOnly: this.ddAppendOnly === true
               });
            }
            if((this.enableDD || this.enableDrag) && !this.dragZone){

                this.dragZone = new Ext.tree.TreeDragZone(this, this.dragConfig || {
                   ddGroup: this.ddGroup || "TreeDD",
                   scroll: this.ddScroll
               });
            }
            this.getSelectionModel().init(this);
        },

        afterRender : function(){
            Ext.tree.TreePanel.superclass.afterRender.call(this);
            this.root.render();
            if(!this.rootVisible){
                this.root.renderChildren();
            }
        },

        onDestroy : function(){
            if(this.rendered){
                this.body.removeAllListeners();
                Ext.dd.ScrollManager.unregister(this.body);
                if(this.dropZone){
                    this.dropZone.unreg();
                }
                if(this.dragZone){
                   this.dragZone.unreg();
                }
            }
            this.root.destroy();
            this.nodeHash = null;
            Ext.tree.TreePanel.superclass.onDestroy.call(this);
        }

    });
    Ext.reg('treepanel', Ext.tree.TreePanel);
    Ext.tree.TreeEventModel = function(tree){
        this.tree = tree;
        this.tree.on('render', this.initEvents, this);
    }

    Ext.tree.TreeEventModel.prototype = {
        initEvents : function(){
            var el = this.tree.getTreeEl();
            el.on('click', this.delegateClick, this);
            if(this.tree.trackMouseOver !== false){
                el.on('mouseover', this.delegateOver, this);
                el.on('mouseout', this.delegateOut, this);
            }
            el.on('dblclick', this.delegateDblClick, this);
            el.on('contextmenu', this.delegateContextMenu, this);
        },

        getNode : function(e){
            var t;
            if(t = e.getTarget('.x-tree-node-el', 10)){
                var id = Ext.fly(t, '_treeEvents').getAttributeNS('ext', 'tree-node-id');
                if(id){
                    return this.tree.getNodeById(id);
                }
            }
            return null;
        },

        getNodeTarget : function(e){
            var t = e.getTarget('.x-tree-node-icon', 1);
            if(!t){
                t = e.getTarget('.x-tree-node-el', 6);
            }
            return t;
        },

        delegateOut : function(e, t){
            if(!this.beforeEvent(e)){
                return;
            }
            if(e.getTarget('.x-tree-ec-icon', 1)){
                var n = this.getNode(e);
                this.onIconOut(e, n);
                if(n == this.lastEcOver){
                    delete this.lastEcOver;
                }
            }
            if((t = this.getNodeTarget(e)) && !e.within(t, true)){
                this.onNodeOut(e, this.getNode(e));
            }
        },

        delegateOver : function(e, t){
            if(!this.beforeEvent(e)){
                return;
            }
            if(this.lastEcOver){
                this.onIconOut(e, this.lastEcOver);
                delete this.lastEcOver;
            }
            if(e.getTarget('.x-tree-ec-icon', 1)){
                this.lastEcOver = this.getNode(e);
                this.onIconOver(e, this.lastEcOver);
            }
            if(t = this.getNodeTarget(e)){
                this.onNodeOver(e, this.getNode(e));
            }
        },

        delegateClick : function(e, t){
            if(!this.beforeEvent(e)){
                return;
            }

            if(e.getTarget('input[type=checkbox]', 1)){
                this.onCheckboxClick(e, this.getNode(e));
            }
            else if(e.getTarget('.x-tree-ec-icon', 1)){
                this.onIconClick(e, this.getNode(e));
            }
            else if(this.getNodeTarget(e)){
                this.onNodeClick(e, this.getNode(e));
            }
        },

        delegateDblClick : function(e, t){
            if(this.beforeEvent(e) && this.getNodeTarget(e)){
                this.onNodeDblClick(e, this.getNode(e));
            }
        },

        delegateContextMenu : function(e, t){
            if(this.beforeEvent(e) && this.getNodeTarget(e)){
                this.onNodeContextMenu(e, this.getNode(e));
            }
        },

        onNodeClick : function(e, node){
            node.ui.onClick(e);
        },

        onNodeOver : function(e, node){
            node.ui.onOver(e);
        },

        onNodeOut : function(e, node){
            node.ui.onOut(e);
        },

        onIconOver : function(e, node){
            node.ui.addClass('x-tree-ec-over');
        },

        onIconOut : function(e, node){
            node.ui.removeClass('x-tree-ec-over');
        },

        onIconClick : function(e, node){
            node.ui.ecClick(e);
        },

        onCheckboxClick : function(e, node){
            node.ui.onCheckChange(e);
        },

        onNodeDblClick : function(e, node){
            node.ui.onDblClick(e);
        },

        onNodeContextMenu : function(e, node){
            node.ui.onContextMenu(e);
        },

        beforeEvent : function(e){
            if(this.disabled){
                e.stopEvent();
                return false;
            }
            return true;
        },

        disable: function(){
            this.disabled = true;
        },

        enable: function(){
            this.disabled = false;
        }
    };

    Ext.tree.DefaultSelectionModel = function(config){
       this.selNode = null;

       this.addEvents(

           "selectionchange",

           "beforeselect"
       );

        Ext.apply(this, config);
        Ext.tree.DefaultSelectionModel.superclass.constructor.call(this);
    };

    Ext.extend(Ext.tree.DefaultSelectionModel, Ext.util.Observable, {
        init : function(tree){
            this.tree = tree;
            tree.getTreeEl().on("keydown", this.onKeyDown, this);
            tree.on("click", this.onNodeClick, this);
        },

        onNodeClick : function(node, e){
            this.select(node);
        },

        select : function(node){
            var last = this.selNode;
            if(last != node && this.fireEvent('beforeselect', this, node, last) !== false){
                if(last){
                    last.ui.onSelectedChange(false);
                }
                this.selNode = node;
                node.ui.onSelectedChange(true);
                this.fireEvent("selectionchange", this, node, last);
            }
            return node;
        },

        unselect : function(node){
            if(this.selNode == node){
                this.clearSelections();
            }
        },

        clearSelections : function(){
            var n = this.selNode;
            if(n){
                n.ui.onSelectedChange(false);
                this.selNode = null;
                this.fireEvent("selectionchange", this, null);
            }
            return n;
        },

        getSelectedNode : function(){
            return this.selNode;
        },

        isSelected : function(node){
            return this.selNode == node;
        },

        selectPrevious : function(){
            var s = this.selNode || this.lastSelNode;
            if(!s){
                return null;
            }
            var ps = s.previousSibling;
            if(ps){
                if(!ps.isExpanded() || ps.childNodes.length < 1){
                    return this.select(ps);
                } else{
                    var lc = ps.lastChild;
                    while(lc && lc.isExpanded() && lc.childNodes.length > 0){
                        lc = lc.lastChild;
                    }
                    return this.select(lc);
                }
            } else if(s.parentNode && (this.tree.rootVisible || !s.parentNode.isRoot)){
                return this.select(s.parentNode);
            }
            return null;
        },

        selectNext : function(){
            var s = this.selNode || this.lastSelNode;
            if(!s){
                return null;
            }
            if(s.firstChild && s.isExpanded()){
                 return this.select(s.firstChild);
             }else if(s.nextSibling){
                 return this.select(s.nextSibling);
             }else if(s.parentNode){
                var newS = null;
                s.parentNode.bubble(function(){
                    if(this.nextSibling){
                        newS = this.getOwnerTree().selModel.select(this.nextSibling);
                        return false;
                    }
                });
                return newS;
             }
            return null;
        },

        onKeyDown : function(e){
            var s = this.selNode || this.lastSelNode;

            var sm = this;
            if(!s){
                return;
            }
            var k = e.getKey();
            switch(k){
                 case e.DOWN:
                     e.stopEvent();
                     this.selectNext();
                 break;
                 case e.UP:
                     e.stopEvent();
                     this.selectPrevious();
                 break;
                 case e.RIGHT:
                     e.preventDefault();
                     if(s.hasChildNodes()){
                         if(!s.isExpanded()){
                             s.expand();
                         }else if(s.firstChild){
                             this.select(s.firstChild, e);
                         }
                     }
                 break;
                 case e.LEFT:
                     e.preventDefault();
                     if(s.hasChildNodes() && s.isExpanded()){
                         s.collapse();
                     }else if(s.parentNode && (this.tree.rootVisible || s.parentNode != this.tree.getRootNode())){
                         this.select(s.parentNode, e);
                     }
                 break;
            };
        }
    });

    Ext.tree.MultiSelectionModel = function(config){
       this.selNodes = [];
       this.selMap = {};
       this.addEvents(

           "selectionchange"
       );
        Ext.apply(this, config);
        Ext.tree.MultiSelectionModel.superclass.constructor.call(this);
    };

    Ext.extend(Ext.tree.MultiSelectionModel, Ext.util.Observable, {
        init : function(tree){
            this.tree = tree;
            tree.getTreeEl().on("keydown", this.onKeyDown, this);
            tree.on("click", this.onNodeClick, this);
        },

        onNodeClick : function(node, e){
            this.select(node, e, e.ctrlKey);
        },

        select : function(node, e, keepExisting){
            if(keepExisting !== true){
                this.clearSelections(true);
            }
            if(this.isSelected(node)){
                this.lastSelNode = node;
                return node;
            }
            this.selNodes.push(node);
            this.selMap[node.id] = node;
            this.lastSelNode = node;
            node.ui.onSelectedChange(true);
            this.fireEvent("selectionchange", this, this.selNodes);
            return node;
        },

        unselect : function(node){
            if(this.selMap[node.id]){
                node.ui.onSelectedChange(false);
                var sn = this.selNodes;
                var index = sn.indexOf(node);
                if(index != -1){
                    this.selNodes.splice(index, 1);
                }
                delete this.selMap[node.id];
                this.fireEvent("selectionchange", this, this.selNodes);
            }
        },

        clearSelections : function(suppressEvent){
            var sn = this.selNodes;
            if(sn.length > 0){
                for(var i = 0, len = sn.length; i < len; i++){
                    sn[i].ui.onSelectedChange(false);
                }
                this.selNodes = [];
                this.selMap = {};
                if(suppressEvent !== true){
                    this.fireEvent("selectionchange", this, this.selNodes);
                }
            }
        },

        isSelected : function(node){
            return this.selMap[node.id] ? true : false;
        },

        getSelectedNodes : function(){
            return this.selNodes;
        },

        onKeyDown : Ext.tree.DefaultSelectionModel.prototype.onKeyDown,

        selectNext : Ext.tree.DefaultSelectionModel.prototype.selectNext,

        selectPrevious : Ext.tree.DefaultSelectionModel.prototype.selectPrevious
    });

    Ext.tree.TreeNode = function(attributes){
        attributes = attributes || {};
        if(typeof attributes == "string"){
            attributes = {text: attributes};
        }
        this.childrenRendered = false;
        this.rendered = false;
        Ext.tree.TreeNode.superclass.constructor.call(this, attributes);
        this.expanded = attributes.expanded === true;
        this.isTarget = attributes.isTarget !== false;
        this.draggable = attributes.draggable !== false && attributes.allowDrag !== false;
        this.allowChildren = attributes.allowChildren !== false && attributes.allowDrop !== false;

        this.text = attributes.text;

        this.disabled = attributes.disabled === true;

        this.addEvents(

            "textchange",

            "beforeexpand",

            "beforecollapse",

            "expand",

            "disabledchange",

            "collapse",

            "beforeclick",

            "click",

            "checkchange",

            "dblclick",

            "contextmenu",

            "beforechildrenrendered"
        );

        var uiClass = this.attributes.uiProvider || this.defaultUI || Ext.tree.TreeNodeUI;

        this.ui = new uiClass(this);
    };
    Ext.extend(Ext.tree.TreeNode, Ext.data.Node, {
        preventHScroll: true,

        isExpanded : function(){
            return this.expanded;
        },

        getUI : function(){
            return this.ui;
        },

        setFirstChild : function(node){
            var of = this.firstChild;
            Ext.tree.TreeNode.superclass.setFirstChild.call(this, node);
            if(this.childrenRendered && of && node != of){
                of.renderIndent(true, true);
            }
            if(this.rendered){
                this.renderIndent(true, true);
            }
        },

        setLastChild : function(node){
            var ol = this.lastChild;
            Ext.tree.TreeNode.superclass.setLastChild.call(this, node);
            if(this.childrenRendered && ol && node != ol){
                ol.renderIndent(true, true);
            }
            if(this.rendered){
                this.renderIndent(true, true);
            }
        },

        appendChild : function(){
            var node = Ext.tree.TreeNode.superclass.appendChild.apply(this, arguments);
            if(node && this.childrenRendered){
                node.render();
            }
            this.ui.updateExpandIcon();
            return node;
        },

        removeChild : function(node){
            this.ownerTree.getSelectionModel().unselect(node);
            Ext.tree.TreeNode.superclass.removeChild.apply(this, arguments);

            if(this.childrenRendered){
                node.ui.remove();
            }
            if(this.childNodes.length < 1){
                this.collapse(false, false);
            }else{
                this.ui.updateExpandIcon();
            }
            if(!this.firstChild && !this.isHiddenRoot()) {
                this.childrenRendered = false;
            }
            return node;
        },

        insertBefore : function(node, refNode){
            var newNode = Ext.tree.TreeNode.superclass.insertBefore.apply(this, arguments);
            if(newNode && refNode && this.childrenRendered){
                node.render();
            }
            this.ui.updateExpandIcon();
            return newNode;
        },

        setText : function(text){
            var oldText = this.text;
            this.text = text;
            this.attributes.text = text;
            if(this.rendered){
                this.ui.onTextChange(this, text, oldText);
            }
            this.fireEvent("textchange", this, text, oldText);
        },

        select : function(){
            this.getOwnerTree().getSelectionModel().select(this);
        },

        unselect : function(){
            this.getOwnerTree().getSelectionModel().unselect(this);
        },

        isSelected : function(){
            return this.getOwnerTree().getSelectionModel().isSelected(this);
        },

        expand : function(deep, anim, callback){
            if(!this.expanded){
                if(this.fireEvent("beforeexpand", this, deep, anim) === false){
                    return;
                }
                if(!this.childrenRendered){
                    this.renderChildren();
                }
                this.expanded = true;
                if(!this.isHiddenRoot() && (this.getOwnerTree().animate && anim !== false) || anim){
                    this.ui.animExpand(function(){
                        this.fireEvent("expand", this);
                        if(typeof callback == "function"){
                            callback(this);
                        }
                        if(deep === true){
                            this.expandChildNodes(true);
                        }
                    }.createDelegate(this));
                    return;
                }else{
                    this.ui.expand();
                    this.fireEvent("expand", this);
                    if(typeof callback == "function"){
                        callback(this);
                    }
                }
            }else{
               if(typeof callback == "function"){
                   callback(this);
               }
            }
            if(deep === true){
                this.expandChildNodes(true);
            }
        },

        isHiddenRoot : function(){
            return this.isRoot && !this.getOwnerTree().rootVisible;
        },

        collapse : function(deep, anim){
            if(this.expanded && !this.isHiddenRoot()){
                if(this.fireEvent("beforecollapse", this, deep, anim) === false){
                    return;
                }
                this.expanded = false;
                if((this.getOwnerTree().animate && anim !== false) || anim){
                    this.ui.animCollapse(function(){
                        this.fireEvent("collapse", this);
                        if(deep === true){
                            this.collapseChildNodes(true);
                        }
                    }.createDelegate(this));
                    return;
                }else{
                    this.ui.collapse();
                    this.fireEvent("collapse", this);
                }
            }
            if(deep === true){
                var cs = this.childNodes;
                for(var i = 0, len = cs.length; i < len; i++) {
                	cs[i].collapse(true, false);
                }
            }
        },

        delayedExpand : function(delay){
            if(!this.expandProcId){
                this.expandProcId = this.expand.defer(delay, this);
            }
        },

        cancelExpand : function(){
            if(this.expandProcId){
                clearTimeout(this.expandProcId);
            }
            this.expandProcId = false;
        },

        toggle : function(){
            if(this.expanded){
                this.collapse();
            }else{
                this.expand();
            }
        },

        ensureVisible : function(callback){
            var tree = this.getOwnerTree();
            tree.expandPath(this.parentNode.getPath(), false, function(){
                var node = tree.getNodeById(this.id);
                tree.getTreeEl().scrollChildIntoView(node.ui.anchor);
                Ext.callback(callback);
            }.createDelegate(this));
        },

        expandChildNodes : function(deep){
            var cs = this.childNodes;
            for(var i = 0, len = cs.length; i < len; i++) {
            	cs[i].expand(deep);
            }
        },

        collapseChildNodes : function(deep){
            var cs = this.childNodes;
            for(var i = 0, len = cs.length; i < len; i++) {
            	cs[i].collapse(deep);
            }
        },

        disable : function(){
            this.disabled = true;
            this.unselect();
            if(this.rendered && this.ui.onDisableChange){
                this.ui.onDisableChange(this, true);
            }
            this.fireEvent("disabledchange", this, true);
        },

        enable : function(){
            this.disabled = false;
            if(this.rendered && this.ui.onDisableChange){
                this.ui.onDisableChange(this, false);
            }
            this.fireEvent("disabledchange", this, false);
        },

        renderChildren : function(suppressEvent){
            if(suppressEvent !== false){
                this.fireEvent("beforechildrenrendered", this);
            }
            var cs = this.childNodes;
            for(var i = 0, len = cs.length; i < len; i++){
                cs[i].render(true);
            }
            this.childrenRendered = true;
        },

        sort : function(fn, scope){
            Ext.tree.TreeNode.superclass.sort.apply(this, arguments);
            if(this.childrenRendered){
                var cs = this.childNodes;
                for(var i = 0, len = cs.length; i < len; i++){
                    cs[i].render(true);
                }
            }
        },

        render : function(bulkRender){
            this.ui.render(bulkRender);
            if(!this.rendered){

                this.getOwnerTree().registerNode(this);
                this.rendered = true;
                if(this.expanded){
                    this.expanded = false;
                    this.expand(false, false);
                }
            }
        },

        renderIndent : function(deep, refresh){
            if(refresh){
                this.ui.childIndent = null;
            }
            this.ui.renderIndent();
            if(deep === true && this.childrenRendered){
                var cs = this.childNodes;
                for(var i = 0, len = cs.length; i < len; i++){
                    cs[i].renderIndent(true, refresh);
                }
            }
        },

        beginUpdate : function(){
            this.childrenRendered = false;
        },

        endUpdate : function(){
            if(this.expanded){
                this.renderChildren();
            }
        },

        destroy : function(){
            for(var i = 0,l = this.childNodes.length; i < l; i++){
                this.childNodes[i].destroy();
            }
            this.childNodes = null;
            if(this.ui.destroy){
                this.ui.destroy();
            }
        }
    });

     Ext.tree.AsyncTreeNode = function(config){
        this.loaded = false;
        this.loading = false;
        Ext.tree.AsyncTreeNode.superclass.constructor.apply(this, arguments);

        this.addEvents('beforeload', 'load');

    };
    Ext.extend(Ext.tree.AsyncTreeNode, Ext.tree.TreeNode, {
        expand : function(deep, anim, callback){
            if(this.loading){
                var timer;
                var f = function(){
                    if(!this.loading){
                        clearInterval(timer);
                        this.expand(deep, anim, callback);
                    }
                }.createDelegate(this);
                timer = setInterval(f, 200);
                return;
            }
            if(!this.loaded){
                if(this.fireEvent("beforeload", this) === false){
                    return;
                }
                this.loading = true;
                this.ui.beforeLoad(this);
                var loader = this.loader || this.attributes.loader || this.getOwnerTree().getLoader();
                if(loader){
                    loader.load(this, this.loadComplete.createDelegate(this, [deep, anim, callback]));
                    return;
                }
            }
            Ext.tree.AsyncTreeNode.superclass.expand.call(this, deep, anim, callback);
        },

        isLoading : function(){
            return this.loading;
        },

        loadComplete : function(deep, anim, callback){
            this.loading = false;
            this.loaded = true;
            this.ui.afterLoad(this);
            this.fireEvent("load", this);
            this.expand(deep, anim, callback);
        },

        isLoaded : function(){
            return this.loaded;
        },

        hasChildNodes : function(){
            if(!this.isLeaf() && !this.loaded){
                return true;
            }else{
                return Ext.tree.AsyncTreeNode.superclass.hasChildNodes.call(this);
            }
        },

        reload : function(callback){
            this.collapse(false, false);
            while(this.firstChild){
                this.removeChild(this.firstChild);
            }
            this.childrenRendered = false;
            this.loaded = false;
            if(this.isHiddenRoot()){
                this.expanded = false;
            }
            this.expand(false, false, callback);
        }
    });

    Ext.tree.TreeNodeUI = function(node){
        this.node = node;
        this.rendered = false;
        this.animating = false;
        this.wasLeaf = true;
        this.ecc = 'x-tree-ec-icon x-tree-elbow';
        this.emptyIcon = Ext.BLANK_IMAGE_URL;
    };

    Ext.tree.TreeNodeUI.prototype = {

        removeChild : function(node){
            if(this.rendered){
                this.ctNode.removeChild(node.ui.getEl());
            }
        },

        beforeLoad : function(){
             this.addClass("x-tree-node-loading");
        },

        afterLoad : function(){
             this.removeClass("x-tree-node-loading");
        },

        onTextChange : function(node, text, oldText){
            if(this.rendered){
                this.textNode.innerHTML = text;
            }
        },

        onDisableChange : function(node, state){
            this.disabled = state;
    		if (this.checkbox) {
    			this.checkbox.disabled = state;
    		}
            if(state){
                this.addClass("x-tree-node-disabled");
            }else{
                this.removeClass("x-tree-node-disabled");
            }
        },

        onSelectedChange : function(state){
            if(state){
                this.focus();
                this.addClass("x-tree-selected");
            }else{

                this.removeClass("x-tree-selected");
            }
        },

        onMove : function(tree, node, oldParent, newParent, index, refNode){
            this.childIndent = null;
            if(this.rendered){
                var targetNode = newParent.ui.getContainer();
                if(!targetNode){
                    this.holder = document.createElement("div");
                    this.holder.appendChild(this.wrap);
                    return;
                }
                var insertBefore = refNode ? refNode.ui.getEl() : null;
                if(insertBefore){
                    targetNode.insertBefore(this.wrap, insertBefore);
                }else{
                    targetNode.appendChild(this.wrap);
                }
                this.node.renderIndent(true);
            }
        },

        addClass : function(cls){
            if(this.elNode){
                Ext.fly(this.elNode).addClass(cls);
            }
        },

        removeClass : function(cls){
            if(this.elNode){
                Ext.fly(this.elNode).removeClass(cls);
            }
        },

        remove : function(){
            if(this.rendered){
                this.holder = document.createElement("div");
                this.holder.appendChild(this.wrap);
            }
        },

        fireEvent : function(){
            return this.node.fireEvent.apply(this.node, arguments);
        },

        initEvents : function(){
            this.node.on("move", this.onMove, this);

            if(this.node.disabled){
                this.addClass("x-tree-node-disabled");
    			if (this.checkbox) {
    				this.checkbox.disabled = true;
    			}
            }
            if(this.node.hidden){
                this.hide();
            }
            var ot = this.node.getOwnerTree();
            var dd = ot.enableDD || ot.enableDrag || ot.enableDrop;
            if(dd && (!this.node.isRoot || ot.rootVisible)){
                Ext.dd.Registry.register(this.elNode, {
                    node: this.node,
                    handles: this.getDDHandles(),
                    isHandle: false
                });
            }
        },

        getDDHandles : function(){
            return [this.iconNode, this.textNode, this.elNode];
        },

        hide : function(){
            this.node.hidden = true;
            if(this.wrap){
                this.wrap.style.display = "none";
            }
        },

        show : function(){
            this.node.hidden = false;
            if(this.wrap){
                this.wrap.style.display = "";
            }
        },

        onContextMenu : function(e){
            if (this.node.hasListener("contextmenu") || this.node.getOwnerTree().hasListener("contextmenu")) {
                e.preventDefault();
                this.focus();
                this.fireEvent("contextmenu", this.node, e);
            }
        },

        onClick : function(e){
            if(this.dropping){
                e.stopEvent();
                return;
            }
            if(this.fireEvent("beforeclick", this.node, e) !== false){
                var a = e.getTarget('a');
                if(!this.disabled && this.node.attributes.href && a){
                    this.fireEvent("click", this.node, e);
                    return;
                }else if(a && e.ctrlKey){
                    e.stopEvent();
                }
                e.preventDefault();
                if(this.disabled){
                    return;
                }

                if(this.node.attributes.singleClickExpand && !this.animating && this.node.hasChildNodes()){
                    this.node.toggle();
                }

                this.fireEvent("click", this.node, e);
            }else{
                e.stopEvent();
            }
        },

        onDblClick : function(e){
            e.preventDefault();
            if(this.disabled){
                return;
            }
            if(this.checkbox){
                this.toggleCheck();
            }
            if(!this.animating && this.node.hasChildNodes()){
                this.node.toggle();
            }
            this.fireEvent("dblclick", this.node, e);
        },

        onOver : function(e){
            this.addClass('x-tree-node-over');
        },

        onOut : function(e){
            this.removeClass('x-tree-node-over');
        },

        onCheckChange : function(){
            var checked = this.checkbox.checked;
            this.node.attributes.checked = checked;
            this.fireEvent('checkchange', this.node, checked);
        },

        ecClick : function(e){
            if(!this.animating && (this.node.hasChildNodes() || this.node.attributes.expandable)){
                this.node.toggle();
            }
        },

        startDrop : function(){
            this.dropping = true;
        },

        endDrop : function(){
           setTimeout(function(){
               this.dropping = false;
           }.createDelegate(this), 50);
        },

        expand : function(){
            this.updateExpandIcon();
            this.ctNode.style.display = "";
        },

        focus : function(){
            if(!this.node.preventHScroll){
                try{this.anchor.focus();
                }catch(e){}
            }else if(!Ext.isIE){
                try{
                    var noscroll = this.node.getOwnerTree().getTreeEl().dom;
                    var l = noscroll.scrollLeft;
                    this.anchor.focus();
                    noscroll.scrollLeft = l;
                }catch(e){}
            }
        },

        toggleCheck : function(value){
            var cb = this.checkbox;
            if(cb){
                cb.checked = (value === undefined ? !cb.checked : value);
            }
        },

        blur : function(){
            try{
                this.anchor.blur();
            }catch(e){}
        },

        animExpand : function(callback){
            var ct = Ext.get(this.ctNode);
            ct.stopFx();
            if(!this.node.hasChildNodes()){
                this.updateExpandIcon();
                this.ctNode.style.display = "";
                Ext.callback(callback);
                return;
            }
            this.animating = true;
            this.updateExpandIcon();

            ct.slideIn('t', {
               callback : function(){
                   this.animating = false;
                   Ext.callback(callback);
                },
                scope: this,
                duration: this.node.ownerTree.duration || .25
            });
        },

        highlight : function(){
            var tree = this.node.getOwnerTree();
            Ext.fly(this.wrap).highlight(
                tree.hlColor || "C3DAF9",
                {endColor: tree.hlBaseColor}
            );
        },

        collapse : function(){
            this.updateExpandIcon();
            this.ctNode.style.display = "none";
        },

        animCollapse : function(callback){
            var ct = Ext.get(this.ctNode);
            ct.enableDisplayMode('block');
            ct.stopFx();

            this.animating = true;
            this.updateExpandIcon();

            ct.slideOut('t', {
                callback : function(){
                   this.animating = false;
                   Ext.callback(callback);
                },
                scope: this,
                duration: this.node.ownerTree.duration || .25
            });
        },

        getContainer : function(){
            return this.ctNode;
        },

        getEl : function(){
            return this.wrap;
        },

        appendDDGhost : function(ghostNode){
            ghostNode.appendChild(this.elNode.cloneNode(true));
        },

        getDDRepairXY : function(){
            return Ext.lib.Dom.getXY(this.iconNode);
        },

        onRender : function(){
            this.render();
        },

        render : function(bulkRender){
            var n = this.node, a = n.attributes;
            var targetNode = n.parentNode ?
                  n.parentNode.ui.getContainer() : n.ownerTree.innerCt.dom;

            if(!this.rendered){
                this.rendered = true;

                this.renderElements(n, a, targetNode, bulkRender);

                if(a.qtip){
                   if(this.textNode.setAttributeNS){
                       this.textNode.setAttributeNS("ext", "qtip", a.qtip);
                       if(a.qtipTitle){
                           this.textNode.setAttributeNS("ext", "qtitle", a.qtipTitle);
                       }
                   }else{
                       this.textNode.setAttribute("ext:qtip", a.qtip);
                       if(a.qtipTitle){
                           this.textNode.setAttribute("ext:qtitle", a.qtipTitle);
                       }
                   }
                }else if(a.qtipCfg){
                    a.qtipCfg.target = Ext.id(this.textNode);
                    Ext.QuickTips.register(a.qtipCfg);
                }
                this.initEvents();
                if(!this.node.expanded){
                    this.updateExpandIcon(true);
                }
            }else{
                if(bulkRender === true) {
                    targetNode.appendChild(this.wrap);
                }
            }
        },

        renderElements : function(n, a, targetNode, bulkRender){

            this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';

            var cb = typeof a.checked == 'boolean';

            var href = a.href ? a.href : Ext.isGecko ? "" : "#";
            var buf = ['',
                '',this.indentMarkup,"",
                '',
                '',
                cb ? ('' : '/>')) : '',
                '',n.text,"",
                '',
                ""].join('');

            var nel;
            if(bulkRender !== true && n.nextSibling && (nel = n.nextSibling.ui.getEl())){
                this.wrap = Ext.DomHelper.insertHtml("beforeBegin", nel, buf);
            }else{
                this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf);
            }

            this.elNode = this.wrap.childNodes[0];
            this.ctNode = this.wrap.childNodes[1];
            var cs = this.elNode.childNodes;
            this.indentNode = cs[0];
            this.ecNode = cs[1];
            this.iconNode = cs[2];
            var index = 3;
            if(cb){
                this.checkbox = cs[3];
                index++;
            }
            this.anchor = cs[index];
            this.textNode = cs[index].firstChild;
        },

        getAnchor : function(){
            return this.anchor;
        },

        getTextEl : function(){
            return this.textNode;
        },

        getIconEl : function(){
            return this.iconNode;
        },

        isChecked : function(){
            return this.checkbox ? this.checkbox.checked : false;
        },

        updateExpandIcon : function(){
            if(this.rendered){
                var n = this.node, c1, c2;
                var cls = n.isLast() ? "x-tree-elbow-end" : "x-tree-elbow";
                var hasChild = n.hasChildNodes();
                if(hasChild || n.attributes.expandable){
                    if(n.expanded){
                        cls += "-minus";
                        c1 = "x-tree-node-collapsed";
                        c2 = "x-tree-node-expanded";
                    }else{
                        cls += "-plus";
                        c1 = "x-tree-node-expanded";
                        c2 = "x-tree-node-collapsed";
                    }
                    if(this.wasLeaf){
                        this.removeClass("x-tree-node-leaf");
                        this.wasLeaf = false;
                    }
                    if(this.c1 != c1 || this.c2 != c2){
                        Ext.fly(this.elNode).replaceClass(c1, c2);
                        this.c1 = c1; this.c2 = c2;
                    }
                }else{
                    if(!this.wasLeaf){
                        Ext.fly(this.elNode).replaceClass("x-tree-node-expanded", "x-tree-node-leaf");
                        delete this.c1;
                        delete this.c2;
                        this.wasLeaf = true;
                    }
                }
                var ecc = "x-tree-ec-icon "+cls;
                if(this.ecc != ecc){
                    this.ecNode.className = ecc;
                    this.ecc = ecc;
                }
            }
        },

        getChildIndent : function(){
            if(!this.childIndent){
                var buf = [];
                var p = this.node;
                while(p){
                    if(!p.isRoot || (p.isRoot && p.ownerTree.rootVisible)){
                        if(!p.isLast()) {
                            buf.unshift('');
                        } else {
                            buf.unshift('');
                        }
                    }
                    p = p.parentNode;
                }
                this.childIndent = buf.join("");
            }
            return this.childIndent;
        },

        renderIndent : function(){
            if(this.rendered){
                var indent = "";
                var p = this.node.parentNode;
                if(p){
                    indent = p.ui.getChildIndent();
                }
                if(this.indentMarkup != indent){
                    this.indentNode.innerHTML = indent;
                    this.indentMarkup = indent;
                }
                this.updateExpandIcon();
            }
        },

        destroy : function(){
            if(this.elNode){
                Ext.dd.Registry.unregister(this.elNode.id);
            }
            delete this.elNode;
            delete this.ctNode;
            delete this.indentNode;
            delete this.ecNode;
            delete this.iconNode;
            delete this.checkbox;
            delete this.anchor;
            delete this.textNode;
            Ext.removeNode(this.ctNode);
        }
    };

    Ext.tree.RootTreeNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {

        render : function(){
            if(!this.rendered){
                var targetNode = this.node.ownerTree.innerCt.dom;
                this.node.expanded = true;
                targetNode.innerHTML = '';
                this.wrap = this.ctNode = targetNode.firstChild;
            }
        },
        collapse : Ext.emptyFn,
        expand : Ext.emptyFn
    });

    Ext.tree.TreeLoader = function(config){
        this.baseParams = {};
        this.requestMethod = "POST";
        Ext.apply(this, config);

        this.addEvents(

            "beforeload",

            "load",

            "loadexception"
        );

        Ext.tree.TreeLoader.superclass.constructor.call(this);
    };

    Ext.extend(Ext.tree.TreeLoader, Ext.util.Observable, {

        uiProviders : {},

        clearOnLoad : true,

        load : function(node, callback){
            if(this.clearOnLoad){
                while(node.firstChild){
                    node.removeChild(node.firstChild);
                }
            }
            if(this.doPreload(node)){
                if(typeof callback == "function"){
                    callback();
                }
            }else if(this.dataUrl||this.url){
                this.requestData(node, callback);
            }
        },

        doPreload : function(node){
            if(node.attributes.children){
                if(node.childNodes.length < 1){
                    var cs = node.attributes.children;
                    node.beginUpdate();
                    for(var i = 0, len = cs.length; i < len; i++){
                        var cn = node.appendChild(this.createNode(cs[i]));
                        if(this.preloadChildren){
                            this.doPreload(cn);
                        }
                    }
                    node.endUpdate();
                }
                return true;
            }else {
                return false;
            }
        },

        getParams: function(node){
            var buf = [], bp = this.baseParams;
            for(var key in bp){
                if(typeof bp[key] != "function"){
                    buf.push(encodeURIComponent(key), "=", encodeURIComponent(bp[key]), "&");
                }
            }
            buf.push("node=", encodeURIComponent(node.id));
            return buf.join("");
        },

        requestData : function(node, callback){
            if(this.fireEvent("beforeload", this, node, callback) !== false){
                this.transId = Ext.Ajax.request({
                    method:this.requestMethod,
                    url: this.dataUrl||this.url,
                    success: this.handleResponse,
                    failure: this.handleFailure,
                    scope: this,
                    argument: {callback: callback, node: node},
                    params: this.getParams(node)
                });
            }else{

                if(typeof callback == "function"){
                    callback();
                }
            }
        },

        isLoading : function(){
            return this.transId ? true : false;
        },

        abort : function(){
            if(this.isLoading()){
                Ext.Ajax.abort(this.transId);
            }
        },

        createNode : function(attr){

            if(this.baseAttrs){
                Ext.applyIf(attr, this.baseAttrs);
            }
            if(this.applyLoader !== false){
                attr.loader = this;
            }
            if(typeof attr.uiProvider == 'string'){
               attr.uiProvider = this.uiProviders[attr.uiProvider] || eval(attr.uiProvider);
            }
            return(attr.leaf ?
                            new Ext.tree.TreeNode(attr) :
                            new Ext.tree.AsyncTreeNode(attr));
        },

        processResponse : function(response, node, callback){
            var json = response.responseText;
            try {
                var o = eval("("+json+")");
                node.beginUpdate();
                for(var i = 0, len = o.length; i < len; i++){
                    var n = this.createNode(o[i]);
                    if(n){
                        node.appendChild(n);
                    }
                }
                node.endUpdate();
                if(typeof callback == "function"){
                    callback(this, node);
                }
            }catch(e){
                this.handleFailure(response);
            }
        },

        handleResponse : function(response){
            this.transId = false;
            var a = response.argument;
            this.processResponse(response, a.node, a.callback);
            this.fireEvent("load", this, a.node, response);
        },

        handleFailure : function(response){
            this.transId = false;
            var a = response.argument;
            this.fireEvent("loadexception", this, a.node, response);
            if(typeof a.callback == "function"){
                a.callback(this, a.node);
            }
        }
    });

    Ext.tree.TreeFilter = function(tree, config){
        this.tree = tree;
        this.filtered = {};
        Ext.apply(this, config);
    };

    Ext.tree.TreeFilter.prototype = {
        clearBlank:false,
        reverse:false,
        autoClear:false,
        remove:false,

        filter : function(value, attr, startNode){
            attr = attr || "text";
            var f;
            if(typeof value == "string"){
                var vlen = value.length;

                if(vlen == 0 && this.clearBlank){
                    this.clear();
                    return;
                }
                value = value.toLowerCase();
                f = function(n){
                    return n.attributes[attr].substr(0, vlen).toLowerCase() == value;
                };
            }else if(value.exec){
                f = function(n){
                    return value.test(n.attributes[attr]);
                };
            }else{
                throw 'Illegal filter type, must be string or regex';
            }
            this.filterBy(f, null, startNode);
    	},

        filterBy : function(fn, scope, startNode){
            startNode = startNode || this.tree.root;
            if(this.autoClear){
                this.clear();
            }
            var af = this.filtered, rv = this.reverse;
            var f = function(n){
                if(n == startNode){
                    return true;
                }
                if(af[n.id]){
                    return false;
                }
                var m = fn.call(scope || n, n);
                if(!m || rv){
                    af[n.id] = n;
                    n.ui.hide();
                    return false;
                }
                return true;
            };
            startNode.cascade(f);
            if(this.remove){
               for(var id in af){
                   if(typeof id != "function"){
                       var n = af[id];
                       if(n && n.parentNode){
                           n.parentNode.removeChild(n);
                       }
                   }
               }
            }
        },

        clear : function(){
            var t = this.tree;
            var af = this.filtered;
            for(var id in af){
                if(typeof id != "function"){
                    var n = af[id];
                    if(n){
                        n.ui.show();
                    }
                }
            }
            this.filtered = {};
        }
    };

    Ext.tree.TreeSorter = function(tree, config){
        Ext.apply(this, config);
        tree.on("beforechildrenrendered", this.doSort, this);
        tree.on("append", this.updateSort, this);
        tree.on("insert", this.updateSort, this);
        tree.on("textchange", this.updateSortParent, this);

        var dsc = this.dir && this.dir.toLowerCase() == "desc";
        var p = this.property || "text";
        var sortType = this.sortType;
        var fs = this.folderSort;
        var cs = this.caseSensitive === true;
        var leafAttr = this.leafAttr || 'leaf';

        this.sortFn = function(n1, n2){
            if(fs){
                if(n1.attributes[leafAttr] && !n2.attributes[leafAttr]){
                    return 1;
                }
                if(!n1.attributes[leafAttr] && n2.attributes[leafAttr]){
                    return -1;
                }
            }
        	var v1 = sortType ? sortType(n1) : (cs ? n1.attributes[p] : n1.attributes[p].toUpperCase());
        	var v2 = sortType ? sortType(n2) : (cs ? n2.attributes[p] : n2.attributes[p].toUpperCase());
        	if(v1 < v2){
    			return dsc ? +1 : -1;
    		}else if(v1 > v2){
    			return dsc ? -1 : +1;
            }else{
    	    	return 0;
            }
        };
    };

    Ext.tree.TreeSorter.prototype = {
        doSort : function(node){
            node.sort(this.sortFn);
        },

        compareNodes : function(n1, n2){
            return (n1.text.toUpperCase() > n2.text.toUpperCase() ? 1 : -1);
        },

        updateSort : function(tree, node){
            if(node.childrenRendered){
                this.doSort.defer(1, this, [node]);
            }
        },

        updateSortParent : function(node){
    		var p = node.parentNode;
    		if(p && p.childrenRendered){
                this.doSort.defer(1, this, [p]);
            }
        }
    };

    if(Ext.dd.DropZone){

    Ext.tree.TreeDropZone = function(tree, config){

        this.allowParentInsert = false;

        this.allowContainerDrop = false;

        this.appendOnly = false;
        Ext.tree.TreeDropZone.superclass.constructor.call(this, tree.innerCt, config);

        this.tree = tree;

        this.dragOverData = {};

        this.lastInsertClass = "x-tree-no-status";
    };

    Ext.extend(Ext.tree.TreeDropZone, Ext.dd.DropZone, {

        ddGroup : "TreeDD",

        expandDelay : 1000,

        expandNode : function(node){
            if(node.hasChildNodes() && !node.isExpanded()){
                node.expand(false, null, this.triggerCacheRefresh.createDelegate(this));
            }
        },

        queueExpand : function(node){
            this.expandProcId = this.expandNode.defer(this.expandDelay, this, [node]);
        },

        cancelExpand : function(){
            if(this.expandProcId){
                clearTimeout(this.expandProcId);
                this.expandProcId = false;
            }
        },

        isValidDropPoint : function(n, pt, dd, e, data){
            if(!n || !data){ return false; }
            var targetNode = n.node;
            var dropNode = data.node;

            if(!(targetNode && targetNode.isTarget && pt)){
                return false;
            }
            if(pt == "append" && targetNode.allowChildren === false){
                return false;
            }
            if((pt == "above" || pt == "below") && (targetNode.parentNode && targetNode.parentNode.allowChildren === false)){
                return false;
            }
            if(dropNode && (targetNode == dropNode || dropNode.contains(targetNode))){
                return false;
            }

            var overEvent = this.dragOverData;
            overEvent.tree = this.tree;
            overEvent.target = targetNode;
            overEvent.data = data;
            overEvent.point = pt;
            overEvent.source = dd;
            overEvent.rawEvent = e;
            overEvent.dropNode = dropNode;
            overEvent.cancel = false;
            var result = this.tree.fireEvent("nodedragover", overEvent);
            return overEvent.cancel === false && result !== false;
        },

        getDropPoint : function(e, n, dd){
            var tn = n.node;
            if(tn.isRoot){
                return tn.allowChildren !== false ? "append" : false;
            }
            var dragEl = n.ddel;
            var t = Ext.lib.Dom.getY(dragEl), b = t + dragEl.offsetHeight;
            var y = Ext.lib.Event.getPageY(e);
            var noAppend = tn.allowChildren === false || tn.isLeaf();
            if(this.appendOnly || tn.parentNode.allowChildren === false){
                return noAppend ? false : "append";
            }
            var noBelow = false;
            if(!this.allowParentInsert){
                noBelow = tn.hasChildNodes() && tn.isExpanded();
            }
            var q = (b - t) / (noAppend ? 2 : 3);
            if(y >= t && y < (t + q)){
                return "above";
            }else if(!noBelow && (noAppend || y >= b-q && y <= b)){
                return "below";
            }else{
                return "append";
            }
        },

        onNodeEnter : function(n, dd, e, data){
            this.cancelExpand();
        },

        onNodeOver : function(n, dd, e, data){
            var pt = this.getDropPoint(e, n, dd);
            var node = n.node;

            if(!this.expandProcId && pt == "append" && node.hasChildNodes() && !n.node.isExpanded()){
                this.queueExpand(node);
            }else if(pt != "append"){
                this.cancelExpand();
            }

            var returnCls = this.dropNotAllowed;
            if(this.isValidDropPoint(n, pt, dd, e, data)){
               if(pt){
                   var el = n.ddel;
                   var cls;
                   if(pt == "above"){
                       returnCls = n.node.isFirst() ? "x-tree-drop-ok-above" : "x-tree-drop-ok-between";
                       cls = "x-tree-drag-insert-above";
                   }else if(pt == "below"){
                       returnCls = n.node.isLast() ? "x-tree-drop-ok-below" : "x-tree-drop-ok-between";
                       cls = "x-tree-drag-insert-below";
                   }else{
                       returnCls = "x-tree-drop-ok-append";
                       cls = "x-tree-drag-append";
                   }
                   if(this.lastInsertClass != cls){
                       Ext.fly(el).replaceClass(this.lastInsertClass, cls);
                       this.lastInsertClass = cls;
                   }
               }
           }
           return returnCls;
        },

        onNodeOut : function(n, dd, e, data){
            this.cancelExpand();
            this.removeDropIndicators(n);
        },

        onNodeDrop : function(n, dd, e, data){
            var point = this.getDropPoint(e, n, dd);
            var targetNode = n.node;
            targetNode.ui.startDrop();
            if(!this.isValidDropPoint(n, point, dd, e, data)){
                targetNode.ui.endDrop();
                return false;
            }

            var dropNode = data.node || (dd.getTreeNode ? dd.getTreeNode(data, targetNode, point, e) : null);
            var dropEvent = {
                tree : this.tree,
                target: targetNode,
                data: data,
                point: point,
                source: dd,
                rawEvent: e,
                dropNode: dropNode,
                cancel: !dropNode,
                dropStatus: false
            };
            var retval = this.tree.fireEvent("beforenodedrop", dropEvent);
            if(retval === false || dropEvent.cancel === true || !dropEvent.dropNode){
                targetNode.ui.endDrop();
                return dropEvent.dropStatus;
            }

            targetNode = dropEvent.target;
            if(point == "append" && !targetNode.isExpanded()){
                targetNode.expand(false, null, function(){
                    this.completeDrop(dropEvent);
                }.createDelegate(this));
            }else{
                this.completeDrop(dropEvent);
            }
            return true;
        },

        completeDrop : function(de){
            var ns = de.dropNode, p = de.point, t = de.target;
            if(!Ext.isArray(ns)){
                ns = [ns];
            }
            var n;
            for(var i = 0, len = ns.length; i < len; i++){
                n = ns[i];
                if(p == "above"){
                    t.parentNode.insertBefore(n, t);
                }else if(p == "below"){
                    t.parentNode.insertBefore(n, t.nextSibling);
                }else{
                    t.appendChild(n);
                }
            }
            n.ui.focus();
            if(this.tree.hlDrop){
                n.ui.highlight();
            }
            t.ui.endDrop();
            this.tree.fireEvent("nodedrop", de);
        },

        afterNodeMoved : function(dd, data, e, targetNode, dropNode){
            if(this.tree.hlDrop){
                dropNode.ui.focus();
                dropNode.ui.highlight();
            }
            this.tree.fireEvent("nodedrop", this.tree, targetNode, data, dd, e);
        },

        getTree : function(){
            return this.tree;
        },

        removeDropIndicators : function(n){
            if(n && n.ddel){
                var el = n.ddel;
                Ext.fly(el).removeClass([
                        "x-tree-drag-insert-above",
                        "x-tree-drag-insert-below",
                        "x-tree-drag-append"]);
                this.lastInsertClass = "_noclass";
            }
        },

        beforeDragDrop : function(target, e, id){
            this.cancelExpand();
            return true;
        },

        afterRepair : function(data){
            if(data && Ext.enableFx){
                data.node.ui.highlight();
            }
            this.hideProxy();
        }
    });

    }

    if(Ext.dd.DragZone){
    Ext.tree.TreeDragZone = function(tree, config){
        Ext.tree.TreeDragZone.superclass.constructor.call(this, tree.getTreeEl(), config);

        this.tree = tree;
    };

    Ext.extend(Ext.tree.TreeDragZone, Ext.dd.DragZone, {

        ddGroup : "TreeDD",

        onBeforeDrag : function(data, e){
            var n = data.node;
            return n && n.draggable && !n.disabled;
        },

        onInitDrag : function(e){
            var data = this.dragData;
            this.tree.getSelectionModel().select(data.node);
            this.tree.eventModel.disable();
            this.proxy.update("");
            data.node.ui.appendDDGhost(this.proxy.ghost.dom);
            this.tree.fireEvent("startdrag", this.tree, data.node, e);
        },

        getRepairXY : function(e, data){
            return data.node.ui.getDDRepairXY();
        },

        onEndDrag : function(data, e){
            this.tree.eventModel.enable.defer(100, this.tree.eventModel);
            this.tree.fireEvent("enddrag", this.tree, data.node, e);
        },

        onValidDrop : function(dd, e, id){
            this.tree.fireEvent("dragdrop", this.tree, this.dragData.node, dd, e);
            this.hideProxy();
        },

        beforeInvalidDrop : function(e, id){

            var sm = this.tree.getSelectionModel();
            sm.clearSelections();
            sm.select(this.dragData.node);
        }
    });
    }

    Ext.tree.TreeEditor = function(tree, config){
        config = config || {};
        var field = config.events ? config : new Ext.form.TextField(config);
        Ext.tree.TreeEditor.superclass.constructor.call(this, field);

        this.tree = tree;

        if(!tree.rendered){
            tree.on('render', this.initEditor, this);
        }else{
            this.initEditor(tree);
        }
    };

    Ext.extend(Ext.tree.TreeEditor, Ext.Editor, {

        alignment: "l-l",
            autoSize: false,

        hideEl : false,

        cls: "x-small-editor x-tree-editor",

        shim:false,
            shadow:"frame",

        maxWidth: 250,

        editDelay : 350,

        initEditor : function(tree){
            tree.on('beforeclick', this.beforeNodeClick, this);
            tree.on('dblclick', this.onNodeDblClick, this);
            this.on('complete', this.updateNode, this);
            this.on('beforestartedit', this.fitToTree, this);
            this.on('startedit', this.bindScroll, this, {delay:10});
            this.on('specialkey', this.onSpecialKey, this);
        },

            fitToTree : function(ed, el){
            var td = this.tree.getTreeEl().dom, nd = el.dom;
            if(td.scrollLeft >  nd.offsetLeft){             td.scrollLeft = nd.offsetLeft;
            }
            var w = Math.min(
                    this.maxWidth,
                    (td.clientWidth > 20 ? td.clientWidth : td.offsetWidth) - Math.max(0, nd.offsetLeft-td.scrollLeft) - 5);
            this.setSize(w, '');
        },

            triggerEdit : function(node, defer){
            this.completeEdit();
    		if(node.attributes.editable !== false){
    			this.editNode = node;
                this.autoEditTimer = this.startEdit.defer(this.editDelay, this, [node.ui.textNode, node.text]);
                return false;
            }
        },

            bindScroll : function(){
            this.tree.getTreeEl().on('scroll', this.cancelEdit, this);
        },

            beforeNodeClick : function(node, e){
            clearTimeout(this.autoEditTimer);
            if(this.tree.getSelectionModel().isSelected(node)){
                e.stopEvent();
                return this.triggerEdit(node);
            }
        },

        onNodeDblClick : function(node, e){
            clearTimeout(this.autoEditTimer);
        },

            updateNode : function(ed, value){
            this.tree.getTreeEl().un('scroll', this.cancelEdit, this);
            this.editNode.setText(value);
        },

            onHide : function(){
            Ext.tree.TreeEditor.superclass.onHide.call(this);
            if(this.editNode){
                this.editNode.ui.focus.defer(50, this.editNode.ui);
            }
        },

            onSpecialKey : function(field, e){
            var k = e.getKey();
            if(k == e.ESC){
                e.stopEvent();
                this.cancelEdit();
            }else if(k == e.ENTER && !e.hasModifier()){
                e.stopEvent();
                this.completeEdit();
            }
        }
    });

    Ext.menu.Menu = function(config){
        if(Ext.isArray(config)){
            config = {items:config};
        }
        Ext.apply(this, config);
        this.id = this.id || Ext.id();
        this.addEvents(

            'beforeshow',

            'beforehide',

            'show',

            'hide',

            'click',

            'mouseover',

            'mouseout',

            'itemclick'
        );
        Ext.menu.MenuMgr.register(this);
        Ext.menu.Menu.superclass.constructor.call(this);
        var mis = this.items;

        this.items = new Ext.util.MixedCollection();
        if(mis){
            this.add.apply(this, mis);
        }
    };

    Ext.extend(Ext.menu.Menu, Ext.util.Observable, {

        minWidth : 120,

        shadow : "sides",

        subMenuAlign : "tl-tr?",

        defaultAlign : "tl-bl?",

        allowOtherMenus : false,

        hidden:true,

        createEl : function(){
            return new Ext.Layer({
                cls: "x-menu",
                shadow:this.shadow,
                constrain: false,
                parentEl: this.parentEl || document.body,
                zindex:15000
            });
        },

            render : function(){
            if(this.el){
                return;
            }
            var el = this.el = this.createEl();

            if(!this.keyNav){
                this.keyNav = new Ext.menu.MenuNav(this);
            }
            if(this.plain){
                el.addClass("x-menu-plain");
            }
            if(this.cls){
                el.addClass(this.cls);
            }
                    this.focusEl = el.createChild({
                tag: "a", cls: "x-menu-focus", href: "#", onclick: "return false;", tabIndex:"-1"
            });
            var ul = el.createChild({tag: "ul", cls: "x-menu-list"});
            ul.on("click", this.onClick, this);
            ul.on("mouseover", this.onMouseOver, this);
            ul.on("mouseout", this.onMouseOut, this);
            this.items.each(function(item){
                var li = document.createElement("li");
                li.className = "x-menu-list-item";
                ul.dom.appendChild(li);
                item.render(li, this);
            }, this);
            this.ul = ul;
            this.autoWidth();
        },

            autoWidth : function(){
            var el = this.el, ul = this.ul;
            if(!el){
                return;
            }
            var w = this.width;
            if(w){
                el.setWidth(w);
            }else if(Ext.isIE){
                el.setWidth(this.minWidth);
                var t = el.dom.offsetWidth;             el.setWidth(ul.getWidth()+el.getFrameWidth("lr"));
            }
        },

            delayAutoWidth : function(){
            if(this.el){
                if(!this.awTask){
                    this.awTask = new Ext.util.DelayedTask(this.autoWidth, this);
                }
                this.awTask.delay(20);
            }
        },

            findTargetItem : function(e){
            var t = e.getTarget(".x-menu-list-item", this.ul,  true);
            if(t && t.menuItemId){
                return this.items.get(t.menuItemId);
            }
        },

            onClick : function(e){
            var t;
            if(t = this.findTargetItem(e)){
                t.onClick(e);
                this.fireEvent("click", this, t, e);
            }
        },

            setActiveItem : function(item, autoExpand){
            if(item != this.activeItem){
                if(this.activeItem){
                    this.activeItem.deactivate();
                }
                this.activeItem = item;
                item.activate(autoExpand);
            }else if(autoExpand){
                item.expandMenu();
            }
        },

            tryActivate : function(start, step){
            var items = this.items;
            for(var i = start, len = items.length; i >= 0 && i < len; i+= step){
                var item = items.get(i);
                if(!item.disabled && item.canActivate){
                    this.setActiveItem(item, false);
                    return item;
                }
            }
            return false;
        },

            onMouseOver : function(e){
            var t;
            if(t = this.findTargetItem(e)){
                if(t.canActivate && !t.disabled){
                    this.setActiveItem(t, true);
                }
            }
            this.fireEvent("mouseover", this, e, t);
        },

            onMouseOut : function(e){
            var t;
            if(t = this.findTargetItem(e)){
                if(t == this.activeItem && t.shouldDeactivate(e)){
                    this.activeItem.deactivate();
                    delete this.activeItem;
                }
            }
            this.fireEvent("mouseout", this, e, t);
        },

        isVisible : function(){
            return this.el && !this.hidden;
        },

        show : function(el, pos, parentMenu){
            this.parentMenu = parentMenu;
            if(!this.el){
                this.render();
            }
            this.fireEvent("beforeshow", this);
            this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign), parentMenu, false);
        },

        showAt : function(xy, parentMenu, _e){
            this.parentMenu = parentMenu;
            if(!this.el){
                this.render();
            }
            if(_e !== false){
                this.fireEvent("beforeshow", this);
                xy = this.el.adjustForConstraints(xy);
            }
            this.el.setXY(xy);
            this.el.show();
            this.hidden = false;
            this.focus();
            this.fireEvent("show", this);
        },

        focus : function(){
            if(!this.hidden){
                this.doFocus.defer(50, this);
            }
        },

        doFocus : function(){
            if(!this.hidden){
                this.focusEl.focus();
            }
        },

        hide : function(deep){
            if(this.el && this.isVisible()){
                this.fireEvent("beforehide", this);
                if(this.activeItem){
                    this.activeItem.deactivate();
                    this.activeItem = null;
                }
                this.el.hide();
                this.hidden = true;
                this.fireEvent("hide", this);
            }
            if(deep === true && this.parentMenu){
                this.parentMenu.hide(true);
            }
        },

        add : function(){
            var a = arguments, l = a.length, item;
            for(var i = 0; i < l; i++){
                var el = a[i];
                if(el.render){                 item = this.addItem(el);
                }else if(typeof el == "string"){                 if(el == "separator" || el == "-"){
                        item = this.addSeparator();
                    }else{
                        item = this.addText(el);
                    }
                }else if(el.tagName || el.el){                 item = this.addElement(el);
                }else if(typeof el == "object"){                 Ext.applyIf(el, this.defaults);
                    item = this.addMenuItem(el);
                }
            }
            return item;
        },

        getEl : function(){
            if(!this.el){
                this.render();
            }
            return this.el;
        },

        addSeparator : function(){
            return this.addItem(new Ext.menu.Separator());
        },

        addElement : function(el){
            return this.addItem(new Ext.menu.BaseItem(el));
        },

        addItem : function(item){
            this.items.add(item);
            if(this.ul){
                var li = document.createElement("li");
                li.className = "x-menu-list-item";
                this.ul.dom.appendChild(li);
                item.render(li, this);
                this.delayAutoWidth();
            }
            return item;
        },

        addMenuItem : function(config){
            if(!(config instanceof Ext.menu.Item)){
                if(typeof config.checked == "boolean"){                 config = new Ext.menu.CheckItem(config);
                }else{
                    config = new Ext.menu.Item(config);
                }
            }
            return this.addItem(config);
        },

        addText : function(text){
            return this.addItem(new Ext.menu.TextItem(text));
        },

        insert : function(index, item){
            this.items.insert(index, item);
            if(this.ul){
                var li = document.createElement("li");
                li.className = "x-menu-list-item";
                this.ul.dom.insertBefore(li, this.ul.dom.childNodes[index]);
                item.render(li, this);
                this.delayAutoWidth();
            }
            return item;
        },

        remove : function(item){
            this.items.removeKey(item.id);
            item.destroy();
        },

        removeAll : function(){
            var f;
            while(f = this.items.first()){
                this.remove(f);
            }
        },

        destroy : function(){
            this.beforeDestroy();
            Ext.menu.MenuMgr.unregister(this);
            if (this.keyNav) {
            	this.keyNav.disable();
            }
            this.removeAll();
            if (this.ul) {
            	this.ul.removeAllListeners();
            }
            if (this.el) {
            	this.el.destroy();
            }
        },

    	    beforeDestroy : Ext.emptyFn

    });

    Ext.menu.MenuNav = function(menu){
        Ext.menu.MenuNav.superclass.constructor.call(this, menu.el);
        this.scope = this.menu = menu;
    };

    Ext.extend(Ext.menu.MenuNav, Ext.KeyNav, {
        doRelay : function(e, h){
            var k = e.getKey();
            if(!this.menu.activeItem && e.isNavKeyPress() && k != e.SPACE && k != e.RETURN){
                this.menu.tryActivate(0, 1);
                return false;
            }
            return h.call(this.scope || this, e, this.menu);
        },

        up : function(e, m){
            if(!m.tryActivate(m.items.indexOf(m.activeItem)-1, -1)){
                m.tryActivate(m.items.length-1, -1);
            }
        },

        down : function(e, m){
            if(!m.tryActivate(m.items.indexOf(m.activeItem)+1, 1)){
                m.tryActivate(0, 1);
            }
        },

        right : function(e, m){
            if(m.activeItem){
                m.activeItem.expandMenu(true);
            }
        },

        left : function(e, m){
            m.hide();
            if(m.parentMenu && m.parentMenu.activeItem){
                m.parentMenu.activeItem.activate();
            }
        },

        enter : function(e, m){
            if(m.activeItem){
                e.stopPropagation();
                m.activeItem.onClick(e);
                m.fireEvent("click", this, m.activeItem);
                return true;
            }
        }
    });

    Ext.menu.MenuMgr = function(){
       var menus, active, groups = {}, attached = false, lastShow = new Date();

          function init(){
           menus = {};
           active = new Ext.util.MixedCollection();
           Ext.getDoc().addKeyListener(27, function(){
               if(active.length > 0){
                   hideAll();
               }
           });
       }

          function hideAll(){
           if(active && active.length > 0){
               var c = active.clone();
               c.each(function(m){
                   m.hide();
               });
           }
       }

          function onHide(m){
           active.remove(m);
           if(active.length < 1){
               Ext.getDoc().un("mousedown", onMouseDown);
               attached = false;
           }
       }

          function onShow(m){
           var last = active.last();
           lastShow = new Date();
           active.add(m);
           if(!attached){
               Ext.getDoc().on("mousedown", onMouseDown);
               attached = true;
           }
           if(m.parentMenu){
              m.getEl().setZIndex(parseInt(m.parentMenu.getEl().getStyle("z-index"), 10) + 3);
              m.parentMenu.activeChild = m;
           }else if(last && last.isVisible()){
              m.getEl().setZIndex(parseInt(last.getEl().getStyle("z-index"), 10) + 3);
           }
       }

          function onBeforeHide(m){
           if(m.activeChild){
               m.activeChild.hide();
           }
           if(m.autoHideTimer){
               clearTimeout(m.autoHideTimer);
               delete m.autoHideTimer;
           }
       }

          function onBeforeShow(m){
           var pm = m.parentMenu;
           if(!pm && !m.allowOtherMenus){
               hideAll();
           }else if(pm && pm.activeChild){
               pm.activeChild.hide();
           }
       }

          function onMouseDown(e){
           if(lastShow.getElapsed() > 50 && active.length > 0 && !e.getTarget(".x-menu")){
               hideAll();
           }
       }

          function onBeforeCheck(mi, state){
           if(state){
               var g = groups[mi.group];
               for(var i = 0, l = g.length; i < l; i++){
                   if(g[i] != mi){
                       g[i].setChecked(false);
                   }
               }
           }
       }

       return {

           hideAll : function(){
                hideAll();
           },

                  register : function(menu){
               if(!menus){
                   init();
               }
               menus[menu.id] = menu;
               menu.on("beforehide", onBeforeHide);
               menu.on("hide", onHide);
               menu.on("beforeshow", onBeforeShow);
               menu.on("show", onShow);
               var g = menu.group;
               if(g && menu.events["checkchange"]){
                   if(!groups[g]){
                       groups[g] = [];
                   }
                   groups[g].push(menu);
                   menu.on("checkchange", onCheck);
               }
           },

           get : function(menu){
               if(typeof menu == "string"){                if(!menus){                     return null;
                   }
                   return menus[menu];
               }else if(menu.events){                 return menu;
               }else if(typeof menu.length == 'number'){                return new Ext.menu.Menu({items:menu});
               }else{                return new Ext.menu.Menu(menu);
               }
           },

                  unregister : function(menu){
               delete menus[menu.id];
               menu.un("beforehide", onBeforeHide);
               menu.un("hide", onHide);
               menu.un("beforeshow", onBeforeShow);
               menu.un("show", onShow);
               var g = menu.group;
               if(g && menu.events["checkchange"]){
                   groups[g].remove(menu);
                   menu.un("checkchange", onCheck);
               }
           },

                  registerCheckable : function(menuItem){
               var g = menuItem.group;
               if(g){
                   if(!groups[g]){
                       groups[g] = [];
                   }
                   groups[g].push(menuItem);
                   menuItem.on("beforecheckchange", onBeforeCheck);
               }
           },

                  unregisterCheckable : function(menuItem){
               var g = menuItem.group;
               if(g){
                   groups[g].remove(menuItem);
                   menuItem.un("beforecheckchange", onBeforeCheck);
               }
           },

           getCheckedItem : function(groupId){
               var g = groups[groupId];
               if(g){
                   for(var i = 0, l = g.length; i < l; i++){
                       if(g[i].checked){
                           return g[i];
                       }
                   }
               }
               return null;
           },

           setCheckedItem : function(groupId, itemId){
               var g = groups[groupId];
               if(g){
                   for(var i = 0, l = g.length; i < l; i++){
                       if(g[i].id == itemId){
                           g[i].setChecked(true);
                       }
                   }
               }
               return null;
           }
       };
    }();

    Ext.menu.BaseItem = function(config){
        Ext.menu.BaseItem.superclass.constructor.call(this, config);

        this.addEvents(

            'click',

            'activate',

            'deactivate'
        );

        if(this.handler){
            this.on("click", this.handler, this.scope);
        }
    };

    Ext.extend(Ext.menu.BaseItem, Ext.Component, {

        canActivate : false,

        activeClass : "x-menu-item-active",

        hideOnClick : true,

        hideDelay : 100,

            ctype: "Ext.menu.BaseItem",

            actionMode : "container",

            render : function(container, parentMenu){
            this.parentMenu = parentMenu;
            Ext.menu.BaseItem.superclass.render.call(this, container);
            this.container.menuItemId = this.id;
        },

            onRender : function(container, position){
            this.el = Ext.get(this.el);
            container.dom.appendChild(this.el.dom);
        },

        setHandler : function(handler, scope){
            if(this.handler){
                this.un("click", this.handler, this.scope);
            }
            this.on("click", this.handler = handler, this.scope = scope);
        },

            onClick : function(e){
            if(!this.disabled && this.fireEvent("click", this, e) !== false
                    && this.parentMenu.fireEvent("itemclick", this, e) !== false){
                this.handleClick(e);
            }else{
                e.stopEvent();
            }
        },

            activate : function(){
            if(this.disabled){
                return false;
            }
            var li = this.container;
            li.addClass(this.activeClass);
            this.region = li.getRegion().adjust(2, 2, -2, -2);
            this.fireEvent("activate", this);
            return true;
        },

            deactivate : function(){
            this.container.removeClass(this.activeClass);
            this.fireEvent("deactivate", this);
        },

            shouldDeactivate : function(e){
            return !this.region || !this.region.contains(e.getPoint());
        },

            handleClick : function(e){
            if(this.hideOnClick){
                this.parentMenu.hide.defer(this.hideDelay, this.parentMenu, [true]);
            }
        },

            expandMenu : function(autoActivate){
                },

            hideMenu : function(){
                }
    });

    Ext.menu.TextItem = function(text){
        this.text = text;
        Ext.menu.TextItem.superclass.constructor.call(this);
    };

    Ext.extend(Ext.menu.TextItem, Ext.menu.BaseItem, {

        hideOnClick : false,

        itemCls : "x-menu-text",

            onRender : function(){
            var s = document.createElement("span");
            s.className = this.itemCls;
            s.innerHTML = this.text;
            this.el = s;
            Ext.menu.TextItem.superclass.onRender.apply(this, arguments);
        }
    });

    Ext.menu.Separator = function(config){
        Ext.menu.Separator.superclass.constructor.call(this, config);
    };

    Ext.extend(Ext.menu.Separator, Ext.menu.BaseItem, {

        itemCls : "x-menu-sep",

        hideOnClick : false,

            onRender : function(li){
            var s = document.createElement("span");
            s.className = this.itemCls;
            s.innerHTML = " ";
            this.el = s;
            li.addClass("x-menu-sep-li");
            Ext.menu.Separator.superclass.onRender.apply(this, arguments);
        }
    });

    Ext.menu.Item = function(config){
        Ext.menu.Item.superclass.constructor.call(this, config);
        if(this.menu){
            this.menu = Ext.menu.MenuMgr.get(this.menu);
        }
    };
    Ext.extend(Ext.menu.Item, Ext.menu.BaseItem, {

        itemCls : "x-menu-item",

        canActivate : true,

        showDelay: 200,
            hideDelay: 200,

            ctype: "Ext.menu.Item",

            onRender : function(container, position){
            var el = document.createElement("a");
            el.hideFocus = true;
            el.unselectable = "on";
            el.href = this.href || "#";
            if(this.hrefTarget){
                el.target = this.hrefTarget;
            }
            el.className = this.itemCls + (this.menu ?  " x-menu-item-arrow" : "") + (this.cls ?  " " + this.cls : "");
            el.innerHTML = String.format(
                    '{1}',
                    this.icon || Ext.BLANK_IMAGE_URL, this.itemText||this.text, this.iconCls || '');
            this.el = el;
            Ext.menu.Item.superclass.onRender.call(this, container, position);
        },

        setText : function(text){
            this.text = text;
            if(this.rendered){
                this.el.update(String.format(
                    '{1}',
                    this.icon || Ext.BLANK_IMAGE_URL, this.text, this.iconCls || ''));
                this.parentMenu.autoWidth();
            }
        },

        setIconClass : function(cls){
            var oldCls = this.iconCls;
            this.iconCls = cls;
            if(this.rendered){
                this.el.child('img.x-menu-item-icon').replaceClass(oldCls, this.iconCls);
            }
        },

            handleClick : function(e){
            if(!this.href){             e.stopEvent();
            }
            Ext.menu.Item.superclass.handleClick.apply(this, arguments);
        },

            activate : function(autoExpand){
            if(Ext.menu.Item.superclass.activate.apply(this, arguments)){
                this.focus();
                if(autoExpand){
                    this.expandMenu();
                }
            }
            return true;
        },

            shouldDeactivate : function(e){
            if(Ext.menu.Item.superclass.shouldDeactivate.call(this, e)){
                if(this.menu && this.menu.isVisible()){
                    return !this.menu.getEl().getRegion().contains(e.getPoint());
                }
                return true;
            }
            return false;
        },

            deactivate : function(){
            Ext.menu.Item.superclass.deactivate.apply(this, arguments);
            this.hideMenu();
        },

            expandMenu : function(autoActivate){
            if(!this.disabled && this.menu){
                clearTimeout(this.hideTimer);
                delete this.hideTimer;
                if(!this.menu.isVisible() && !this.showTimer){
                    this.showTimer = this.deferExpand.defer(this.showDelay, this, [autoActivate]);
                }else if (this.menu.isVisible() && autoActivate){
                    this.menu.tryActivate(0, 1);
                }
            }
        },

            deferExpand : function(autoActivate){
            delete this.showTimer;
            this.menu.show(this.container, this.parentMenu.subMenuAlign || "tl-tr?", this.parentMenu);
            if(autoActivate){
                this.menu.tryActivate(0, 1);
            }
        },

            hideMenu : function(){
            clearTimeout(this.showTimer);
            delete this.showTimer;
            if(!this.hideTimer && this.menu && this.menu.isVisible()){
                this.hideTimer = this.deferHide.defer(this.hideDelay, this);
            }
        },

            deferHide : function(){
            delete this.hideTimer;
            this.menu.hide();
        }
    });

    Ext.menu.CheckItem = function(config){
        Ext.menu.CheckItem.superclass.constructor.call(this, config);
        this.addEvents(

            "beforecheckchange" ,

            "checkchange"
        );

        if(this.checkHandler){
            this.on('checkchange', this.checkHandler, this.scope);
        }
        Ext.menu.MenuMgr.registerCheckable(this);
    };
    Ext.extend(Ext.menu.CheckItem, Ext.menu.Item, {

        itemCls : "x-menu-item x-menu-check-item",

        groupClass : "x-menu-group-item",

        checked: false,

            ctype: "Ext.menu.CheckItem",

            onRender : function(c){
            Ext.menu.CheckItem.superclass.onRender.apply(this, arguments);
            if(this.group){
                this.el.addClass(this.groupClass);
            }
            if(this.checked){
                this.checked = false;
                this.setChecked(true, true);
            }
        },

            destroy : function(){
            Ext.menu.MenuMgr.unregisterCheckable(this);
            Ext.menu.CheckItem.superclass.destroy.apply(this, arguments);
        },

        setChecked : function(state, suppressEvent){
            if(this.checked != state && this.fireEvent("beforecheckchange", this, state) !== false){
                if(this.container){
                    this.container[state ? "addClass" : "removeClass"]("x-menu-item-checked");
                }
                this.checked = state;
                if(suppressEvent !== true){
                    this.fireEvent("checkchange", this, state);
                }
            }
        },

            handleClick : function(e){
           if(!this.disabled && !(this.checked && this.group)){           this.setChecked(!this.checked);
           }
           Ext.menu.CheckItem.superclass.handleClick.apply(this, arguments);
        }
    });

    Ext.menu.Adapter = function(component, config){
        Ext.menu.Adapter.superclass.constructor.call(this, config);
        this.component = component;
    };
    Ext.extend(Ext.menu.Adapter, Ext.menu.BaseItem, {
            canActivate : true,

            onRender : function(container, position){
            this.component.render(container);
            this.el = this.component.getEl();
        },

            activate : function(){
            if(this.disabled){
                return false;
            }
            this.component.focus();
            this.fireEvent("activate", this);
            return true;
        },

            deactivate : function(){
            this.fireEvent("deactivate", this);
        },

            disable : function(){
            this.component.disable();
            Ext.menu.Adapter.superclass.disable.call(this);
        },

            enable : function(){
            this.component.enable();
            Ext.menu.Adapter.superclass.enable.call(this);
        }
    });

    Ext.menu.DateItem = function(config){
        Ext.menu.DateItem.superclass.constructor.call(this, new Ext.DatePicker(config), config);

        this.picker = this.component;
        this.addEvents('select');

        this.picker.on("render", function(picker){
            picker.getEl().swallowEvent("click");
            picker.container.addClass("x-menu-date-item");
        });

        this.picker.on("select", this.onSelect, this);
    };

    Ext.extend(Ext.menu.DateItem, Ext.menu.Adapter, {
            onSelect : function(picker, date){
            this.fireEvent("select", this, date, picker);
            Ext.menu.DateItem.superclass.handleClick.call(this);
        }
    });

    Ext.menu.ColorItem = function(config){
        Ext.menu.ColorItem.superclass.constructor.call(this, new Ext.ColorPalette(config), config);

        this.palette = this.component;
        this.relayEvents(this.palette, ["select"]);
        if(this.selectHandler){
            this.on('select', this.selectHandler, this.scope);
        }
    };
    Ext.extend(Ext.menu.ColorItem, Ext.menu.Adapter);

    Ext.menu.DateMenu = function(config){
        Ext.menu.DateMenu.superclass.constructor.call(this, config);
        this.plain = true;
        var di = new Ext.menu.DateItem(config);
        this.add(di);

        this.picker = di.picker;

        this.relayEvents(di, ["select"]);

        this.on('beforeshow', function(){
            if(this.picker){
                this.picker.hideMonthPicker(true);
            }
        }, this);
    };
    Ext.extend(Ext.menu.DateMenu, Ext.menu.Menu, {
        cls:'x-date-menu',

            beforeDestroy : function() {
            this.picker.destroy();
        }
    });

    Ext.menu.ColorMenu = function(config){
        Ext.menu.ColorMenu.superclass.constructor.call(this, config);
        this.plain = true;
        var ci = new Ext.menu.ColorItem(config);
        this.add(ci);

        this.palette = ci.palette;

        this.relayEvents(ci, ["select"]);
    };
    Ext.extend(Ext.menu.ColorMenu, Ext.menu.Menu);

    Ext.form.Field = Ext.extend(Ext.BoxComponent,  {

        invalidClass : "x-form-invalid",

        invalidText : "The value in this field is invalid",

        focusClass : "x-form-focus",

        validationEvent : "keyup",

        validateOnBlur : true,

        validationDelay : 250,

        defaultAutoCreate : {tag: "input", type: "text", size: "20", autocomplete: "off"},

        fieldClass : "x-form-field",

        msgTarget : 'qtip',

        msgFx : 'normal',

        readOnly : false,

        disabled : false,

            isFormField : true,

            hasFocus : false,

    		initComponent : function(){
            Ext.form.Field.superclass.initComponent.call(this);
            this.addEvents(

                'focus',

                'blur',

                'specialkey',

                'change',

                'invalid',

                'valid'
            );
        },

        getName: function(){
             return this.rendered && this.el.dom.name ? this.el.dom.name : (this.hiddenName || '');
        },

            onRender : function(ct, position){
            Ext.form.Field.superclass.onRender.call(this, ct, position);
            if(!this.el){
                var cfg = this.getAutoCreate();
                if(!cfg.name){
                    cfg.name = this.name || this.id;
                }
                if(this.inputType){
                    cfg.type = this.inputType;
                }
                this.el = ct.createChild(cfg, position);
            }
            var type = this.el.dom.type;
            if(type){
                if(type == 'password'){
                    type = 'text';
                }
                this.el.addClass('x-form-'+type);
            }
            if(this.readOnly){
                this.el.dom.readOnly = true;
            }
            if(this.tabIndex !== undefined){
                this.el.dom.setAttribute('tabIndex', this.tabIndex);
            }

            this.el.addClass([this.fieldClass, this.cls]);
            this.initValue();
        },

            initValue : function(){
            if(this.value !== undefined){
                this.setValue(this.value);
            }else if(this.el.dom.value.length > 0){
                this.setValue(this.el.dom.value);
            }
        },

        isDirty : function() {
            if(this.disabled) {
                return false;
            }
            return String(this.getValue()) !== String(this.originalValue);
        },

            afterRender : function(){
            Ext.form.Field.superclass.afterRender.call(this);
            this.initEvents();
        },

            fireKey : function(e){
            if(e.isSpecialKey()){
                this.fireEvent("specialkey", this, e);
            }
        },

        reset : function(){
            this.setValue(this.originalValue);
            this.clearInvalid();
        },

            initEvents : function(){
            this.el.on(Ext.isIE ? "keydown" : "keypress", this.fireKey,  this);
            this.el.on("focus", this.onFocus,  this);
            this.el.on("blur", this.onBlur,  this);

                    this.originalValue = this.getValue();
        },

            onFocus : function(){
            if(!Ext.isOpera && this.focusClass){             this.el.addClass(this.focusClass);
            }
            if(!this.hasFocus){
                this.hasFocus = true;
                this.startValue = this.getValue();
                this.fireEvent("focus", this);
            }
        },

        beforeBlur : Ext.emptyFn,

            onBlur : function(){
            this.beforeBlur();
            if(!Ext.isOpera && this.focusClass){             this.el.removeClass(this.focusClass);
            }
            this.hasFocus = false;
            if(this.validationEvent !== false && this.validateOnBlur && this.validationEvent != "blur"){
                this.validate();
            }
            var v = this.getValue();
            if(String(v) !== String(this.startValue)){
                this.fireEvent('change', this, v, this.startValue);
            }
            this.fireEvent("blur", this);
        },

        isValid : function(preventMark){
            if(this.disabled){
                return true;
            }
            var restore = this.preventMark;
            this.preventMark = preventMark === true;
            var v = this.validateValue(this.processValue(this.getRawValue()));
            this.preventMark = restore;
            return v;
        },

        validate : function(){
            if(this.disabled || this.validateValue(this.processValue(this.getRawValue()))){
                this.clearInvalid();
                return true;
            }
            return false;
        },

        processValue : function(value){
            return value;
        },

                validateValue : function(value){
            return true;
        },

        markInvalid : function(msg){
            if(!this.rendered || this.preventMark){             return;
            }
            this.el.addClass(this.invalidClass);
            msg = msg || this.invalidText;
            switch(this.msgTarget){
                case 'qtip':
                    this.el.dom.qtip = msg;
                    this.el.dom.qclass = 'x-form-invalid-tip';
                    if(Ext.QuickTips){                     Ext.QuickTips.enable();
                    }
                    break;
                case 'title':
                    this.el.dom.title = msg;
                    break;
                case 'under':
                    if(!this.errorEl){
                        var elp = this.el.findParent('.x-form-element', 5, true);
                        this.errorEl = elp.createChild({cls:'x-form-invalid-msg'});
                        this.errorEl.setWidth(elp.getWidth(true)-20);
                    }
                    this.errorEl.update(msg);
                    Ext.form.Field.msgFx[this.msgFx].show(this.errorEl, this);
                    break;
                case 'side':
                    if(!this.errorIcon){
                        var elp = this.el.findParent('.x-form-element', 5, true);
                        this.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});
                    }
                    this.alignErrorIcon();
                    this.errorIcon.dom.qtip = msg;
                    this.errorIcon.dom.qclass = 'x-form-invalid-tip';
                    this.errorIcon.show();
                    this.on('resize', this.alignErrorIcon, this);
                    break;
                default:
                    var t = Ext.getDom(this.msgTarget);
                    t.innerHTML = msg;
                    t.style.display = this.msgDisplay;
                    break;
            }
            this.fireEvent('invalid', this, msg);
        },

            alignErrorIcon : function(){
            this.errorIcon.alignTo(this.el, 'tl-tr', [2, 0]);
        },

        clearInvalid : function(){
            if(!this.rendered || this.preventMark){             return;
            }
            this.el.removeClass(this.invalidClass);
            switch(this.msgTarget){
                case 'qtip':
                    this.el.dom.qtip = '';
                    break;
                case 'title':
                    this.el.dom.title = '';
                    break;
                case 'under':
                    if(this.errorEl){
                        Ext.form.Field.msgFx[this.msgFx].hide(this.errorEl, this);
                    }
                    break;
                case 'side':
                    if(this.errorIcon){
                        this.errorIcon.dom.qtip = '';
                        this.errorIcon.hide();
                        this.un('resize', this.alignErrorIcon, this);
                    }
                    break;
                default:
                    var t = Ext.getDom(this.msgTarget);
                    t.innerHTML = '';
                    t.style.display = 'none';
                    break;
            }
            this.fireEvent('valid', this);
        },

        getRawValue : function(){
            var v = this.rendered ? this.el.getValue() : Ext.value(this.value, '');
            if(v === this.emptyText){
                v = '';
            }
            return v;
        },

        getValue : function(){
            if(!this.rendered) {
                return this.value;
            }
            var v = this.el.getValue();
            if(v === this.emptyText || v === undefined){
                v = '';
            }
            return v;
        },

        setRawValue : function(v){
            return this.el.dom.value = (v === null || v === undefined ? '' : v);
        },

        setValue : function(v){
            this.value = v;
            if(this.rendered){
                this.el.dom.value = (v === null || v === undefined ? '' : v);
                this.validate();
            }
        },

        adjustSize : function(w, h){
            var s = Ext.form.Field.superclass.adjustSize.call(this, w, h);
            s.width = this.adjustWidth(this.el.dom.tagName, s.width);
            return s;
        },

        adjustWidth : function(tag, w){
            tag = tag.toLowerCase();
            if(typeof w == 'number' && !Ext.isSafari){
                if(Ext.isIE && (tag == 'input' || tag == 'textarea')){
                    if(tag == 'input' && !Ext.isStrict){
                        return this.inEditor ? w : w - 3;
                    }
                    if(tag == 'input' && Ext.isStrict){
                        return w - (Ext.isIE6 ? 4 : 1);
                    }
                    if(tag = 'textarea' && Ext.isStrict){
                        return w-2;
                    }
                }else if(Ext.isOpera && Ext.isStrict){
                    if(tag == 'input'){
                        return w + 2;
                    }
                    if(tag = 'textarea'){
                        return w-2;
                    }
                }
            }
            return w;
        }

    });

    Ext.form.Field.msgFx = {
        normal : {
            show: function(msgEl, f){
                msgEl.setDisplayed('block');
            },

            hide : function(msgEl, f){
                msgEl.setDisplayed(false).update('');
            }
        },

        slide : {
            show: function(msgEl, f){
                msgEl.slideIn('t', {stopFx:true});
            },

            hide : function(msgEl, f){
                msgEl.slideOut('t', {stopFx:true,useDisplay:true});
            }
        },

        slideRight : {
            show: function(msgEl, f){
                msgEl.fixDisplay();
                msgEl.alignTo(f.el, 'tl-tr');
                msgEl.slideIn('l', {stopFx:true});
            },

            hide : function(msgEl, f){
                msgEl.slideOut('l', {stopFx:true,useDisplay:true});
            }
        }
    };
    Ext.reg('field', Ext.form.Field);

    Ext.form.TextField = Ext.extend(Ext.form.Field,  {

        grow : false,

        growMin : 30,

        growMax : 800,

        vtype : null,

        maskRe : null,

        disableKeyFilter : false,

        allowBlank : true,

        minLength : 0,

        maxLength : Number.MAX_VALUE,

        minLengthText : "The minimum length for this field is {0}",

        maxLengthText : "The maximum length for this field is {0}",

        selectOnFocus : false,

        blankText : "This field is required",

        validator : null,

        regex : null,

        regexText : "",

        emptyText : null,

        emptyClass : 'x-form-empty-field',

        initComponent : function(){
            Ext.form.TextField.superclass.initComponent.call(this);
            this.addEvents(

                'autosize'
            );
        },

            initEvents : function(){
            Ext.form.TextField.superclass.initEvents.call(this);
            if(this.validationEvent == 'keyup'){
                this.validationTask = new Ext.util.DelayedTask(this.validate, this);
                this.el.on('keyup', this.filterValidation, this);
            }
            else if(this.validationEvent !== false){
                this.el.on(this.validationEvent, this.validate, this, {buffer: this.validationDelay});
            }
            if(this.selectOnFocus || this.emptyText){
                this.on("focus", this.preFocus, this);
                if(this.emptyText){
                    this.on('blur', this.postBlur, this);
                    this.applyEmptyText();
                }
            }
            if(this.maskRe || (this.vtype && this.disableKeyFilter !== true && (this.maskRe = Ext.form.VTypes[this.vtype+'Mask']))){
                this.el.on("keypress", this.filterKeys, this);
            }
            if(this.grow){
                this.el.on("keyup", this.onKeyUp,  this, {buffer:50});
                this.el.on("click", this.autoSize,  this);
            }
        },

        processValue : function(value){
            if(this.stripCharsRe){
                var newValue = value.replace(this.stripCharsRe, '');
                if(newValue !== value){
                    this.setRawValue(newValue);
                    return newValue;
                }
            }
            return value;
        },

        filterValidation : function(e){
            if(!e.isNavKeyPress()){
                this.validationTask.delay(this.validationDelay);
            }
        },

            onKeyUp : function(e){
            if(!e.isNavKeyPress()){
                this.autoSize();
            }
        },

        reset : function(){
            Ext.form.TextField.superclass.reset.call(this);
            this.applyEmptyText();
        },

        applyEmptyText : function(){
            if(this.rendered && this.emptyText && this.getRawValue().length < 1){
                this.setRawValue(this.emptyText);
                this.el.addClass(this.emptyClass);
            }
        },

            preFocus : function(){
            if(this.emptyText){
                if(this.el.dom.value == this.emptyText){
                    this.setRawValue('');
                }
                this.el.removeClass(this.emptyClass);
            }
            if(this.selectOnFocus){
                this.el.dom.select();
            }
        },

            postBlur : function(){
            this.applyEmptyText();
        },

            filterKeys : function(e){
            var k = e.getKey();
            if(!Ext.isIE && (e.isNavKeyPress() || k == e.BACKSPACE || (k == e.DELETE && e.button == -1))){
                return;
            }
            var c = e.getCharCode(), cc = String.fromCharCode(c);
            if(Ext.isIE && (e.isSpecialKey() || !cc)){
                return;
            }
            if(!this.maskRe.test(cc)){
                e.stopEvent();
            }
        },

        setValue : function(v){
            if(this.emptyText && this.el && v !== undefined && v !== null && v !== ''){
                this.el.removeClass(this.emptyClass);
            }
            Ext.form.TextField.superclass.setValue.apply(this, arguments);
            this.applyEmptyText();
            this.autoSize();
        },

        validateValue : function(value){
            if(value.length < 1 || value === this.emptyText){              if(this.allowBlank){
                     this.clearInvalid();
                     return true;
                 }else{
                     this.markInvalid(this.blankText);
                     return false;
                 }
            }
            if(value.length < this.minLength){
                this.markInvalid(String.format(this.minLengthText, this.minLength));
                return false;
            }
            if(value.length > this.maxLength){
                this.markInvalid(String.format(this.maxLengthText, this.maxLength));
                return false;
            }
            if(this.vtype){
                var vt = Ext.form.VTypes;
                if(!vt[this.vtype](value, this)){
                    this.markInvalid(this.vtypeText || vt[this.vtype +'Text']);
                    return false;
                }
            }
            if(typeof this.validator == "function"){
                var msg = this.validator(value);
                if(msg !== true){
                    this.markInvalid(msg);
                    return false;
                }
            }
            if(this.regex && !this.regex.test(value)){
                this.markInvalid(this.regexText);
                return false;
            }
            return true;
        },

        selectText : function(start, end){
            var v = this.getRawValue();
            if(v.length > 0){
                start = start === undefined ? 0 : start;
                end = end === undefined ? v.length : end;
                var d = this.el.dom;
                if(d.setSelectionRange){
                    d.setSelectionRange(start, end);
                }else if(d.createTextRange){
                    var range = d.createTextRange();
                    range.moveStart("character", start);
                    range.moveEnd("character", end-v.length);
                    range.select();
                }
            }
        },

        autoSize : function(){
            if(!this.grow || !this.rendered){
                return;
            }
            if(!this.metrics){
                this.metrics = Ext.util.TextMetrics.createInstance(this.el);
            }
            var el = this.el;
            var v = el.dom.value;
            var d = document.createElement('div');
            d.appendChild(document.createTextNode(v));
            v = d.innerHTML;
            d = null;
            v += " ";
            var w = Math.min(this.growMax, Math.max(this.metrics.getWidth(v) +  10, this.growMin));
            this.el.setWidth(w);
            this.fireEvent("autosize", this, w);
        }
    });
    Ext.reg('textfield', Ext.form.TextField);

    Ext.form.TriggerField = Ext.extend(Ext.form.TextField,  {

        defaultAutoCreate : {tag: "input", type: "text", size: "16", autocomplete: "off"},

        hideTrigger:false,

        autoSize: Ext.emptyFn,
            monitorTab : true,
            deferHeight : true,
            mimicing : false,

            onResize : function(w, h){
            Ext.form.TriggerField.superclass.onResize.call(this, w, h);
            if(typeof w == 'number'){
                this.el.setWidth(this.adjustWidth('input', w - this.trigger.getWidth()));
            }
            this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth());
        },

            adjustSize : Ext.BoxComponent.prototype.adjustSize,

            getResizeEl : function(){
            return this.wrap;
        },

            getPositionEl : function(){
            return this.wrap;
        },

            alignErrorIcon : function(){
            this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);
        },

            onRender : function(ct, position){
            Ext.form.TriggerField.superclass.onRender.call(this, ct, position);
            this.wrap = this.el.wrap({cls: "x-form-field-wrap"});
            this.trigger = this.wrap.createChild(this.triggerConfig ||
                    {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.triggerClass});
            if(this.hideTrigger){
                this.trigger.setDisplayed(false);
            }
            this.initTrigger();
            if(!this.width){
                this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth());
            }
        },

            initTrigger : function(){
            this.trigger.on("click", this.onTriggerClick, this, {preventDefault:true});
            this.trigger.addClassOnOver('x-form-trigger-over');
            this.trigger.addClassOnClick('x-form-trigger-click');
        },

            onDestroy : function(){
            if(this.trigger){
                this.trigger.removeAllListeners();
                this.trigger.remove();
            }
            if(this.wrap){
                this.wrap.remove();
            }
            Ext.form.TriggerField.superclass.onDestroy.call(this);
        },

            onFocus : function(){
            Ext.form.TriggerField.superclass.onFocus.call(this);
            if(!this.mimicing){
                this.wrap.addClass('x-trigger-wrap-focus');
                this.mimicing = true;
                Ext.get(Ext.isIE ? document.body : document).on("mousedown", this.mimicBlur, this, {delay: 10});
                if(this.monitorTab){
                    this.el.on("keydown", this.checkTab, this);
                }
            }
        },

            checkTab : function(e){
            if(e.getKey() == e.TAB){
                this.triggerBlur();
            }
        },

            onBlur : function(){
                },

            mimicBlur : function(e){
            if(!this.wrap.contains(e.target) && this.validateBlur(e)){
                this.triggerBlur();
            }
        },

            triggerBlur : function(){
            this.mimicing = false;
            Ext.get(Ext.isIE ? document.body : document).un("mousedown", this.mimicBlur);
            if(this.monitorTab){
                this.el.un("keydown", this.checkTab, this);
            }
            this.beforeBlur();
            this.wrap.removeClass('x-trigger-wrap-focus');
            Ext.form.TriggerField.superclass.onBlur.call(this);
        },

        beforeBlur : Ext.emptyFn,

                validateBlur : function(e){
            return true;
        },

            onDisable : function(){
            Ext.form.TriggerField.superclass.onDisable.call(this);
            if(this.wrap){
                this.wrap.addClass('x-item-disabled');
            }
        },

            onEnable : function(){
            Ext.form.TriggerField.superclass.onEnable.call(this);
            if(this.wrap){
                this.wrap.removeClass('x-item-disabled');
            }
        },

            onShow : function(){
            if(this.wrap){
                this.wrap.dom.style.display = '';
                this.wrap.dom.style.visibility = 'visible';
            }
        },

            onHide : function(){
            this.wrap.dom.style.display = 'none';
        },

        onTriggerClick : Ext.emptyFn

    });

    Ext.form.TwinTriggerField = Ext.extend(Ext.form.TriggerField, {
        initComponent : function(){
            Ext.form.TwinTriggerField.superclass.initComponent.call(this);

            this.triggerConfig = {
                tag:'span', cls:'x-form-twin-triggers', cn:[
                {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger1Class},
                {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger2Class}
            ]};
        },

        getTrigger : function(index){
            return this.triggers[index];
        },

        initTrigger : function(){
            var ts = this.trigger.select('.x-form-trigger', true);
            this.wrap.setStyle('overflow', 'hidden');
            var triggerField = this;
            ts.each(function(t, all, index){
                t.hide = function(){
                    var w = triggerField.wrap.getWidth();
                    this.dom.style.display = 'none';
                    triggerField.el.setWidth(w-triggerField.trigger.getWidth());
                };
                t.show = function(){
                    var w = triggerField.wrap.getWidth();
                    this.dom.style.display = '';
                    triggerField.el.setWidth(w-triggerField.trigger.getWidth());
                };
                var triggerIndex = 'Trigger'+(index+1);

                if(this['hide'+triggerIndex]){
                    t.dom.style.display = 'none';
                }
                t.on("click", this['on'+triggerIndex+'Click'], this, {preventDefault:true});
                t.addClassOnOver('x-form-trigger-over');
                t.addClassOnClick('x-form-trigger-click');
            }, this);
            this.triggers = ts.elements;
        },

        onTrigger1Click : Ext.emptyFn,
        onTrigger2Click : Ext.emptyFn
    });
    Ext.reg('trigger', Ext.form.TriggerField);

    Ext.form.TextArea = Ext.extend(Ext.form.TextField,  {

        growMin : 60,

        growMax: 1000,
        growAppend : ' \n ',
        growPad : 0,

        enterIsSpecial : false,

        preventScrollbars: false,

            onRender : function(ct, position){
            if(!this.el){
                this.defaultAutoCreate = {
                    tag: "textarea",
                    style:"width:100px;height:60px;",
                    autocomplete: "off"
                };
            }
            Ext.form.TextArea.superclass.onRender.call(this, ct, position);
            if(this.grow){
                this.textSizeEl = Ext.DomHelper.append(document.body, {
                    tag: "pre", cls: "x-form-grow-sizer"
                });
                if(this.preventScrollbars){
                    this.el.setStyle("overflow", "hidden");
                }
                this.el.setHeight(this.growMin);
            }
        },

        onDestroy : function(){
            if(this.textSizeEl){
                Ext.removeNode(this.textSizeEl);
            }
            Ext.form.TextArea.superclass.onDestroy.call(this);
        },

        fireKey : function(e){
            if(e.isSpecialKey() && (this.enterIsSpecial || (e.getKey() != e.ENTER || e.hasModifier()))){
                this.fireEvent("specialkey", this, e);
            }
        },

            onKeyUp : function(e){
            if(!e.isNavKeyPress() || e.getKey() == e.ENTER){
                this.autoSize();
            }
        },

        autoSize : function(){
            if(!this.grow || !this.textSizeEl){
                return;
            }
            var el = this.el;
            var v = el.dom.value;
            var ts = this.textSizeEl;
            ts.innerHTML = '';
            ts.appendChild(document.createTextNode(v));
            v = ts.innerHTML;

            Ext.fly(ts).setWidth(this.el.getWidth());
            if(v.length < 1){
                v = "  ";
            }else{
                if(Ext.isIE){
                    v = v.replace(/\n/g, ' ');
                }
                v += this.growAppend;
            }
            ts.innerHTML = v;
            var h = Math.min(this.growMax, Math.max(ts.offsetHeight, this.growMin)+this.growPad);
            if(h != this.lastHeight){
                this.lastHeight = h;
                this.el.setHeight(h);
                this.fireEvent("autosize", this, h);
            }
        }
    });
    Ext.reg('textarea', Ext.form.TextArea);

    Ext.form.NumberField = Ext.extend(Ext.form.TextField,  {

        fieldClass: "x-form-field x-form-num-field",

        allowDecimals : true,

        decimalSeparator : ".",

        decimalPrecision : 2,

        allowNegative : true,

        minValue : Number.NEGATIVE_INFINITY,

        maxValue : Number.MAX_VALUE,

        minText : "The minimum value for this field is {0}",

        maxText : "The maximum value for this field is {0}",

        nanText : "{0} is not a valid number",

        baseChars : "0123456789",

            initEvents : function(){
            Ext.form.NumberField.superclass.initEvents.call(this);
            var allowed = this.baseChars+'';
            if(this.allowDecimals){
                allowed += this.decimalSeparator;
            }
            if(this.allowNegative){
                allowed += "-";
            }
            this.stripCharsRe = new RegExp('[^'+allowed+']', 'gi');
            var keyPress = function(e){
                var k = e.getKey();
                if(!Ext.isIE && (e.isSpecialKey() || k == e.BACKSPACE || k == e.DELETE)){
                    return;
                }
                var c = e.getCharCode();
                if(allowed.indexOf(String.fromCharCode(c)) === -1){
                    e.stopEvent();
                }
            };
            this.el.on("keypress", keyPress, this);
        },

            validateValue : function(value){
            if(!Ext.form.NumberField.superclass.validateValue.call(this, value)){
                return false;
            }
            if(value.length < 1){              return true;
            }
            value = String(value).replace(this.decimalSeparator, ".");
            if(isNaN(value)){
                this.markInvalid(String.format(this.nanText, value));
                return false;
            }
            var num = this.parseValue(value);
            if(num < this.minValue){
                this.markInvalid(String.format(this.minText, this.minValue));
                return false;
            }
            if(num > this.maxValue){
                this.markInvalid(String.format(this.maxText, this.maxValue));
                return false;
            }
            return true;
        },

        getValue : function(){
            return this.fixPrecision(this.parseValue(Ext.form.NumberField.superclass.getValue.call(this)));
        },

        setValue : function(v){
        	v = parseFloat(v);
        	v = isNaN(v) ? '' : String(v).replace(".", this.decimalSeparator);
            Ext.form.NumberField.superclass.setValue.call(this, v);
        },

            parseValue : function(value){
            value = parseFloat(String(value).replace(this.decimalSeparator, "."));
            return isNaN(value) ? '' : value;
        },

            fixPrecision : function(value){
            var nan = isNaN(value);
            if(!this.allowDecimals || this.decimalPrecision == -1 || nan || !value){
               return nan ? '' : value;
            }
            return parseFloat(parseFloat(value).toFixed(this.decimalPrecision));
        },

        beforeBlur : function(){
            var v = this.parseValue(this.getRawValue());
            if(v){
                this.setValue(this.fixPrecision(v));
            }
        }
    });
    Ext.reg('numberfield', Ext.form.NumberField);

    Ext.form.DateField = Ext.extend(Ext.form.TriggerField,  {

        format : "m/d/y",

        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",

        disabledDays : null,

        disabledDaysText : "Disabled",

        disabledDates : null,

        disabledDatesText : "Disabled",

        minValue : null,

        maxValue : null,

        minText : "The date in this field must be equal to or after {0}",

        maxText : "The date in this field must be equal to or before {0}",

        invalidText : "{0} is not a valid date - it must be in the format {1}",

        triggerClass : 'x-form-date-trigger',

            defaultAutoCreate : {tag: "input", type: "text", size: "10", autocomplete: "off"},

        initComponent : function(){
            Ext.form.DateField.superclass.initComponent.call(this);
            if(typeof this.minValue == "string"){
                this.minValue = this.parseDate(this.minValue);
            }
            if(typeof this.maxValue == "string"){
                this.maxValue = this.parseDate(this.maxValue);
            }
            this.ddMatch = null;
            if(this.disabledDates){
                var dd = this.disabledDates;
                var re = "(?:";
                for(var i = 0; i < dd.length; i++){
                    re += dd[i];
                    if(i != dd.length-1) re += "|";
                }
                this.ddMatch = new RegExp(re + ")");
            }
        },

            validateValue : function(value){
            value = this.formatDate(value);
            if(!Ext.form.DateField.superclass.validateValue.call(this, value)){
                return false;
            }
            if(value.length < 1){              return true;
            }
            var svalue = value;
            value = this.parseDate(value);
            if(!value){
                this.markInvalid(String.format(this.invalidText, svalue, this.format));
                return false;
            }
            var time = value.getTime();
            if(this.minValue && time < this.minValue.getTime()){
                this.markInvalid(String.format(this.minText, this.formatDate(this.minValue)));
                return false;
            }
            if(this.maxValue && time > this.maxValue.getTime()){
                this.markInvalid(String.format(this.maxText, this.formatDate(this.maxValue)));
                return false;
            }
            if(this.disabledDays){
                var day = value.getDay();
                for(var i = 0; i < this.disabledDays.length; i++) {
                	if(day === this.disabledDays[i]){
                	    this.markInvalid(this.disabledDaysText);
                        return false;
                	}
                }
            }
            var fvalue = this.formatDate(value);
            if(this.ddMatch && this.ddMatch.test(fvalue)){
                this.markInvalid(String.format(this.disabledDatesText, fvalue));
                return false;
            }
            return true;
        },

                validateBlur : function(){
            return !this.menu || !this.menu.isVisible();
        },

        getValue : function(){
            return this.parseDate(Ext.form.DateField.superclass.getValue.call(this)) || "";
        },

        setValue : function(date){
            Ext.form.DateField.superclass.setValue.call(this, this.formatDate(this.parseDate(date)));
        },

            parseDate : function(value){
            if(!value || Ext.isDate(value)){
                return value;
            }
            var v = Date.parseDate(value, this.format);
            if(!v && this.altFormats){
                if(!this.altFormatsArray){
                    this.altFormatsArray = this.altFormats.split("|");
                }
                for(var i = 0, len = this.altFormatsArray.length; i < len && !v; i++){
                    v = Date.parseDate(value, this.altFormatsArray[i]);
                }
            }
            return v;
        },

            onDestroy : function(){
            if(this.menu) {
                this.menu.destroy();
            }
            if(this.wrap){
                this.wrap.remove();
            }
            Ext.form.DateField.superclass.onDestroy.call(this);
        },

            formatDate : function(date){
            return Ext.isDate(date) ? date.dateFormat(this.format) : date;
        },

            menuListeners : {
            select: function(m, d){
                this.setValue(d);
            },
            show : function(){             this.onFocus();
            },
            hide : function(){
                this.focus.defer(10, this);
                var ml = this.menuListeners;
                this.menu.un("select", ml.select,  this);
                this.menu.un("show", ml.show,  this);
                this.menu.un("hide", ml.hide,  this);
            }
        },

                onTriggerClick : function(){
            if(this.disabled){
                return;
            }
            if(this.menu == null){
                this.menu = new Ext.menu.DateMenu();
            }
            Ext.apply(this.menu.picker,  {
                minDate : this.minValue,
                maxDate : this.maxValue,
                disabledDatesRE : this.ddMatch,
                disabledDatesText : this.disabledDatesText,
                disabledDays : this.disabledDays,
                disabledDaysText : this.disabledDaysText,
                format : this.format,
                minText : String.format(this.minText, this.formatDate(this.minValue)),
                maxText : String.format(this.maxText, this.formatDate(this.maxValue))
            });
            this.menu.on(Ext.apply({}, this.menuListeners, {
                scope:this
            }));
            this.menu.picker.setValue(this.getValue() || new Date());
            this.menu.show(this.el, "tl-bl?");
        },

        beforeBlur : function(){
            var v = this.parseDate(this.getRawValue());
            if(v){
                this.setValue(v);
            }
        }

    });
    Ext.reg('datefield', Ext.form.DateField);

    Ext.form.ComboBox = Ext.extend(Ext.form.TriggerField, {

            defaultAutoCreate : {tag: "input", type: "text", size: "24", autocomplete: "off"},

        listClass: '',

        selectedClass: 'x-combo-selected',

        triggerClass : 'x-form-arrow-trigger',

        shadow:'sides',

        listAlign: 'tl-bl?',

        maxHeight: 300,

        minHeight: 90,

        triggerAction: 'query',

        minChars : 4,

        typeAhead: false,

        queryDelay: 500,

        pageSize: 0,

        selectOnFocus:false,

        queryParam: 'query',

        loadingText: 'Loading...',

        resizable: false,

        handleHeight : 8,

        editable: true,

        allQuery: '',

        mode: 'remote',

        minListWidth : 70,

        forceSelection:false,

        typeAheadDelay : 250,

        lazyInit : true,

        initComponent : function(){
            Ext.form.ComboBox.superclass.initComponent.call(this);
            this.addEvents(

                'expand',

                'collapse',

                'beforeselect',

                'select',

                'beforequery'
            );
            if(this.transform){
                this.allowDomMove = false;
                var s = Ext.getDom(this.transform);
                if(!this.hiddenName){
                    this.hiddenName = s.name;
                }
                if(!this.store){
                    this.mode = 'local';
                    var d = [], opts = s.options;
                    for(var i = 0, len = opts.length;i < len; i++){
                        var o = opts[i];
                        var value = (Ext.isIE ? o.getAttributeNode('value').specified : o.hasAttribute('value')) ? o.value : o.text;
                        if(o.selected) {
                            this.value = value;
                        }
                        d.push([value, o.text]);
                    }
                    this.store = new Ext.data.SimpleStore({
                        'id': 0,
                        fields: ['value', 'text'],
                        data : d
                    });
                    this.valueField = 'value';
                    this.displayField = 'text';
                }
                s.name = Ext.id();             if(!this.lazyRender){
                    this.target = true;
                    this.el = Ext.DomHelper.insertBefore(s, this.autoCreate || this.defaultAutoCreate);
                    Ext.removeNode(s);                 this.render(this.el.parentNode);
                }else{
                    Ext.removeNode(s);             }

            }
            this.selectedIndex = -1;
            if(this.mode == 'local'){
                if(this.initialConfig.queryDelay === undefined){
                    this.queryDelay = 10;
                }
                if(this.initialConfig.minChars === undefined){
                    this.minChars = 0;
                }
            }
        },

            onRender : function(ct, position){
            Ext.form.ComboBox.superclass.onRender.call(this, ct, position);
            if(this.hiddenName){
                this.hiddenField = this.el.insertSibling({tag:'input', type:'hidden', name: this.hiddenName, id: (this.hiddenId||this.hiddenName)},
                        'before', true);
                this.hiddenField.value =
                    this.hiddenValue !== undefined ? this.hiddenValue :
                    this.value !== undefined ? this.value : '';

                            this.el.dom.removeAttribute('name');
            }
            if(Ext.isGecko){
                this.el.dom.setAttribute('autocomplete', 'off');
            }

            if(!this.lazyInit){
                this.initList();
            }else{
                this.on('focus', this.initList, this, {single: true});
            }

            if(!this.editable){
                this.editable = true;
                this.setEditable(false);
            }
        },

        initList : function(){
            if(!this.list){
                var cls = 'x-combo-list';

                this.list = new Ext.Layer({
                    shadow: this.shadow, cls: [cls, this.listClass].join(' '), constrain:false
                });

                var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);
                this.list.setWidth(lw);
                this.list.swallowEvent('mousewheel');
                this.assetHeight = 0;

                if(this.title){
                    this.header = this.list.createChild({cls:cls+'-hd', html: this.title});
                    this.assetHeight += this.header.getHeight();
                }

                this.innerList = this.list.createChild({cls:cls+'-inner'});
                this.innerList.on('mouseover', this.onViewOver, this);
                this.innerList.on('mousemove', this.onViewMove, this);
                this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));

                if(this.pageSize){
                    this.footer = this.list.createChild({cls:cls+'-ft'});
                    this.pageTb = new Ext.PagingToolbar({
                        store:this.store,
                        pageSize: this.pageSize,
                        renderTo:this.footer
                    });
                    this.assetHeight += this.footer.getHeight();
                }

                if(!this.tpl){

                    this.tpl = '{' + this.displayField + '}';
                }

                this.view = new Ext.DataView({
                    applyTo: this.innerList,
                    tpl: this.tpl,
                    singleSelect: true,
                    selectedClass: this.selectedClass,
                    itemSelector: this.itemSelector || '.' + cls + '-item'
                });

                this.view.on('click', this.onViewClick, this);

                this.bindStore(this.store, true);

                if(this.resizable){
                    this.resizer = new Ext.Resizable(this.list,  {
                       pinned:true, handles:'se'
                    });
                    this.resizer.on('resize', function(r, w, h){
                        this.maxHeight = h-this.handleHeight-this.list.getFrameWidth('tb')-this.assetHeight;
                        this.listWidth = w;
                        this.innerList.setWidth(w - this.list.getFrameWidth('lr'));
                        this.restrictHeight();
                    }, this);
                    this[this.pageSize?'footer':'innerList'].setStyle('margin-bottom', this.handleHeight+'px');
                }
            }
        },

            bindStore : function(store, initial){
            if(this.store && !initial){
                this.store.un('beforeload', this.onBeforeLoad, this);
                this.store.un('load', this.onLoad, this);
                this.store.un('loadexception', this.collapse, this);
                if(!store){
                    this.store = null;
                    if(this.view){
                        this.view.setStore(null);
                    }
                }
            }
            if(store){
                this.store = Ext.StoreMgr.lookup(store);

                this.store.on('beforeload', this.onBeforeLoad, this);
                this.store.on('load', this.onLoad, this);
                this.store.on('loadexception', this.collapse, this);

                if(this.view){
                    this.view.setStore(store);
                }
            }
        },

            initEvents : function(){
            Ext.form.ComboBox.superclass.initEvents.call(this);

            this.keyNav = new Ext.KeyNav(this.el, {
                "up" : function(e){
                    this.inKeyMode = true;
                    this.selectPrev();
                },

                "down" : function(e){
                    if(!this.isExpanded()){
                        this.onTriggerClick();
                    }else{
                        this.inKeyMode = true;
                        this.selectNext();
                    }
                },

                "enter" : function(e){
                    this.onViewClick();
                    this.delayedCheck = true;
    				this.unsetDelayCheck.defer(10, this);
                },

                "esc" : function(e){
                    this.collapse();
                },

                "tab" : function(e){
                    this.onViewClick(false);
                    return true;
                },

                scope : this,

                doRelay : function(foo, bar, hname){
                    if(hname == 'down' || this.scope.isExpanded()){
                       return Ext.KeyNav.prototype.doRelay.apply(this, arguments);
                    }
                    return true;
                },

                forceKeyDown : true
            });
            this.queryDelay = Math.max(this.queryDelay || 10,
                    this.mode == 'local' ? 10 : 250);
            this.dqTask = new Ext.util.DelayedTask(this.initQuery, this);
            if(this.typeAhead){
                this.taTask = new Ext.util.DelayedTask(this.onTypeAhead, this);
            }
            if(this.editable !== false){
                this.el.on("keyup", this.onKeyUp, this);
            }
            if(this.forceSelection){
                this.on('blur', this.doForce, this);
            }
        },

        onDestroy : function(){
            if(this.view){
                this.view.el.removeAllListeners();
                this.view.el.remove();
                this.view.purgeListeners();
            }
            if(this.list){
                this.list.destroy();
            }
            this.bindStore(null);
            Ext.form.ComboBox.superclass.onDestroy.call(this);
        },

    	unsetDelayCheck : function(){
    		delete this.delayedCheck;
    	},
            fireKey : function(e){
            if(e.isNavKeyPress() && !this.isExpanded() && !this.delayedCheck){
                this.fireEvent("specialkey", this, e);
            }
        },

            onResize: function(w, h){
            Ext.form.ComboBox.superclass.onResize.apply(this, arguments);
            if(this.list && this.listWidth === undefined){
                var lw = Math.max(w, this.minListWidth);
                this.list.setWidth(lw);
                this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
            }
        },

            onEnable: function(){
            Ext.form.ComboBox.superclass.onEnable.apply(this, arguments);
            if(this.hiddenField){
                this.hiddenField.disabled = false;
            }
        },

            onDisable: function(){
            Ext.form.ComboBox.superclass.onDisable.apply(this, arguments);
            if(this.hiddenField){
                this.hiddenField.disabled = true;
            }
        },

        setEditable : function(value){
            if(value == this.editable){
                return;
            }
            this.editable = value;
            if(!value){
                this.el.dom.setAttribute('readOnly', true);
                this.el.on('mousedown', this.onTriggerClick,  this);
                this.el.addClass('x-combo-noedit');
            }else{
                this.el.dom.setAttribute('readOnly', false);
                this.el.un('mousedown', this.onTriggerClick,  this);
                this.el.removeClass('x-combo-noedit');
            }
        },

            onBeforeLoad : function(){
            if(!this.hasFocus){
                return;
            }
            this.innerList.update(this.loadingText ?
                   ''+this.loadingText+'' : '');
            this.restrictHeight();
            this.selectedIndex = -1;
        },

            onLoad : function(){
            if(!this.hasFocus){
                return;
            }
            if(this.store.getCount() > 0){
                this.expand();
                this.restrictHeight();
                if(this.lastQuery == this.allQuery){
                    if(this.editable){
                        this.el.dom.select();
                    }
                    if(!this.selectByValue(this.value, true)){
                        this.select(0, true);
                    }
                }else{
                    this.selectNext();
                    if(this.typeAhead && this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE){
                        this.taTask.delay(this.typeAheadDelay);
                    }
                }
            }else{
                this.onEmptyResults();
            }
                },

            onTypeAhead : function(){
            if(this.store.getCount() > 0){
                var r = this.store.getAt(0);
                var newValue = r.data[this.displayField];
                var len = newValue.length;
                var selStart = this.getRawValue().length;
                if(selStart != len){
                    this.setRawValue(newValue);
                    this.selectText(selStart, newValue.length);
                }
            }
        },

            onSelect : function(record, index){
            if(this.fireEvent('beforeselect', this, record, index) !== false){
                this.setValue(record.data[this.valueField || this.displayField]);
                this.collapse();
                this.fireEvent('select', this, record, index);
            }
        },

        getValue : function(){
            if(this.valueField){
                return typeof this.value != 'undefined' ? this.value : '';
            }else{
                return Ext.form.ComboBox.superclass.getValue.call(this);
            }
        },

        clearValue : function(){
            if(this.hiddenField){
                this.hiddenField.value = '';
            }
            this.setRawValue('');
            this.lastSelectionText = '';
            this.applyEmptyText();
            this.value = '';
        },

        setValue : function(v){
            var text = v;
            if(this.valueField){
                var r = this.findRecord(this.valueField, v);
                if(r){
                    text = r.data[this.displayField];
                }else if(this.valueNotFoundText !== undefined){
                    text = this.valueNotFoundText;
                }
            }
            this.lastSelectionText = text;
            if(this.hiddenField){
                this.hiddenField.value = v;
            }
            Ext.form.ComboBox.superclass.setValue.call(this, text);
            this.value = v;
        },

            findRecord : function(prop, value){
            var record;
            if(this.store.getCount() > 0){
                this.store.each(function(r){
                    if(r.data[prop] == value){
                        record = r;
                        return false;
                    }
                });
            }
            return record;
        },

            onViewMove : function(e, t){
            this.inKeyMode = false;
        },

            onViewOver : function(e, t){
            if(this.inKeyMode){             return;
            }
            var item = this.view.findItemFromChild(t);
            if(item){
                var index = this.view.indexOf(item);
                this.select(index, false);
            }
        },

            onViewClick : function(doFocus){
            var index = this.view.getSelectedIndexes()[0];
            var r = this.store.getAt(index);
            if(r){
                this.onSelect(r, index);
            }
            if(doFocus !== false){
                this.el.focus();
            }
        },

        	restrictHeight : function(){
            this.innerList.dom.style.height = '';
            var inner = this.innerList.dom;
            var pad = this.list.getFrameWidth('tb')+(this.resizable?this.handleHeight:0)+this.assetHeight;
            var h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight);
            var ha = this.getPosition()[1]-Ext.getBody().getScroll().top;
            var hb = Ext.lib.Dom.getViewHeight()-ha-this.getSize().height;
            var space = Math.max(ha, hb, this.minHeight || 0)-this.list.shadow.offset-pad-2;
            h = Math.min(h, space, this.maxHeight);

            this.innerList.setHeight(h);
            this.list.beginUpdate();
            this.list.setHeight(h+pad);
            this.list.alignTo(this.el, this.listAlign);
            this.list.endUpdate();
        },

            onEmptyResults : function(){
            this.collapse();
        },

        isExpanded : function(){
            return this.list && this.list.isVisible();
        },

        selectByValue : function(v, scrollIntoView){
            if(v !== undefined && v !== null){
                var r = this.findRecord(this.valueField || this.displayField, v);
                if(r){
                    this.select(this.store.indexOf(r), scrollIntoView);
                    return true;
                }
            }
            return false;
        },

        select : function(index, scrollIntoView){
            this.selectedIndex = index;
            this.view.select(index);
            if(scrollIntoView !== false){
                var el = this.view.getNode(index);
                if(el){
                    this.innerList.scrollChildIntoView(el, false);
                }
            }
        },

            selectNext : function(){
            var ct = this.store.getCount();
            if(ct > 0){
                if(this.selectedIndex == -1){
                    this.select(0);
                }else if(this.selectedIndex < ct-1){
                    this.select(this.selectedIndex+1);
                }
            }
        },

            selectPrev : function(){
            var ct = this.store.getCount();
            if(ct > 0){
                if(this.selectedIndex == -1){
                    this.select(0);
                }else if(this.selectedIndex != 0){
                    this.select(this.selectedIndex-1);
                }
            }
        },

            onKeyUp : function(e){
            if(this.editable !== false && !e.isSpecialKey()){
                this.lastKey = e.getKey();
                this.dqTask.delay(this.queryDelay);
            }
        },

            validateBlur : function(){
            return !this.list || !this.list.isVisible();
        },

            initQuery : function(){
            this.doQuery(this.getRawValue());
        },

            doForce : function(){
            if(this.el.dom.value.length > 0){
                this.el.dom.value =
                    this.lastSelectionText === undefined ? '' : this.lastSelectionText;
                this.applyEmptyText();
            }
        },

        doQuery : function(q, forceAll){
            if(q === undefined || q === null){
                q = '';
            }
            var qe = {
                query: q,
                forceAll: forceAll,
                combo: this,
                cancel:false
            };
            if(this.fireEvent('beforequery', qe)===false || qe.cancel){
                return false;
            }
            q = qe.query;
            forceAll = qe.forceAll;
            if(forceAll === true || (q.length >= this.minChars)){
                if(this.lastQuery !== q){
                    this.lastQuery = q;
                    if(this.mode == 'local'){
                        this.selectedIndex = -1;
                        if(forceAll){
                            this.store.clearFilter();
                        }else{
                            this.store.filter(this.displayField, q);
                        }
                        this.onLoad();
                    }else{
                        this.store.baseParams[this.queryParam] = q;
                        this.store.load({
                            params: this.getParams(q)
                        });
                        this.expand();
                    }
                }else{
                    this.selectedIndex = -1;
                    this.onLoad();
                }
            }
        },

            getParams : function(q){
            var p = {};
                    if(this.pageSize){
                p.start = 0;
                p.limit = this.pageSize;
            }
            return p;
        },

        collapse : function(){
            if(!this.isExpanded()){
                return;
            }
            this.list.hide();
            Ext.getDoc().un('mousewheel', this.collapseIf, this);
            Ext.getDoc().un('mousedown', this.collapseIf, this);
            this.fireEvent('collapse', this);
        },

            collapseIf : function(e){
            if(!e.within(this.wrap) && !e.within(this.list)){
                this.collapse();
            }
        },

        expand : function(){
            if(this.isExpanded() || !this.hasFocus){
                return;
            }
            this.list.alignTo(this.wrap, this.listAlign);
            this.list.show();
            this.innerList.setOverflow('auto');         Ext.getDoc().on('mousewheel', this.collapseIf, this);
            Ext.getDoc().on('mousedown', this.collapseIf, this);
            this.fireEvent('expand', this);
        },

                onTriggerClick : function(){
            if(this.disabled){
                return;
            }
            if(this.isExpanded()){
                this.collapse();
                this.el.focus();
            }else {
                this.onFocus({});
                if(this.triggerAction == 'all') {
                    this.doQuery(this.allQuery, true);
                } else {
                    this.doQuery(this.getRawValue());
                }
                this.el.focus();
            }
        }

    });
    Ext.reg('combo', Ext.form.ComboBox);

    Ext.form.Checkbox = Ext.extend(Ext.form.Field,  {

        focusClass : undefined,

        fieldClass: "x-form-field",

        checked: false,

        defaultAutoCreate : { tag: "input", type: 'checkbox', autocomplete: "off"},

    	    initComponent : function(){
            Ext.form.Checkbox.superclass.initComponent.call(this);
            this.addEvents(

                'check'
            );
        },

            onResize : function(){
            Ext.form.Checkbox.superclass.onResize.apply(this, arguments);
            if(!this.boxLabel){
                this.el.alignTo(this.wrap, 'c-c');
            }
        },

            initEvents : function(){
            Ext.form.Checkbox.superclass.initEvents.call(this);
            this.el.on("click", this.onClick,  this);
            this.el.on("change", this.onClick,  this);
        },

    	    getResizeEl : function(){
            return this.wrap;
        },

            getPositionEl : function(){
            return this.wrap;
        },

        markInvalid : Ext.emptyFn,

        clearInvalid : Ext.emptyFn,

            onRender : function(ct, position){
            Ext.form.Checkbox.superclass.onRender.call(this, ct, position);
            if(this.inputValue !== undefined){
                this.el.dom.value = this.inputValue;
            }
            this.wrap = this.el.wrap({cls: "x-form-check-wrap"});
            if(this.boxLabel){
                this.wrap.createChild({tag: 'label', htmlFor: this.el.id, cls: 'x-form-cb-label', html: this.boxLabel});
            }
            if(this.checked){
                this.setValue(true);
            }else{
                this.checked = this.el.dom.checked;
            }
        },

            onDestroy : function(){
            if(this.wrap){
                this.wrap.remove();
            }
            Ext.form.Checkbox.superclass.onDestroy.call(this);
        },

            initValue : Ext.emptyFn,

        getValue : function(){
            if(this.rendered){
                return this.el.dom.checked;
            }
            return false;
        },

    	    onClick : function(){
            if(this.el.dom.checked != this.checked){
                this.setValue(this.el.dom.checked);
            }
        },

        setValue : function(v){
            this.checked = (v === true || v === 'true' || v == '1' || String(v).toLowerCase() == 'on');
            if(this.el && this.el.dom){
                this.el.dom.checked = this.checked;
                this.el.dom.defaultChecked = this.checked;
            }
            this.fireEvent("check", this, this.checked);
        }
    });
    Ext.reg('checkbox', Ext.form.Checkbox);

    Ext.form.Radio = Ext.extend(Ext.form.Checkbox, {
        inputType: 'radio',

        markInvalid : Ext.emptyFn,

        clearInvalid : Ext.emptyFn,

        getGroupValue : function(){
        	var p = this.el.up('form') || Ext.getBody();
            var c = p.child('input[name='+this.el.dom.name+']:checked', true);
            return c ? c.value : null;
        },

            onClick : function(){
        	if(this.el.dom.checked != this.checked){
        		var p = this.el.up('form') || Ext.getBody();
    			var els = p.select('input[name='+this.el.dom.name+']');
    			els.each(function(el){
    				if(el.dom.id == this.id){
    					this.setValue(true);
    				}else{
    					Ext.getCmp(el.dom.id).setValue(false);
    				}
    			}, this);
    		}
        },

        setValue : function(v){
        	if (typeof v == 'boolean') {
                Ext.form.Radio.superclass.setValue.call(this, v);
            } else {
                var r = this.el.up('form').child('input[name='+this.el.dom.name+'][value='+v+']', true);
                if (r){
                    r.checked = true;
                };
            }
        }
    });
    Ext.reg('radio', Ext.form.Radio);

    Ext.form.Hidden = Ext.extend(Ext.form.Field, {

        inputType : 'hidden',

        onRender : function(){
            Ext.form.Hidden.superclass.onRender.apply(this, arguments);
        },

        initEvents : function(){
            this.originalValue = this.getValue();
        },

        setSize : Ext.emptyFn,
        setWidth : Ext.emptyFn,
        setHeight : Ext.emptyFn,
        setPosition : Ext.emptyFn,
        setPagePosition : Ext.emptyFn,
        markInvalid : Ext.emptyFn,
        clearInvalid : Ext.emptyFn
    });
    Ext.reg('hidden', Ext.form.Hidden);

    Ext.form.BasicForm = function(el, config){
        Ext.apply(this, config);

        this.items = new Ext.util.MixedCollection(false, function(o){
            return o.id || (o.id = Ext.id());
        });
        this.addEvents(

            'beforeaction',

            'actionfailed',

            'actioncomplete'
        );

        if(el){
            this.initEl(el);
        }
        Ext.form.BasicForm.superclass.constructor.call(this);
    };

    Ext.extend(Ext.form.BasicForm, Ext.util.Observable, {

        timeout: 30,

            activeAction : null,

        trackResetOnLoad : false,

            initEl : function(el){
            this.el = Ext.get(el);
            this.id = this.el.id || Ext.id();
            if(!this.standardSubmit){
                this.el.on('submit', this.onSubmit, this);
            }
            this.el.addClass('x-form');
        },

        getEl: function(){
            return this.el;
        },

            onSubmit : function(e){
            e.stopEvent();
        },

        	destroy: function() {
            this.items.each(function(f){
                Ext.destroy(f);
            });
            if(this.el){
    			this.el.removeAllListeners();
    			this.el.remove();
            }
    		this.purgeListeners();
    	},

        isValid : function(){
            var valid = true;
            this.items.each(function(f){
               if(!f.validate()){
                   valid = false;
               }
            });
            return valid;
        },

        isDirty : function(){
            var dirty = false;
            this.items.each(function(f){
               if(f.isDirty()){
                   dirty = true;
                   return false;
               }
            });
            return dirty;
        },

        doAction : function(action, options){
            if(typeof action == 'string'){
                action = new Ext.form.Action.ACTION_TYPES[action](this, options);
            }
            if(this.fireEvent('beforeaction', this, action) !== false){
                this.beforeAction(action);
                action.run.defer(100, action);
            }
            return this;
        },

        submit : function(options){
            if(this.standardSubmit){
                var v = this.isValid();
                if(v){
                    this.el.dom.submit();
                }
                return v;
            }
            this.doAction('submit', options);
            return this;
        },

        load : function(options){
            this.doAction('load', options);
            return this;
        },

        updateRecord : function(record){
            record.beginEdit();
            var fs = record.fields;
            fs.each(function(f){
                var field = this.findField(f.name);
                if(field){
                    record.set(f.name, field.getValue());
                }
            }, this);
            record.endEdit();
            return this;
        },

        loadRecord : function(record){
            this.setValues(record.data);
            return this;
        },

            beforeAction : function(action){
            var o = action.options;
            if(o.waitMsg){
                if(this.waitMsgTarget === true){
                    this.el.mask(o.waitMsg, 'x-mask-loading');
                }else if(this.waitMsgTarget){
                    this.waitMsgTarget = Ext.get(this.waitMsgTarget);
                    this.waitMsgTarget.mask(o.waitMsg, 'x-mask-loading');
                }else{
                    Ext.MessageBox.wait(o.waitMsg, o.waitTitle || this.waitTitle || 'Please Wait...');
                }
            }
        },

            afterAction : function(action, success){
            this.activeAction = null;
            var o = action.options;
            if(o.waitMsg){
                if(this.waitMsgTarget === true){
                    this.el.unmask();
                }else if(this.waitMsgTarget){
                    this.waitMsgTarget.unmask();
                }else{
                    Ext.MessageBox.updateProgress(1);
                    Ext.MessageBox.hide();
                }
            }
            if(success){
                if(o.reset){
                    this.reset();
                }
                Ext.callback(o.success, o.scope, [this, action]);
                this.fireEvent('actioncomplete', this, action);
            }else{
                Ext.callback(o.failure, o.scope, [this, action]);
                this.fireEvent('actionfailed', this, action);
            }
        },

        findField : function(id){
            var field = this.items.get(id);
            if(!field){
                this.items.each(function(f){
                    if(f.isFormField && (f.dataIndex == id || f.id == id || f.getName() == id)){
                        field = f;
                        return false;
                    }
                });
            }
            return field || null;
        },

        markInvalid : function(errors){
            if(Ext.isArray(errors)){
                for(var i = 0, len = errors.length; i < len; i++){
                    var fieldError = errors[i];
                    var f = this.findField(fieldError.id);
                    if(f){
                        f.markInvalid(fieldError.msg);
                    }
                }
            }else{
                var field, id;
                for(id in errors){
                    if(typeof errors[id] != 'function' && (field = this.findField(id))){
                        field.markInvalid(errors[id]);
                    }
                }
            }
            return this;
        },

        setValues : function(values){
            if(Ext.isArray(values)){             for(var i = 0, len = values.length; i < len; i++){
                    var v = values[i];
                    var f = this.findField(v.id);
                    if(f){
                        f.setValue(v.value);
                        if(this.trackResetOnLoad){
                            f.originalValue = f.getValue();
                        }
                    }
                }
            }else{             var field, id;
                for(id in values){
                    if(typeof values[id] != 'function' && (field = this.findField(id))){
                        field.setValue(values[id]);
                        if(this.trackResetOnLoad){
                            field.originalValue = field.getValue();
                        }
                    }
                }
            }
            return this;
        },

        getValues : function(asString){
            var fs = Ext.lib.Ajax.serializeForm(this.el.dom);
            if(asString === true){
                return fs;
            }
            return Ext.urlDecode(fs);
        },

        clearInvalid : function(){
            this.items.each(function(f){
               f.clearInvalid();
            });
            return this;
        },

        reset : function(){
            this.items.each(function(f){
                f.reset();
            });
            return this;
        },

        add : function(){
            this.items.addAll(Array.prototype.slice.call(arguments, 0));
            return this;
        },

        remove : function(field){
            this.items.remove(field);
            return this;
        },

        render : function(){
            this.items.each(function(f){
                if(f.isFormField && !f.rendered && document.getElementById(f.id)){                 f.applyToMarkup(f.id);
                }
            });
            return this;
        },

        applyToFields : function(o){
            this.items.each(function(f){
               Ext.apply(f, o);
            });
            return this;
        },

        applyIfToFields : function(o){
            this.items.each(function(f){
               Ext.applyIf(f, o);
            });
            return this;
        }
    });

    Ext.BasicForm = Ext.form.BasicForm;

    Ext.FormPanel = Ext.extend(Ext.Panel, {

        buttonAlign:'center',

        minButtonWidth:75,

        labelAlign:'left',

        monitorValid : false,

        monitorPoll : 200,

        layout: 'form',

            initComponent :function(){
            this.form = this.createForm();

            Ext.FormPanel.superclass.initComponent.call(this);

            this.addEvents(

                'clientvalidation'
            );

            this.relayEvents(this.form, ['beforeaction', 'actionfailed', 'actioncomplete']);
        },

            createForm: function(){
            delete this.initialConfig.listeners;
            return new Ext.form.BasicForm(null, this.initialConfig);
        },

            initFields : function(){
            var f = this.form;
            var formPanel = this;
            var fn = function(c){
                if(c.doLayout && c != formPanel){
                    Ext.applyIf(c, {
                        labelAlign: c.ownerCt.labelAlign,
                        labelWidth: c.ownerCt.labelWidth,
                        itemCls: c.ownerCt.itemCls
                    });
                    if(c.items){
                        c.items.each(fn);
                    }
                }else if(c.isFormField){
                    f.add(c);
                }
            }
            this.items.each(fn);
        },

            getLayoutTarget : function(){
            return this.form.el;
        },

        getForm : function(){
            return this.form;
        },

            onRender : function(ct, position){
            this.initFields();

            Ext.FormPanel.superclass.onRender.call(this, ct, position);
            var o = {
                tag: 'form',
                method : this.method || 'POST',
                id : this.formId || Ext.id()
            };
            if(this.fileUpload) {
                o.enctype = 'multipart/form-data';
            }
            this.form.initEl(this.body.createChild(o));
        },

            beforeDestroy: function(){
            Ext.FormPanel.superclass.beforeDestroy.call(this);
            Ext.destroy(this.form);
        },

            initEvents : function(){
            Ext.FormPanel.superclass.initEvents.call(this);
    		this.items.on('remove', this.onRemove, this);
    		this.items.on('add', this.onAdd, this);
            if(this.monitorValid){             this.startMonitoring();
            }
        },

        	onAdd : function(ct, c) {
    		if (c.isFormField) {
    			this.form.add(c);
    		}
    	},

    		onRemove : function(c) {
    		if (c.isFormField) {
    			Ext.destroy(c.container.up('.x-form-item'));
    			this.form.remove(c);
    		}
    	},

        startMonitoring : function(){
            if(!this.bound){
                this.bound = true;
                Ext.TaskMgr.start({
                    run : this.bindHandler,
                    interval : this.monitorPoll || 200,
                    scope: this
                });
            }
        },

        stopMonitoring : function(){
            this.bound = false;
        },

        load : function(){
            this.form.load.apply(this.form, arguments);
        },

            onDisable : function(){
            Ext.FormPanel.superclass.onDisable.call(this);
            if(this.form){
                this.form.items.each(function(){
                     this.disable();
                });
            }
        },

            onEnable : function(){
            Ext.FormPanel.superclass.onEnable.call(this);
            if(this.form){
                this.form.items.each(function(){
                     this.enable();
                });
            }
        },

            bindHandler : function(){
            if(!this.bound){
                return false;         }
            var valid = true;
            this.form.items.each(function(f){
                if(!f.isValid(true)){
                    valid = false;
                    return false;
                }
            });
            if(this.buttons){
                for(var i = 0, len = this.buttons.length; i < len; i++){
                    var btn = this.buttons[i];
                    if(btn.formBind === true && btn.disabled === valid){
                        btn.setDisabled(!valid);
                    }
                }
            }
            this.fireEvent('clientvalidation', this, valid);
        }
    });
    Ext.reg('form', Ext.FormPanel);

    Ext.form.FormPanel = Ext.FormPanel;

    Ext.form.FieldSet = Ext.extend(Ext.Panel, {

        baseCls:'x-fieldset',

        layout: 'form',

        onRender : function(ct, position){
            if(!this.el){
                this.el = document.createElement('fieldset');
                this.el.id = this.id;
                if (this.title || this.header || this.checkboxToggle) {
                    this.el.appendChild(document.createElement('legend')).className = 'x-fieldset-header';
                }
            }

            Ext.form.FieldSet.superclass.onRender.call(this, ct, position);

            if(this.checkboxToggle){
                var o = typeof this.checkboxToggle == 'object' ?
                        this.checkboxToggle :
                        {tag: 'input', type: 'checkbox', name: this.checkboxName || this.id+'-checkbox'};
                this.checkbox = this.header.insertFirst(o);
                this.checkbox.dom.checked = !this.collapsed;
                this.checkbox.on('click', this.onCheckClick, this);
            }
        },

        onCollapse : function(doAnim, animArg){
            if(this.checkbox){
                this.checkbox.dom.checked = false;
            }
            this.afterCollapse();

        },

        onExpand : function(doAnim, animArg){
            if(this.checkbox){
                this.checkbox.dom.checked = true;
            }
            this.afterExpand();
        },

        onCheckClick : function(){
            this[this.checkbox.dom.checked ? 'expand' : 'collapse']();
        }

    });
    Ext.reg('fieldset', Ext.form.FieldSet);

    Ext.form.HtmlEditor = Ext.extend(Ext.form.Field, {

        enableFormat : true,

        enableFontSize : true,

        enableColors : true,

        enableAlignments : true,

        enableLists : true,

        enableSourceEdit : true,

        enableLinks : true,

        enableFont : true,

        createLinkText : 'Please enter the URL for the link:',

        defaultLinkValue : 'http:/'+'/',

        fontFamilies : [
            'Arial',
            'Courier New',
            'Tahoma',
            'Times New Roman',
            'Verdana'
        ],
        defaultFont: 'tahoma',

        validationEvent : false,
        deferHeight: true,
        initialized : false,
        activated : false,
        sourceEditMode : false,
        onFocus : Ext.emptyFn,
        iframePad:3,
        hideMode:'offsets',
        defaultAutoCreate : {
            tag: "textarea",
            style:"width:500px;height:300px;",
            autocomplete: "off"
        },

        initComponent : function(){
            this.addEvents(

                'initialize',

                'activate',

                'beforesync',

                'beforepush',

                'sync',

                'push',

                'editmodechange'
            )
        },

        createFontOptions : function(){
            var buf = [], fs = this.fontFamilies, ff, lc;
            for(var i = 0, len = fs.length; i< len; i++){
                ff = fs[i];
                lc = ff.toLowerCase();
                buf.push(
                    '' : '>'),
                        ff,
                    ''
                );
            }
            return buf.join('');
        },

        createToolbar : function(editor){

            function btn(id, toggle, handler){
                return {
                    itemId : id,
                    cls : 'x-btn-icon x-edit-'+id,
                    enableToggle:toggle !== false,
                    scope: editor,
                    handler:handler||editor.relayBtnCmd,
                    clickEvent:'mousedown',
                    tooltip: editor.buttonTips[id] || undefined,
                    tabIndex:-1
                };
            }

            var tb = new Ext.Toolbar({
                renderTo:this.wrap.dom.firstChild
            });

            tb.el.on('click', function(e){
                e.preventDefault();
            });

            if(this.enableFont && !Ext.isSafari){
                this.fontSelect = tb.el.createChild({
                    tag:'select',
                    cls:'x-font-select',
                    html: this.createFontOptions()
                });
                this.fontSelect.on('change', function(){
                    var font = this.fontSelect.dom.value;
                    this.relayCmd('fontname', font);
                    this.deferFocus();
                }, this);
                tb.add(
                    this.fontSelect.dom,
                    '-'
                );
            };

            if(this.enableFormat){
                tb.add(
                    btn('bold'),
                    btn('italic'),
                    btn('underline')
                );
            };

            if(this.enableFontSize){
                tb.add(
                    '-',
                    btn('increasefontsize', false, this.adjustFont),
                    btn('decreasefontsize', false, this.adjustFont)
                );
            };

            if(this.enableColors){
                tb.add(
                    '-', {
                        itemId:'forecolor',
                        cls:'x-btn-icon x-edit-forecolor',
                        clickEvent:'mousedown',
                        tooltip: editor.buttonTips['forecolor'] || undefined,
                        tabIndex:-1,
                        menu : new Ext.menu.ColorMenu({
                            allowReselect: true,
                            focus: Ext.emptyFn,
                            value:'000000',
                            plain:true,
                            selectHandler: function(cp, color){
                                this.execCmd('forecolor', Ext.isSafari || Ext.isIE ? '#'+color : color);
                                this.deferFocus();
                            },
                            scope: this,
                            clickEvent:'mousedown'
                        })
                    }, {
                        itemId:'backcolor',
                        cls:'x-btn-icon x-edit-backcolor',
                        clickEvent:'mousedown',
                        tooltip: editor.buttonTips['backcolor'] || undefined,
                        tabIndex:-1,
                        menu : new Ext.menu.ColorMenu({
                            focus: Ext.emptyFn,
                            value:'FFFFFF',
                            plain:true,
                            allowReselect: true,
                            selectHandler: function(cp, color){
                                if(Ext.isGecko){
                                    this.execCmd('useCSS', false);
                                    this.execCmd('hilitecolor', color);
                                    this.execCmd('useCSS', true);
                                    this.deferFocus();
                                }else{
                                    this.execCmd(Ext.isOpera ? 'hilitecolor' : 'backcolor', Ext.isSafari || Ext.isIE ? '#'+color : color);
                                    this.deferFocus();
                                }
                            },
                            scope:this,
                            clickEvent:'mousedown'
                        })
                    }
                );
            };

            if(this.enableAlignments){
                tb.add(
                    '-',
                    btn('justifyleft'),
                    btn('justifycenter'),
                    btn('justifyright')
                );
            };

            if(!Ext.isSafari){
                if(this.enableLinks){
                    tb.add(
                        '-',
                        btn('createlink', false, this.createLink)
                    );
                };

                if(this.enableLists){
                    tb.add(
                        '-',
                        btn('insertorderedlist'),
                        btn('insertunorderedlist')
                    );
                }
                if(this.enableSourceEdit){
                    tb.add(
                        '-',
                        btn('sourceedit', true, function(btn){
                            this.toggleSourceEdit(btn.pressed);
                        })
                    );
                }
            }

            this.tb = tb;
        },

        getDocMarkup : function(){
            return '';
        },

        getEditorBody : function(){
            return this.doc.body || this.doc.documentElement;
        },

        onRender : function(ct, position){
            Ext.form.HtmlEditor.superclass.onRender.call(this, ct, position);
            this.el.dom.style.border = '0 none';
            this.el.dom.setAttribute('tabIndex', -1);
            this.el.addClass('x-hidden');
            if(Ext.isIE){
                this.el.applyStyles('margin-top:-1px;margin-bottom:-1px;')
            }
            this.wrap = this.el.wrap({
                cls:'x-html-editor-wrap', cn:{cls:'x-html-editor-tb'}
            });

            this.createToolbar(this);

            this.tb.items.each(function(item){
               if(item.itemId != 'sourceedit'){
                    item.disable();
                }
            });

            var iframe = document.createElement('iframe');
            iframe.name = Ext.id();
            iframe.frameBorder = 'no';

            iframe.src=(Ext.SSL_SECURE_URL || "javascript:false");

            this.wrap.dom.appendChild(iframe);

            this.iframe = iframe;

            if(Ext.isIE){
                iframe.contentWindow.document.designMode = 'on';
                this.doc = iframe.contentWindow.document;
                this.win = iframe.contentWindow;
            } else {
                this.doc = (iframe.contentDocument || window.frames[iframe.name].document);
                this.win = window.frames[iframe.name];
                this.doc.designMode = 'on';
            }
            this.doc.open();
            this.doc.write(this.getDocMarkup())
            this.doc.close();

            var task = {
                run : function(){
                    if(this.doc.body || this.doc.readyState == 'complete'){
                        Ext.TaskMgr.stop(task);
                        this.doc.designMode="on";
                        this.initEditor.defer(10, this);
                    }
                },
                interval : 10,
                duration:10000,
                scope: this
            };
            Ext.TaskMgr.start(task);

            if(!this.width){
                this.setSize(this.el.getSize());
            }
        },

        onResize : function(w, h){
            Ext.form.HtmlEditor.superclass.onResize.apply(this, arguments);
            if(this.el && this.iframe){
                if(typeof w == 'number'){
                    var aw = w - this.wrap.getFrameWidth('lr');
                    this.el.setWidth(this.adjustWidth('textarea', aw));
                    this.iframe.style.width = aw + 'px';
                }
                if(typeof h == 'number'){
                    var ah = h - this.wrap.getFrameWidth('tb') - this.tb.el.getHeight();
                    this.el.setHeight(this.adjustWidth('textarea', ah));
                    this.iframe.style.height = ah + 'px';
                    if(this.doc){
                        this.getEditorBody().style.height = (ah - (this.iframePad*2)) + 'px';
                    }
                }
            }
        },

        toggleSourceEdit : function(sourceEditMode){
            if(sourceEditMode === undefined){
                sourceEditMode = !this.sourceEditMode;
            }
            this.sourceEditMode = sourceEditMode === true;
            var btn = this.tb.items.get('sourceedit');
            if(btn.pressed !== this.sourceEditMode){
                btn.toggle(this.sourceEditMode);
                return;
            }
            if(this.sourceEditMode){
                this.tb.items.each(function(item){
                    if(item.itemId != 'sourceedit'){
                        item.disable();
                    }
                });
                this.syncValue();
                this.iframe.className = 'x-hidden';
                this.el.removeClass('x-hidden');
                this.el.dom.removeAttribute('tabIndex');
                this.el.focus();
            }else{
                if(this.initialized){
                    this.tb.items.each(function(item){
                        item.enable();
                    });
                }
                this.pushValue();
                this.iframe.className = '';
                this.el.addClass('x-hidden');
                this.el.dom.setAttribute('tabIndex', -1);
                this.deferFocus();
            }
            var lastSize = this.lastSize;
            if(lastSize){
                delete this.lastSize;
                this.setSize(lastSize);
            }
            this.fireEvent('editmodechange', this, this.sourceEditMode);
        },

        createLink : function(){
            var url = prompt(this.createLinkText, this.defaultLinkValue);
            if(url && url != 'http:/'+'/'){
                this.relayCmd('createlink', url);
            }
        },

        adjustSize : Ext.BoxComponent.prototype.adjustSize,

        getResizeEl : function(){
            return this.wrap;
        },

        getPositionEl : function(){
            return this.wrap;
        },

        initEvents : function(){
            this.originalValue = this.getValue();
        },

        markInvalid : Ext.emptyFn,

        clearInvalid : Ext.emptyFn,

        setValue : function(v){
            Ext.form.HtmlEditor.superclass.setValue.call(this, v);
            this.pushValue();
        },

        cleanHtml : function(html){
            html = String(html);
            if(html.length > 5){
                if(Ext.isSafari){
                    html = html.replace(/\sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi, '');
                }
            }
            if(html == ' '){
                html = '';
            }
            return html;
        },

        syncValue : function(){
            if(this.initialized){
                var bd = this.getEditorBody();
                var html = bd.innerHTML;
                if(Ext.isSafari){
                    var bs = bd.getAttribute('style');
                    var m = bs.match(/text-align:(.*?);/i);
                    if(m && m[1]){
                        html = '' + html + '';
                    }
                }
                html = this.cleanHtml(html);
                if(this.fireEvent('beforesync', this, html) !== false){
                    this.el.dom.value = html;
                    this.fireEvent('sync', this, html);
                }
            }
        },

        pushValue : function(){
            if(this.initialized){
                var v = this.el.dom.value;
                if(!this.activated && v.length < 1){
                    v = ' ';
                }
                if(this.fireEvent('beforepush', this, v) !== false){
                    this.getEditorBody().innerHTML = v;
                    this.fireEvent('push', this, v);
                }
            }
        },

        deferFocus : function(){
            this.focus.defer(10, this);
        },

        focus : function(){
            if(this.win && !this.sourceEditMode){
                this.win.focus();
            }else{
                this.el.focus();
            }
        },

        initEditor : function(){
            var dbody = this.getEditorBody();
            var ss = this.el.getStyles('font-size', 'font-family', 'background-image', 'background-repeat');
            ss['background-attachment'] = 'fixed';
            dbody.bgProperties = 'fixed';
            Ext.DomHelper.applyStyles(dbody, ss);
            Ext.EventManager.on(this.doc, {
                'mousedown': this.onEditorEvent,
                'dblclick': this.onEditorEvent,
                'click': this.onEditorEvent,
                'keyup': this.onEditorEvent,
                buffer:100,
                scope: this
            });
            if(Ext.isGecko){
                Ext.EventManager.on(this.doc, 'keypress', this.applyCommand, this);
            }
            if(Ext.isIE || Ext.isSafari || Ext.isOpera){
                Ext.EventManager.on(this.doc, 'keydown', this.fixKeys, this);
            }
            this.initialized = true;

            this.fireEvent('initialize', this);
            this.pushValue();
        },

        onDestroy : function(){
            if(this.rendered){
                this.tb.items.each(function(item){
                    if(item.menu){
                        item.menu.removeAll();
                        if(item.menu.el){
                            item.menu.el.destroy();
                        }
                    }
                    item.destroy();
                });
                this.wrap.dom.innerHTML = '';
                this.wrap.remove();
            }
        },

        onFirstFocus : function(){
            this.activated = true;
            this.tb.items.each(function(item){
               item.enable();
            });
            if(Ext.isGecko){
                this.win.focus();
                var s = this.win.getSelection();
                if(!s.focusNode || s.focusNode.nodeType != 3){
                    var r = s.getRangeAt(0);
                    r.selectNodeContents(this.getEditorBody());
                    r.collapse(true);
                    this.deferFocus();
                }
                try{
                    this.execCmd('useCSS', true);
                    this.execCmd('styleWithCSS', false);
                }catch(e){}
            }
            this.fireEvent('activate', this);
        },

        adjustFont: function(btn){
            var adjust = btn.itemId == 'increasefontsize' ? 1 : -1;

            var v = parseInt(this.doc.queryCommandValue('FontSize') || 2, 10);
            if(Ext.isSafari3 || Ext.isAir){

                if(v <= 10){
                    v = 1 + adjust;
                }else if(v <= 13){
                    v = 2 + adjust;
                }else if(v <= 16){
                    v = 3 + adjust;
                }else if(v <= 18){
                    v = 4 + adjust;
                }else if(v <= 24){
                    v = 5 + adjust;
                }else {
                    v = 6 + adjust;
                }
                v = v.constrain(1, 6);
            }else{
                if(Ext.isSafari){
                    adjust *= 2;
                }
                v = Math.max(1, v+adjust) + (Ext.isSafari ? 'px' : 0);
            }
            this.execCmd('FontSize', v);
        },

        onEditorEvent : function(e){
            this.updateToolbar();
        },

        updateToolbar: function(){

            if(!this.activated){
                this.onFirstFocus();
                return;
            }

            var btns = this.tb.items.map, doc = this.doc;

            if(this.enableFont && !Ext.isSafari){
                var name = (this.doc.queryCommandValue('FontName')||this.defaultFont).toLowerCase();
                if(name != this.fontSelect.dom.value){
                    this.fontSelect.dom.value = name;
                }
            }
            if(this.enableFormat){
                btns.bold.toggle(doc.queryCommandState('bold'));
                btns.italic.toggle(doc.queryCommandState('italic'));
                btns.underline.toggle(doc.queryCommandState('underline'));
            }
            if(this.enableAlignments){
                btns.justifyleft.toggle(doc.queryCommandState('justifyleft'));
                btns.justifycenter.toggle(doc.queryCommandState('justifycenter'));
                btns.justifyright.toggle(doc.queryCommandState('justifyright'));
            }
            if(!Ext.isSafari && this.enableLists){
                btns.insertorderedlist.toggle(doc.queryCommandState('insertorderedlist'));
                btns.insertunorderedlist.toggle(doc.queryCommandState('insertunorderedlist'));
            }

            Ext.menu.MenuMgr.hideAll();

            this.syncValue();
        },

        relayBtnCmd : function(btn){
            this.relayCmd(btn.itemId);
        },

        relayCmd : function(cmd, value){
            this.win.focus();
            this.execCmd(cmd, value);
            this.updateToolbar();
            this.deferFocus();
        },

        execCmd : function(cmd, value){
            this.doc.execCommand(cmd, false, value === undefined ? null : value);
            this.syncValue();
        },

        applyCommand : function(e){
            if(e.ctrlKey){
                var c = e.getCharCode(), cmd;
                if(c > 0){
                    c = String.fromCharCode(c);
                    switch(c){
                        case 'b':
                            cmd = 'bold';
                        break;
                        case 'i':
                            cmd = 'italic';
                        break;
                        case 'u':
                            cmd = 'underline';
                        break;
                    }
                    if(cmd){
                        this.win.focus();
                        this.execCmd(cmd);
                        this.deferFocus();
                        e.preventDefault();
                    }
                }
            }
        },

        insertAtCursor : function(text){
            if(!this.activated){
                return;
            }
            if(Ext.isIE){
                this.win.focus();
                var r = this.doc.selection.createRange();
                if(r){
                    r.collapse(true);
                    r.pasteHTML(text);
                    this.syncValue();
                    this.deferFocus();
                }
            }else if(Ext.isGecko || Ext.isOpera){
                this.win.focus();
                this.execCmd('InsertHTML', text);
                this.deferFocus();
            }else if(Ext.isSafari){
                this.execCmd('InsertText', text);
                this.deferFocus();
            }
        },

        fixKeys : function(){
            if(Ext.isIE){
                return function(e){
                    var k = e.getKey(), r;
                    if(k == e.TAB){
                        e.stopEvent();
                        r = this.doc.selection.createRange();
                        if(r){
                            r.collapse(true);
                            r.pasteHTML('    ');
                            this.deferFocus();
                        }
                    }else if(k == e.ENTER){
                        r = this.doc.selection.createRange();
                        if(r){
                            var target = r.parentElement();
                            if(!target || target.tagName.toLowerCase() != 'li'){
                                e.stopEvent();
                                r.pasteHTML('
    ');
                                r.collapse(false);
                                r.select();
                            }
                        }
                    }
                };
            }else if(Ext.isOpera){
                return function(e){
                    var k = e.getKey();
                    if(k == e.TAB){
                        e.stopEvent();
                        this.win.focus();
                        this.execCmd('InsertHTML','    ');
                        this.deferFocus();
                    }
                };
            }else if(Ext.isSafari){
                return function(e){
                    var k = e.getKey();
                    if(k == e.TAB){
                        e.stopEvent();
                        this.execCmd('InsertText','\t');
                        this.deferFocus();
                    }
                 };
            }
        }(),

        getToolbar : function(){
            return this.tb;
        },

        buttonTips : {
            bold : {
                title: 'Bold (Ctrl+B)',
                text: 'Make the selected text bold.',
                cls: 'x-html-editor-tip'
            },
            italic : {
                title: 'Italic (Ctrl+I)',
                text: 'Make the selected text italic.',
                cls: 'x-html-editor-tip'
            },
            underline : {
                title: 'Underline (Ctrl+U)',
                text: 'Underline the selected text.',
                cls: 'x-html-editor-tip'
            },
            increasefontsize : {
                title: 'Grow Text',
                text: 'Increase the font size.',
                cls: 'x-html-editor-tip'
            },
            decreasefontsize : {
                title: 'Shrink Text',
                text: 'Decrease the font size.',
                cls: 'x-html-editor-tip'
            },
            backcolor : {
                title: 'Text Highlight Color',
                text: 'Change the background color of the selected text.',
                cls: 'x-html-editor-tip'
            },
            forecolor : {
                title: 'Font Color',
                text: 'Change the color of the selected text.',
                cls: 'x-html-editor-tip'
            },
            justifyleft : {
                title: 'Align Text Left',
                text: 'Align text to the left.',
                cls: 'x-html-editor-tip'
            },
            justifycenter : {
                title: 'Center Text',
                text: 'Center text in the editor.',
                cls: 'x-html-editor-tip'
            },
            justifyright : {
                title: 'Align Text Right',
                text: 'Align text to the right.',
                cls: 'x-html-editor-tip'
            },
            insertunorderedlist : {
                title: 'Bullet List',
                text: 'Start a bulleted list.',
                cls: 'x-html-editor-tip'
            },
            insertorderedlist : {
                title: 'Numbered List',
                text: 'Start a numbered list.',
                cls: 'x-html-editor-tip'
            },
            createlink : {
                title: 'Hyperlink',
                text: 'Make the selected text a hyperlink.',
                cls: 'x-html-editor-tip'
            },
            sourceedit : {
                title: 'Source Edit',
                text: 'Switch to source editing mode.',
                cls: 'x-html-editor-tip'
            }
        }

    });
    Ext.reg('htmleditor', Ext.form.HtmlEditor);

    Ext.form.TimeField = Ext.extend(Ext.form.ComboBox, {

        minValue : null,

        maxValue : null,

        minText : "The time in this field must be equal to or after {0}",

        maxText : "The time in this field must be equal to or before {0}",

        invalidText : "{0} is not a valid time",

        format : "g:i A",

        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",

        increment: 15,

        mode: 'local',

        triggerAction: 'all',

        typeAhead: false,

        initComponent : function(){
            Ext.form.TimeField.superclass.initComponent.call(this);

            if(typeof this.minValue == "string"){
                this.minValue = this.parseDate(this.minValue);
            }
            if(typeof this.maxValue == "string"){
                this.maxValue = this.parseDate(this.maxValue);
            }

            if(!this.store){
                var min = this.parseDate(this.minValue);
                if(!min){
                    min = new Date().clearTime();
                }
                var max = this.parseDate(this.maxValue);
                if(!max){
                    max = new Date().clearTime().add('mi', (24 * 60) - 1);
                }
                var times = [];
                while(min <= max){
                    times.push([min.dateFormat(this.format)]);
                    min = min.add('mi', this.increment);
                }
                this.store = new Ext.data.SimpleStore({
                    fields: ['text'],
                    data : times
                });
                this.displayField = 'text';
            }
        },

        getValue : function(){
            var v = Ext.form.TimeField.superclass.getValue.call(this);
            return this.formatDate(this.parseDate(v)) || '';
        },

        setValue : function(value){
            Ext.form.TimeField.superclass.setValue.call(this, this.formatDate(this.parseDate(value)));
        },

        validateValue : Ext.form.DateField.prototype.validateValue,
        parseDate : Ext.form.DateField.prototype.parseDate,
        formatDate : Ext.form.DateField.prototype.formatDate,

        beforeBlur : function(){
            var v = this.parseDate(this.getRawValue());
            if(v){
                this.setValue(v.dateFormat(this.format));
            }
        }

    });
    Ext.reg('timefield', Ext.form.TimeField);
    Ext.form.Label = Ext.extend(Ext.BoxComponent, {
        onRender : function(ct, position){
            if(!this.el){
                this.el = document.createElement('label');
                this.el.innerHTML = this.text ? Ext.util.Format.htmlEncode(this.text) : (this.html || '');
                if(this.forId){
                    this.el.setAttribute('htmlFor', this.forId);
                }
            }
            Ext.form.Label.superclass.onRender.call(this, ct, position);
        }
    });

    Ext.reg('label', Ext.form.Label);

    Ext.form.Action = function(form, options){
        this.form = form;
        this.options = options || {};
    };

    Ext.form.Action.CLIENT_INVALID = 'client';

    Ext.form.Action.SERVER_INVALID = 'server';

    Ext.form.Action.CONNECT_FAILURE = 'connect';

    Ext.form.Action.LOAD_FAILURE = 'load';

    Ext.form.Action.prototype = {

        type : 'default',

            run : function(options){

        },

            success : function(response){

        },

            handleResponse : function(response){

        },

            failure : function(response){
            this.response = response;
            this.failureType = Ext.form.Action.CONNECT_FAILURE;
            this.form.afterAction(this, false);
        },

            processResponse : function(response){
            this.response = response;
            if(!response.responseText){
                return true;
            }
            this.result = this.handleResponse(response);
            return this.result;
        },

            getUrl : function(appendParams){
            var url = this.options.url || this.form.url || this.form.el.dom.action;
            if(appendParams){
                var p = this.getParams();
                if(p){
                    url += (url.indexOf('?') != -1 ? '&' : '?') + p;
                }
            }
            return url;
        },

            getMethod : function(){
            return (this.options.method || this.form.method || this.form.el.dom.method || 'POST').toUpperCase();
        },

            getParams : function(){
            var bp = this.form.baseParams;
            var p = this.options.params;
            if(p){
                if(typeof p == "object"){
                    p = Ext.urlEncode(Ext.applyIf(p, bp));
                }else if(typeof p == 'string' && bp){
                    p += '&' + Ext.urlEncode(bp);
                }
            }else if(bp){
                p = Ext.urlEncode(bp);
            }
            return p;
        },

            createCallback : function(opts){
    		var opts = opts || {};
            return {
                success: this.success,
                failure: this.failure,
                scope: this,
                timeout: (opts.timeout*1000) || (this.form.timeout*1000),
                upload: this.form.fileUpload ? this.success : undefined
            };
        }
    };

    Ext.form.Action.Submit = function(form, options){
        Ext.form.Action.Submit.superclass.constructor.call(this, form, options);
    };

    Ext.extend(Ext.form.Action.Submit, Ext.form.Action, {

        type : 'submit',

            run : function(){
            var o = this.options;
            var method = this.getMethod();
            var isPost = method == 'POST';
            if(o.clientValidation === false || this.form.isValid()){
                Ext.Ajax.request(Ext.apply(this.createCallback(o), {
                    form:this.form.el.dom,
                    url:this.getUrl(!isPost),
                    method: method,
                    params:isPost ? this.getParams() : null,
                    isUpload: this.form.fileUpload
                }));

            }else if (o.clientValidation !== false){             this.failureType = Ext.form.Action.CLIENT_INVALID;
                this.form.afterAction(this, false);
            }
        },

            success : function(response){
            var result = this.processResponse(response);
            if(result === true || result.success){
                this.form.afterAction(this, true);
                return;
            }
            if(result.errors){
                this.form.markInvalid(result.errors);
                this.failureType = Ext.form.Action.SERVER_INVALID;
            }
            this.form.afterAction(this, false);
        },

            handleResponse : function(response){
            if(this.form.errorReader){
                var rs = this.form.errorReader.read(response);
                var errors = [];
                if(rs.records){
                    for(var i = 0, len = rs.records.length; i < len; i++) {
                        var r = rs.records[i];
                        errors[i] = r.data;
                    }
                }
                if(errors.length < 1){
                    errors = null;
                }
                return {
                    success : rs.success,
                    errors : errors
                };
            }
            return Ext.decode(response.responseText);
        }
    });

    Ext.form.Action.Load = function(form, options){
        Ext.form.Action.Load.superclass.constructor.call(this, form, options);
        this.reader = this.form.reader;
    };

    Ext.extend(Ext.form.Action.Load, Ext.form.Action, {
            type : 'load',

            run : function(){
            Ext.Ajax.request(Ext.apply(
                    this.createCallback(this.options), {
                        method:this.getMethod(),
                        url:this.getUrl(false),
                        params:this.getParams()
            }));
        },

            success : function(response){
            var result = this.processResponse(response);
            if(result === true || !result.success || !result.data){
                this.failureType = Ext.form.Action.LOAD_FAILURE;
                this.form.afterAction(this, false);
                return;
            }
            this.form.clearInvalid();
            this.form.setValues(result.data);
            this.form.afterAction(this, true);
        },

            handleResponse : function(response){
            if(this.form.reader){
                var rs = this.form.reader.read(response);
                var data = rs.records && rs.records[0] ? rs.records[0].data : null;
                return {
                    success : rs.success,
                    data : data
                };
            }
            return Ext.decode(response.responseText);
        }
    });

    Ext.form.Action.ACTION_TYPES = {
        'load' : Ext.form.Action.Load,
        'submit' : Ext.form.Action.Submit
    };

    Ext.form.VTypes = function(){
            var alpha = /^[a-zA-Z_]+$/;
        var alphanum = /^[a-zA-Z0-9_]+$/;
        var email = /^([\w]+)(.[\w]+)*@([\w-]+\.){1,5}([A-Za-z]){2,4}$/;
        var url = /(((https?)|(ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;

            return {

            'email' : function(v){
                return email.test(v);
            },

            'emailText' : 'This field should be an e-mail address in the format "user@domain.com"',

            'emailMask' : /[a-z0-9_\.\-@]/i,

            'url' : function(v){
                return url.test(v);
            },

            'urlText' : 'This field should be a URL in the format "http:/'+'/www.domain.com"',

            'alpha' : function(v){
                return alpha.test(v);
            },

            'alphaText' : 'This field should only contain letters and _',

            'alphaMask' : /[a-z_]/i,

            'alphanum' : function(v){
                return alphanum.test(v);
            },

            'alphanumText' : 'This field should only contain letters, numbers and _',

            'alphanumMask' : /[a-z0-9_]/i
        };
    }();

    Ext.grid.GridPanel = Ext.extend(Ext.Panel, {

        ddText : "{0} selected row{1}",

        minColumnWidth : 25,

        trackMouseOver : true,

        enableDragDrop : false,

        enableColumnMove : true,

        enableColumnHide : true,

        enableHdMenu : true,

        stripeRows : false,

        autoExpandColumn : false,

        autoExpandMin : 50,

        autoExpandMax : 1000,

        view : null,

        loadMask : false,

        rendered : false,

        viewReady: false,

        stateEvents: ["columnmove", "columnresize", "sortchange"],

        initComponent : function(){
            Ext.grid.GridPanel.superclass.initComponent.call(this);

            this.autoScroll = false;
            this.autoWidth = false;

            if(Ext.isArray(this.columns)){
                this.colModel = new Ext.grid.ColumnModel(this.columns);
                delete this.columns;
            }

            if(this.ds){
                this.store = this.ds;
                delete this.ds;
            }
            if(this.cm){
                this.colModel = this.cm;
                delete this.cm;
            }
            if(this.sm){
                this.selModel = this.sm;
                delete this.sm;
            }
            this.store = Ext.StoreMgr.lookup(this.store);

            this.addEvents(

                "click",

                "dblclick",

                "contextmenu",

                "mousedown",

                "mouseup",

                "mouseover",

                "mouseout",

                "keypress",

                "keydown",

                "cellmousedown",

                "rowmousedown",

                "headermousedown",

                "cellclick",

                "celldblclick",

                "rowclick",

                "rowdblclick",

                "headerclick",

                "headerdblclick",

                "rowcontextmenu",

                "cellcontextmenu",

                "headercontextmenu",

                "bodyscroll",

                "columnresize",

                "columnmove",

                "sortchange"
            );
        },

        onRender : function(ct, position){
            Ext.grid.GridPanel.superclass.onRender.apply(this, arguments);

            var c = this.body;

            this.el.addClass('x-grid-panel');

            var view = this.getView();
            view.init(this);

            c.on("mousedown", this.onMouseDown, this);
            c.on("click", this.onClick, this);
            c.on("dblclick", this.onDblClick, this);
            c.on("contextmenu", this.onContextMenu, this);
            c.on("keydown", this.onKeyDown, this);

            this.relayEvents(c, ["mousedown","mouseup","mouseover","mouseout","keypress"]);

            this.getSelectionModel().init(this);
            this.view.render();
        },

        initEvents : function(){
            Ext.grid.GridPanel.superclass.initEvents.call(this);

            if(this.loadMask){
                this.loadMask = new Ext.LoadMask(this.bwrap,
                        Ext.apply({store:this.store}, this.loadMask));
            }
        },

        initStateEvents : function(){
            Ext.grid.GridPanel.superclass.initStateEvents.call(this);
            this.colModel.on('hiddenchange', this.saveState, this, {delay: 100});
        },

        applyState : function(state){
            var cm = this.colModel;
            var cs = state.columns;
            if(cs){
                for(var i = 0, len = cs.length; i < len; i++){
                    var s = cs[i];
                    var c = cm.getColumnById(s.id);
                    if(c){
                        c.hidden = s.hidden;
                        c.width = s.width;
                        var oldIndex = cm.getIndexById(s.id);
                        if(oldIndex != i){
                            cm.moveColumn(oldIndex, i);
                        }
                    }
                }
            }
            if(state.sort){
                this.store[this.store.remoteSort ? 'setDefaultSort' : 'sort'](state.sort.field, state.sort.direction);
            }
        },

        getState : function(){
            var o = {columns: []};
            for(var i = 0, c; c = this.colModel.config[i]; i++){
                o.columns[i] = {
                    id: c.id,
                    width: c.width
                };
                if(c.hidden){
                    o.columns[i].hidden = true;
                }
            }
            var ss = this.store.getSortState();
            if(ss){
                o.sort = ss;
            }
            return o;
        },

        afterRender : function(){
            Ext.grid.GridPanel.superclass.afterRender.call(this);
            this.view.layout();
            this.viewReady = true;
        },

        reconfigure : function(store, colModel){
            if(this.loadMask){
                this.loadMask.destroy();
                this.loadMask = new Ext.LoadMask(this.bwrap,
                        Ext.apply({store:store}, this.initialConfig.loadMask));
            }
            this.view.bind(store, colModel);
            this.store = store;
            this.colModel = colModel;
            if(this.rendered){
                this.view.refresh(true);
            }
        },

        onKeyDown : function(e){
            this.fireEvent("keydown", e);
        },

        onDestroy : function(){
            if(this.rendered){
                if(this.loadMask){
                    this.loadMask.destroy();
                }
                var c = this.body;
                c.removeAllListeners();
                this.view.destroy();
                c.update("");
            }
            this.colModel.purgeListeners();
            Ext.grid.GridPanel.superclass.onDestroy.call(this);
        },

        processEvent : function(name, e){
            this.fireEvent(name, e);
            var t = e.getTarget();
            var v = this.view;
            var header = v.findHeaderIndex(t);
            if(header !== false){
                this.fireEvent("header" + name, this, header, e);
            }else{
                var row = v.findRowIndex(t);
                var cell = v.findCellIndex(t);
                if(row !== false){
                    this.fireEvent("row" + name, this, row, e);
                    if(cell !== false){
                        this.fireEvent("cell" + name, this, row, cell, e);
                    }
                }
            }
        },

        onClick : function(e){
            this.processEvent("click", e);
        },

        onMouseDown : function(e){
            this.processEvent("mousedown", e);
        },

        onContextMenu : function(e, t){
            this.processEvent("contextmenu", e);
        },

        onDblClick : function(e){
            this.processEvent("dblclick", e);
        },

        walkCells : function(row, col, step, fn, scope){
            var cm = this.colModel, clen = cm.getColumnCount();
            var ds = this.store, rlen = ds.getCount(), first = true;
            if(step < 0){
                if(col < 0){
                    row--;
                    first = false;
                }
                while(row >= 0){
                    if(!first){
                        col = clen-1;
                    }
                    first = false;
                    while(col >= 0){
                        if(fn.call(scope || this, row, col, cm) === true){
                            return [row, col];
                        }
                        col--;
                    }
                    row--;
                }
            } else {
                if(col >= clen){
                    row++;
                    first = false;
                }
                while(row < rlen){
                    if(!first){
                        col = 0;
                    }
                    first = false;
                    while(col < clen){
                        if(fn.call(scope || this, row, col, cm) === true){
                            return [row, col];
                        }
                        col++;
                    }
                    row++;
                }
            }
            return null;
        },

        getSelections : function(){
            return this.selModel.getSelections();
        },

        onResize : function(){
            Ext.grid.GridPanel.superclass.onResize.apply(this, arguments);
            if(this.viewReady){
                this.view.layout();
            }
        },

        getGridEl : function(){
            return this.body;
        },

        stopEditing : function(){},

        getSelectionModel : function(){
            if(!this.selModel){
                this.selModel = new Ext.grid.RowSelectionModel(
                        this.disableSelection ? {selectRow: Ext.emptyFn} : null);
            }
            return this.selModel;
        },

        getStore : function(){
            return this.store;
        },

        getColumnModel : function(){
            return this.colModel;
        },

        getView : function(){
            if(!this.view){
                this.view = new Ext.grid.GridView(this.viewConfig);
            }
            return this.view;
        },

        getDragDropText : function(){
            var count = this.selModel.getCount();
            return String.format(this.ddText, count, count == 1 ? '' : 's');
        }

    });
    Ext.reg('grid', Ext.grid.GridPanel);

    Ext.grid.GridView = function(config){
        Ext.apply(this, config);
            this.addEvents(

          "beforerowremoved",

          "beforerowsinserted",

          "beforerefresh",

          "rowremoved",

          "rowsinserted",

          "rowupdated",

          "refresh"
      );
        Ext.grid.GridView.superclass.constructor.call(this);
    };

    Ext.extend(Ext.grid.GridView, Ext.util.Observable, {

        scrollOffset: 19,

        autoFill: false,

        forceFit: false,

        sortClasses : ["sort-asc", "sort-desc"],

        sortAscText : "Sort Ascending",

        sortDescText : "Sort Descending",

        columnsText : "Columns",

            borderWidth: 2,

            initTemplates : function(){
            var ts = this.templates || {};
            if(!ts.master){
                ts.master = new Ext.Template(
                        '',
                            '',
                                '{header}',
                                '{body}',
                            "",
                            ' ',
                            ' ',
                        ""
                        );
            }

            if(!ts.header){
                ts.header = new Ext.Template(
                        '',
                        '{cells}',
                        ""
                        );
            }

            if(!ts.hcell){
                ts.hcell = new Ext.Template(
                        '', this.grid.enableHdMenu ? '' : '',
                        '{value}',
                        ""
                        );
            }

            if(!ts.body){
                ts.body = new Ext.Template('{rows}');
            }

            if(!ts.row){
                ts.row = new Ext.Template(
                        '',
                        '{cells}',
                        (this.enableRowBody ? '{body}' : ''),
                        ''
                        );
            }

            if(!ts.cell){
                ts.cell = new Ext.Template(
                        '',
                        '{value}',
                        ""
                        );
            }

            for(var k in ts){
                var t = ts[k];
                if(t && typeof t.compile == 'function' && !t.compiled){
                    t.disableFormats = true;
                    t.compile();
                }
            }

            this.templates = ts;

            this.tdClass = 'x-grid3-cell';
            this.cellSelector = 'td.x-grid3-cell';
            this.hdCls = 'x-grid3-hd';
            this.rowSelector = 'div.x-grid3-row';
            this.colRe = new RegExp("x-grid3-td-([^\\s]+)", "");
        },

            fly : function(el){
            if(!this._flyweight){
                this._flyweight = new Ext.Element.Flyweight(document.body);
            }
            this._flyweight.dom = el;
            return this._flyweight;
        },

            getEditorParent : function(ed){
            return this.scroller.dom;
        },

            initElements : function(){
            var E = Ext.Element;

            var el = this.grid.getGridEl().dom.firstChild;
            var cs = el.childNodes;

            this.el = new E(el);

            this.mainWrap = new E(cs[0]);
            this.mainHd = new E(this.mainWrap.dom.firstChild);

            if(this.grid.hideHeaders){
                this.mainHd.setDisplayed(false);
            }

            this.innerHd = this.mainHd.dom.firstChild;
            this.scroller = new E(this.mainWrap.dom.childNodes[1]);
            if(this.forceFit){
                this.scroller.setStyle('overflow-x', 'hidden');
            }
            this.mainBody = new E(this.scroller.dom.firstChild);

            this.focusEl = new E(this.scroller.dom.childNodes[1]);
            this.focusEl.swallowEvent("click", true);

            this.resizeMarker = new E(cs[1]);
            this.resizeProxy = new E(cs[2]);
        },

            getRows : function(){
            return this.hasRows() ? this.mainBody.dom.childNodes : [];
        },

            findCell : function(el){
            if(!el){
                return false;
            }
            return this.fly(el).findParent(this.cellSelector, 3);
        },

            findCellIndex : function(el, requiredCls){
            var cell = this.findCell(el);
            if(cell && (!requiredCls || this.fly(cell).hasClass(requiredCls))){
                return this.getCellIndex(cell);
            }
            return false;
        },

            getCellIndex : function(el){
            if(el){
                var m = el.className.match(this.colRe);
                if(m && m[1]){
                    return this.cm.getIndexById(m[1]);
                }
            }
            return false;
        },

            findHeaderCell : function(el){
            var cell = this.findCell(el);
            return cell && this.fly(cell).hasClass(this.hdCls) ? cell : null;
        },

            findHeaderIndex : function(el){
            return this.findCellIndex(el, this.hdCls);
        },

            findRow : function(el){
            if(!el){
                return false;
            }
            return this.fly(el).findParent(this.rowSelector, 10);
        },

            findRowIndex : function(el){
            var r = this.findRow(el);
            return r ? r.rowIndex : false;
        },

        getRow : function(row){
            return this.getRows()[row];
        },

        getCell : function(row, col){
            return this.getRow(row).getElementsByTagName('td')[col];
        },

        getHeaderCell : function(index){
          return this.mainHd.dom.getElementsByTagName('td')[index];
        },

            addRowClass : function(row, cls){
            var r = this.getRow(row);
            if(r){
                this.fly(r).addClass(cls);
            }
        },

            removeRowClass : function(row, cls){
            var r = this.getRow(row);
            if(r){
                this.fly(r).removeClass(cls);
            }
        },

            removeRow : function(row){
            Ext.removeNode(this.getRow(row));
        },

            removeRows : function(firstRow, lastRow){
            var bd = this.mainBody.dom;
            for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){
                Ext.removeNode(bd.childNodes[firstRow]);
            }
        },

            getScrollState : function(){
            var sb = this.scroller.dom;
            return {left: sb.scrollLeft, top: sb.scrollTop};
        },

            restoreScroll : function(state){
            var sb = this.scroller.dom;
            sb.scrollLeft = state.left;
            sb.scrollTop = state.top;
        },

        scrollToTop : function(){
            this.scroller.dom.scrollTop = 0;
            this.scroller.dom.scrollLeft = 0;
        },

            syncScroll : function(){
          this.syncHeaderScroll();
          var mb = this.scroller.dom;
            this.grid.fireEvent("bodyscroll", mb.scrollLeft, mb.scrollTop);
        },

            syncHeaderScroll : function(){
            var mb = this.scroller.dom;
            this.innerHd.scrollLeft = mb.scrollLeft;
            this.innerHd.scrollLeft = mb.scrollLeft;     },

            updateSortIcon : function(col, dir){
            var sc = this.sortClasses;
            var hds = this.mainHd.select('td').removeClass(sc);
            hds.item(col).addClass(sc[dir == "DESC" ? 1 : 0]);
        },

            updateAllColumnWidths : function(){
            var tw = this.getTotalWidth();
            var clen = this.cm.getColumnCount();
            var ws = [];
            for(var i = 0; i < clen; i++){
                ws[i] = this.getColumnWidth(i);
            }

            this.innerHd.firstChild.firstChild.style.width = tw;

            for(var i = 0; i < clen; i++){
                var hd = this.getHeaderCell(i);
                hd.style.width = ws[i];
            }

            var ns = this.getRows();
            for(var i = 0, len = ns.length; i < len; i++){
                ns[i].style.width = tw;
                ns[i].firstChild.style.width = tw;
                var row = ns[i].firstChild.rows[0];
                for(var j = 0; j < clen; j++){
                    row.childNodes[j].style.width = ws[j];
                }
            }

            this.onAllColumnWidthsUpdated(ws, tw);
        },

            updateColumnWidth : function(col, width){
            var w = this.getColumnWidth(col);
            var tw = this.getTotalWidth();

            this.innerHd.firstChild.firstChild.style.width = tw;
            var hd = this.getHeaderCell(col);
            hd.style.width = w;

            var ns = this.getRows();
            for(var i = 0, len = ns.length; i < len; i++){
                ns[i].style.width = tw;
                ns[i].firstChild.style.width = tw;
                ns[i].firstChild.rows[0].childNodes[col].style.width = w;
            }

            this.onColumnWidthUpdated(col, w, tw);
        },

            updateColumnHidden : function(col, hidden){
            var tw = this.getTotalWidth();

            this.innerHd.firstChild.firstChild.style.width = tw;

            var display = hidden ? 'none' : '';

            var hd = this.getHeaderCell(col);
            hd.style.display = display;

            var ns = this.getRows();
            for(var i = 0, len = ns.length; i < len; i++){
                ns[i].style.width = tw;
                ns[i].firstChild.style.width = tw;
                ns[i].firstChild.rows[0].childNodes[col].style.display = display;
            }

            this.onColumnHiddenUpdated(col, hidden, tw);

            delete this.lastViewWidth;         this.layout();
        },

            doRender : function(cs, rs, ds, startRow, colCount, stripe){
            var ts = this.templates, ct = ts.cell, rt = ts.row, last = colCount-1;
            var tstyle = 'width:'+this.getTotalWidth()+';';
                    var buf = [], cb, c, p = {}, rp = {tstyle: tstyle}, r;
            for(var j = 0, len = rs.length; j < len; j++){
                r = rs[j]; cb = [];
                var rowIndex = (j+startRow);
                for(var i = 0; i < colCount; i++){
                    c = cs[i];
                    p.id = c.id;
                    p.css = i == 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');
                    p.attr = p.cellAttr = "";
                    p.value = c.renderer(r.data[c.name], p, r, rowIndex, i, ds);
                    p.style = c.style;
                    if(p.value == undefined || p.value === "") p.value = " ";
                    if(r.dirty && typeof r.modified[c.name] !== 'undefined'){
                        p.css += ' x-grid3-dirty-cell';
                    }
                    cb[cb.length] = ct.apply(p);
                }
                var alt = [];
                if(stripe && ((rowIndex+1) % 2 == 0)){
                    alt[0] = "x-grid3-row-alt";
                }
                if(r.dirty){
                    alt[1] = " x-grid3-dirty-row";
                }
                rp.cols = colCount;
                if(this.getRowClass){
                    alt[2] = this.getRowClass(r, rowIndex, rp, ds);
                }
                rp.alt = alt.join(" ");
                rp.cells = cb.join("");
                buf[buf.length] =  rt.apply(rp);
            }
            return buf.join("");
        },

            processRows : function(startRow, skipStripe){
            if(this.ds.getCount() < 1){
                return;
            }
            skipStripe = skipStripe || !this.grid.stripeRows;
            startRow = startRow || 0;
            var rows = this.getRows();
            var cls = ' x-grid3-row-alt ';
            for(var i = startRow, len = rows.length; i < len; i++){
                var row = rows[i];
                row.rowIndex = i;
                if(!skipStripe){
                    var isAlt = ((i+1) % 2 == 0);
                    var hasAlt = (' '+row.className + ' ').indexOf(cls) != -1;
                    if(isAlt == hasAlt){
                        continue;
                    }
                    if(isAlt){
                        row.className += " x-grid3-row-alt";
                    }else{
                        row.className = row.className.replace("x-grid3-row-alt", "");
                    }
                }
            }
        },

            renderUI : function(){

            var header = this.renderHeaders();
            var body = this.templates.body.apply({rows:''});

            var html = this.templates.master.apply({
                body: body,
                header: header
            });

            var g = this.grid;

            g.getGridEl().dom.innerHTML = html;

            this.initElements();

            this.mainBody.dom.innerHTML = this.renderRows();
            this.processRows(0, true);

                    Ext.fly(this.innerHd).on("click", this.handleHdDown, this);
            this.mainHd.on("mouseover", this.handleHdOver, this);
            this.mainHd.on("mouseout", this.handleHdOut, this);
            this.mainHd.on("mousemove", this.handleHdMove, this);

            this.scroller.on('scroll', this.syncScroll,  this);
            if(g.enableColumnResize !== false){
                this.splitone = new Ext.grid.GridView.SplitDragZone(g, this.mainHd.dom);
            }

            if(g.enableColumnMove){
                this.columnDrag = new Ext.grid.GridView.ColumnDragZone(g, this.innerHd);
                this.columnDrop = new Ext.grid.HeaderDropZone(g, this.mainHd.dom);
            }

            if(g.enableHdMenu !== false){
                if(g.enableColumnHide !== false){
                    this.colMenu = new Ext.menu.Menu({id:g.id + "-hcols-menu"});
                    this.colMenu.on("beforeshow", this.beforeColMenuShow, this);
                    this.colMenu.on("itemclick", this.handleHdMenuClick, this);
                }
                this.hmenu = new Ext.menu.Menu({id: g.id + "-hctx"});
                this.hmenu.add(
                    {id:"asc", text: this.sortAscText, cls: "xg-hmenu-sort-asc"},
                    {id:"desc", text: this.sortDescText, cls: "xg-hmenu-sort-desc"}
                );
                if(g.enableColumnHide !== false){
                    this.hmenu.add('-',
                        {id:"columns", text: this.columnsText, menu: this.colMenu, iconCls: 'x-cols-icon'}
                    );
                }
                this.hmenu.on("itemclick", this.handleHdMenuClick, this);

                        }

            if(g.enableDragDrop || g.enableDrag){
                var dd = new Ext.grid.GridDragZone(g, {
                    ddGroup : g.ddGroup || 'GridDD'
                });
            }

            this.updateHeaderSortState();

        },

            layout : function(){
            if(!this.mainBody){
                return;         }
            var g = this.grid;
            var c = g.getGridEl(), cm = this.cm,
                    expandCol = g.autoExpandColumn,
                    gv = this;

            var csize = c.getSize(true);
            var vw = csize.width;

            if(vw < 20 || csize.height < 20){             return;
            }

            if(g.autoHeight){
                this.scroller.dom.style.overflow = 'visible';
            }else{
                this.el.setSize(csize.width, csize.height);

                var hdHeight = this.mainHd.getHeight();
                var vh = csize.height - (hdHeight);

                this.scroller.setSize(vw, vh);
                if(this.innerHd){
                    this.innerHd.style.width = (vw)+'px';
                }
            }
            if(this.forceFit){
                if(this.lastViewWidth != vw){
                    this.fitColumns(false, false);
                    this.lastViewWidth = vw;
                }
            }else {
                this.autoExpand();
                this.syncHeaderScroll();
            }
            this.onLayout(vw, vh);
        },

                onLayout : function(vw, vh){
                },

        onColumnWidthUpdated : function(col, w, tw){
                },

        onAllColumnWidthsUpdated : function(ws, tw){
                },

        onColumnHiddenUpdated : function(col, hidden, tw){
                },

        updateColumnText : function(col, text){
                },

        afterMove : function(colIndex){
                },

            init: function(grid){
            this.grid = grid;

            this.initTemplates();
            this.initData(grid.store, grid.colModel);
            this.initUI(grid);
        },

            getColumnId : function(index){
          return this.cm.getColumnId(index);
        },

            renderHeaders : function(){
            var cm = this.cm, ts = this.templates;
            var ct = ts.hcell;

            var cb = [], sb = [], p = {};

            for(var i = 0, len = cm.getColumnCount(); i < len; i++){
                p.id = cm.getColumnId(i);
                p.value = cm.getColumnHeader(i) || "";
                p.style = this.getColumnStyle(i, true);
                p.tooltip = this.getColumnTooltip(i);
                if(cm.config[i].align == 'right'){
                    p.istyle = 'padding-right:16px';
                } else {
                    delete p.istyle;
                }
                cb[cb.length] = ct.apply(p);
            }
            return ts.header.apply({cells: cb.join(""), tstyle:'width:'+this.getTotalWidth()+';'});
        },

            getColumnTooltip : function(i){
            var tt = this.cm.getColumnTooltip(i);
            if(tt){
                if(Ext.QuickTips.isEnabled()){
                    return 'ext:qtip="'+tt+'"';
                }else{
                    return 'title="'+tt+'"';
                }
            }
            return "";
        },

            beforeUpdate : function(){
            this.grid.stopEditing(true);
        },

            updateHeaders : function(){
            this.innerHd.firstChild.innerHTML = this.renderHeaders();
        },

        focusRow : function(row){
            this.focusCell(row, 0, false);
        },

        focusCell : function(row, col, hscroll){
            var xy = this.ensureVisible(row, col, hscroll);
            this.focusEl.setXY(xy);
            if(Ext.isGecko){
                this.focusEl.focus();
            }else{
                this.focusEl.focus.defer(1, this.focusEl);
            }
        },

            ensureVisible : function(row, col, hscroll){
            if(typeof row != "number"){
                row = row.rowIndex;
            }
            if(!this.ds){
                return;
            }
            if(row < 0 || row >= this.ds.getCount()){
                return;
            }
            col = (col !== undefined ? col : 0);

            var rowEl = this.getRow(row), cellEl;
            if(!(hscroll === false && col === 0)){
                while(this.cm.isHidden(col)){
                    col++;
                }
                cellEl = this.getCell(row, col);
            }
            if(!rowEl){
                return;
            }

            var c = this.scroller.dom;

            var ctop = 0;
            var p = rowEl, stop = this.el.dom;
            while(p && p != stop){
                ctop += p.offsetTop;
                p = p.offsetParent;
            }
            ctop -= this.mainHd.dom.offsetHeight;

            var cbot = ctop + rowEl.offsetHeight;

            var ch = c.clientHeight;
            var stop = parseInt(c.scrollTop, 10);
            var sbot = stop + ch;

            if(ctop < stop){
              c.scrollTop = ctop;
            }else if(cbot > sbot){
                c.scrollTop = cbot-ch;
            }

            if(hscroll !== false){
                var cleft = parseInt(cellEl.offsetLeft, 10);
                var cright = cleft + cellEl.offsetWidth;

                var sleft = parseInt(c.scrollLeft, 10);
                var sright = sleft + c.clientWidth;
                if(cleft < sleft){
                    c.scrollLeft = cleft;
                }else if(cright > sright){
                    c.scrollLeft = cright-c.clientWidth;
                }
            }
            return cellEl ? Ext.fly(cellEl).getXY() : [c.scrollLeft, Ext.fly(rowEl).getY()];
        },

            insertRows : function(dm, firstRow, lastRow, isUpdate){
            if(!isUpdate && firstRow === 0 && lastRow == dm.getCount()-1){
                this.refresh();
            }else{
                if(!isUpdate){
                    this.fireEvent("beforerowsinserted", this, firstRow, lastRow);
                }
                var html = this.renderRows(firstRow, lastRow);
                var before = this.getRow(firstRow);
                if(before){
                    Ext.DomHelper.insertHtml('beforeBegin', before, html);
                }else{
                    Ext.DomHelper.insertHtml('beforeEnd', this.mainBody.dom, html);
                }
                if(!isUpdate){
                    this.fireEvent("rowsinserted", this, firstRow, lastRow);
                    this.processRows(firstRow);
                }
            }
        },

            deleteRows : function(dm, firstRow, lastRow){
            if(dm.getRowCount()<1){
                this.refresh();
            }else{
                this.fireEvent("beforerowsdeleted", this, firstRow, lastRow);

                this.removeRows(firstRow, lastRow);

                this.processRows(firstRow);
                this.fireEvent("rowsdeleted", this, firstRow, lastRow);
            }
        },

            getColumnStyle : function(col, isHeader){
            var style = !isHeader ? (this.cm.config[col].css || '') : '';
            style += 'width:'+this.getColumnWidth(col)+';';
            if(this.cm.isHidden(col)){
                style += 'display:none;';
            }
            var align = this.cm.config[col].align;
            if(align){
                style += 'text-align:'+align+';';
            }
            return style;
        },

            getColumnWidth : function(col){
            var w = this.cm.getColumnWidth(col);
            if(typeof w == 'number'){
                return (Ext.isBorderBox ? w : (w-this.borderWidth > 0 ? w-this.borderWidth:0)) + 'px';
            }
            return w;
        },

            getTotalWidth : function(){
            return this.cm.getTotalWidth()+'px';
        },

            fitColumns : function(preventRefresh, onlyExpand, omitColumn){
            var cm = this.cm, leftOver, dist, i;
            var tw = cm.getTotalWidth(false);
            var aw = this.grid.getGridEl().getWidth(true)-this.scrollOffset;

            if(aw < 20){             return;
            }
            var extra = aw - tw;

            if(extra === 0){
                return false;
            }

            var vc = cm.getColumnCount(true);
            var ac = vc-(typeof omitColumn == 'number' ? 1 : 0);
            if(ac === 0){
                ac = 1;
                omitColumn = undefined;
            }
            var colCount = cm.getColumnCount();
            var cols = [];
            var extraCol = 0;
            var width = 0;
            var w;
            for (i = 0; i < colCount; i++){
                if(!cm.isHidden(i) && !cm.isFixed(i) && i !== omitColumn){
                    w = cm.getColumnWidth(i);
                    cols.push(i);
                    extraCol = i;
                    cols.push(w);
                    width += w;
                }
            }
            var frac = (aw - cm.getTotalWidth())/width;
            while (cols.length){
                w = cols.pop();
                i = cols.pop();
                cm.setColumnWidth(i, Math.max(this.grid.minColumnWidth, Math.floor(w + w*frac)), true);
            }

            if((tw = cm.getTotalWidth(false)) > aw){
                var adjustCol = ac != vc ? omitColumn : extraCol;
                 cm.setColumnWidth(adjustCol, Math.max(1,
                         cm.getColumnWidth(adjustCol)- (tw-aw)), true);
            }

            if(preventRefresh !== true){
                this.updateAllColumnWidths();
            }

            return true;
        },

            autoExpand : function(preventUpdate){
            var g = this.grid, cm = this.cm;
            if(!this.userResized && g.autoExpandColumn){
                var tw = cm.getTotalWidth(false);
                var aw = this.grid.getGridEl().getWidth(true)-this.scrollOffset;
                if(tw != aw){
                    var ci = cm.getIndexById(g.autoExpandColumn);
                    var currentWidth = cm.getColumnWidth(ci);
                    var cw = Math.min(Math.max(((aw-tw)+currentWidth), g.autoExpandMin), g.autoExpandMax);
                    if(cw != currentWidth){
                        cm.setColumnWidth(ci, cw, true);
                        if(preventUpdate !== true){
                            this.updateColumnWidth(ci, cw);
                        }
                    }
                }
            }
        },

            getColumnData : function(){
                    var cs = [], cm = this.cm, colCount = cm.getColumnCount();
            for(var i = 0; i < colCount; i++){
                var name = cm.getDataIndex(i);
                cs[i] = {
                    name : (typeof name == 'undefined' ? this.ds.fields.get(i).name : name),
                    renderer : cm.getRenderer(i),
                    id : cm.getColumnId(i),
                    style : this.getColumnStyle(i)
                };
            }
            return cs;
        },

            renderRows : function(startRow, endRow){
                    var g = this.grid, cm = g.colModel, ds = g.store, stripe = g.stripeRows;
            var colCount = cm.getColumnCount();

            if(ds.getCount() < 1){
                return "";
            }

            var cs = this.getColumnData();

            startRow = startRow || 0;
            endRow = typeof endRow == "undefined"? ds.getCount()-1 : endRow;

                    var rs = ds.getRange(startRow, endRow);

            return this.doRender(cs, rs, ds, startRow, colCount, stripe);
        },

            renderBody : function(){
            var markup = this.renderRows();
            return this.templates.body.apply({rows: markup});
        },

            refreshRow : function(record){
            var ds = this.ds, index;
            if(typeof record == 'number'){
                index = record;
                record = ds.getAt(index);
            }else{
                index = ds.indexOf(record);
            }
            var cls = [];
            this.insertRows(ds, index, index, true);
            this.getRow(index).rowIndex = index;
            this.onRemove(ds, record, index+1, true);
            this.fireEvent("rowupdated", this, index, record);
        },

        refresh : function(headersToo){
            this.fireEvent("beforerefresh", this);
            this.grid.stopEditing(true);

            var result = this.renderBody();
            this.mainBody.update(result);

            if(headersToo === true){
                this.updateHeaders();
                this.updateHeaderSortState();
            }
            this.processRows(0, true);
            this.layout();
            this.applyEmptyText();
            this.fireEvent("refresh", this);
        },

            applyEmptyText : function(){
            if(this.emptyText && !this.hasRows()){
                this.mainBody.update('' + this.emptyText + '');
            }
        },

            updateHeaderSortState : function(){
            var state = this.ds.getSortState();
            if(!state){
                return;
            }
            if(!this.sortState || (this.sortState.field != state.field || this.sortState.direction != state.direction)){
                this.grid.fireEvent('sortchange', this.grid, state);
            }
            this.sortState = state;
            var sortColumn = this.cm.findColumnIndex(state.field);
            if(sortColumn != -1){
                var sortDir = state.direction;
                this.updateSortIcon(sortColumn, sortDir);
            }
        },

            destroy : function(){
            if(this.colMenu){
                this.colMenu.removeAll();
                Ext.menu.MenuMgr.unregister(this.colMenu);
                this.colMenu.getEl().remove();
                delete this.colMenu;
            }
            if(this.hmenu){
                this.hmenu.removeAll();
                Ext.menu.MenuMgr.unregister(this.hmenu);
                this.hmenu.getEl().remove();
                delete this.hmenu;
            }
            if(this.grid.enableColumnMove){
                var dds = Ext.dd.DDM.ids['gridHeader' + this.grid.getGridEl().id];
                if(dds){
                    for(var dd in dds){
                        if(!dds[dd].config.isTarget && dds[dd].dragElId){
                            var elid = dds[dd].dragElId;
                            dds[dd].unreg();
                            Ext.get(elid).remove();
                        } else if(dds[dd].config.isTarget){
                            dds[dd].proxyTop.remove();
                            dds[dd].proxyBottom.remove();
                            dds[dd].unreg();
                        }
                        if(Ext.dd.DDM.locationCache[dd]){
                            delete Ext.dd.DDM.locationCache[dd];
                        }
                    }
                    delete Ext.dd.DDM.ids['gridHeader' + this.grid.getGridEl().id];
                }
            }

            Ext.destroy(this.resizeMarker, this.resizeProxy);

            this.initData(null, null);
            Ext.EventManager.removeResizeListener(this.onWindowResize, this);
        },

            onDenyColumnHide : function(){

        },

            render : function(){

            var cm = this.cm;
            var colCount = cm.getColumnCount();

            if(this.autoFill){
                this.fitColumns(true, true);
            }else if(this.forceFit){
                this.fitColumns(true, false);
            }else if(this.grid.autoExpandColumn){
                this.autoExpand(true);
            }

            this.renderUI();
        },

            initData : function(ds, cm){
            if(this.ds){
                this.ds.un("load", this.onLoad, this);
                this.ds.un("datachanged", this.onDataChange, this);
                this.ds.un("add", this.onAdd, this);
                this.ds.un("remove", this.onRemove, this);
                this.ds.un("update", this.onUpdate, this);
                this.ds.un("clear", this.onClear, this);
            }
            if(ds){
                ds.on("load", this.onLoad, this);
                ds.on("datachanged", this.onDataChange, this);
                ds.on("add", this.onAdd, this);
                ds.on("remove", this.onRemove, this);
                ds.on("update", this.onUpdate, this);
                ds.on("clear", this.onClear, this);
            }
            this.ds = ds;

            if(this.cm){
                this.cm.un("configchange", this.onColConfigChange, this);
                this.cm.un("widthchange", this.onColWidthChange, this);
                this.cm.un("headerchange", this.onHeaderChange, this);
                this.cm.un("hiddenchange", this.onHiddenChange, this);
                this.cm.un("columnmoved", this.onColumnMove, this);
                this.cm.un("columnlockchange", this.onColumnLock, this);
            }
            if(cm){
                cm.on("configchange", this.onColConfigChange, this);
                cm.on("widthchange", this.onColWidthChange, this);
                cm.on("headerchange", this.onHeaderChange, this);
                cm.on("hiddenchange", this.onHiddenChange, this);
                cm.on("columnmoved", this.onColumnMove, this);
                cm.on("columnlockchange", this.onColumnLock, this);
            }
            this.cm = cm;
        },

            onDataChange : function(){
            this.refresh();
            this.updateHeaderSortState();
        },

            onClear : function(){
            this.refresh();
        },

            onUpdate : function(ds, record){
            this.refreshRow(record);
        },

            onAdd : function(ds, records, index){
            this.insertRows(ds, index, index + (records.length-1));
        },

            onRemove : function(ds, record, index, isUpdate){
            if(isUpdate !== true){
                this.fireEvent("beforerowremoved", this, index, record);
            }
            this.removeRow(index);
            if(isUpdate !== true){
                this.processRows(index);
                this.applyEmptyText();
                this.fireEvent("rowremoved", this, index, record);
            }
        },

            onLoad : function(){
            this.scrollToTop();
        },

            onColWidthChange : function(cm, col, width){
            this.updateColumnWidth(col, width);
        },

            onHeaderChange : function(cm, col, text){
            this.updateHeaders();
        },

            onHiddenChange : function(cm, col, hidden){
            this.updateColumnHidden(col, hidden);
        },

            onColumnMove : function(cm, oldIndex, newIndex){
            this.indexMap = null;
            var s = this.getScrollState();
            this.refresh(true);
            this.restoreScroll(s);
            this.afterMove(newIndex);
        },

            onColConfigChange : function(){
            delete this.lastViewWidth;
            this.indexMap = null;
            this.refresh(true);
        },

            initUI : function(grid){
            grid.on("headerclick", this.onHeaderClick, this);

            if(grid.trackMouseOver){
                grid.on("mouseover", this.onRowOver, this);
              grid.on("mouseout", this.onRowOut, this);
          }
        },

            initEvents : function(){

        },

            onHeaderClick : function(g, index){
            if(this.headersDisabled || !this.cm.isSortable(index)){
                return;
            }
            g.stopEditing(true);
            g.store.sort(this.cm.getDataIndex(index));
        },

            onRowOver : function(e, t){
            var row;
            if((row = this.findRowIndex(t)) !== false){
                this.addRowClass(row, "x-grid3-row-over");
            }
        },

            onRowOut : function(e, t){
            var row;
            if((row = this.findRowIndex(t)) !== false && row !== this.findRowIndex(e.getRelatedTarget())){
                this.removeRowClass(row, "x-grid3-row-over");
            }
        },

            handleWheel : function(e){
            e.stopPropagation();
        },

            onRowSelect : function(row){
            this.addRowClass(row, "x-grid3-row-selected");
        },

            onRowDeselect : function(row){
            this.removeRowClass(row, "x-grid3-row-selected");
        },

            onCellSelect : function(row, col){
            var cell = this.getCell(row, col);
            if(cell){
                this.fly(cell).addClass("x-grid3-cell-selected");
            }
        },

            onCellDeselect : function(row, col){
            var cell = this.getCell(row, col);
            if(cell){
                this.fly(cell).removeClass("x-grid3-cell-selected");
            }
        },

            onColumnSplitterMoved : function(i, w){
            this.userResized = true;
            var cm = this.grid.colModel;
            cm.setColumnWidth(i, w, true);

            if(this.forceFit){
                this.fitColumns(true, false, i);
                this.updateAllColumnWidths();
            }else{
                this.updateColumnWidth(i, w);
            }

            this.grid.fireEvent("columnresize", i, w);
        },

            handleHdMenuClick : function(item){
            var index = this.hdCtxIndex;
            var cm = this.cm, ds = this.ds;
            switch(item.id){
                case "asc":
                    ds.sort(cm.getDataIndex(index), "ASC");
                    break;
                case "desc":
                    ds.sort(cm.getDataIndex(index), "DESC");
                    break;
                default:
                    index = cm.getIndexById(item.id.substr(4));
                    if(index != -1){
                        if(item.checked && cm.getColumnsBy(this.isHideableColumn, this).length <= 1){
                            this.onDenyColumnHide();
                            return false;
                        }
                        cm.setHidden(index, item.checked);
                    }
            }
            return true;
        },

            isHideableColumn : function(c){
            return !c.hidden && !c.fixed;
        },

            beforeColMenuShow : function(){
            var cm = this.cm,  colCount = cm.getColumnCount();
            this.colMenu.removeAll();
            for(var i = 0; i < colCount; i++){
                if(cm.config[i].fixed !== true && cm.config[i].hideable !== false){
                    this.colMenu.add(new Ext.menu.CheckItem({
                        id: "col-"+cm.getColumnId(i),
                        text: cm.getColumnHeader(i),
                        checked: !cm.isHidden(i),
                        hideOnClick:false,
                        disabled: cm.config[i].hideable === false
                    }));
                }
            }
        },

            handleHdDown : function(e, t){
            if(Ext.fly(t).hasClass('x-grid3-hd-btn')){
                e.stopEvent();
                var hd = this.findHeaderCell(t);
                Ext.fly(hd).addClass('x-grid3-hd-menu-open');
                var index = this.getCellIndex(hd);
                this.hdCtxIndex = index;
                var ms = this.hmenu.items, cm = this.cm;
                ms.get("asc").setDisabled(!cm.isSortable(index));
                ms.get("desc").setDisabled(!cm.isSortable(index));
                this.hmenu.on("hide", function(){
                    Ext.fly(hd).removeClass('x-grid3-hd-menu-open');
                }, this, {single:true});
                this.hmenu.show(t, "tl-bl?");
            }
        },

            handleHdOver : function(e, t){
            var hd = this.findHeaderCell(t);
            if(hd && !this.headersDisabled){
                this.activeHd = hd;
                this.activeHdIndex = this.getCellIndex(hd);
                var fly = this.fly(hd);
                this.activeHdRegion = fly.getRegion();
                if(!this.cm.isMenuDisabled(this.activeHdIndex)){
                    fly.addClass("x-grid3-hd-over");
                    this.activeHdBtn = fly.child('.x-grid3-hd-btn');
                    if(this.activeHdBtn){
                        this.activeHdBtn.dom.style.height = (hd.firstChild.offsetHeight-1)+'px';
                    }
                }
            }
        },

            handleHdMove : function(e, t){
            if(this.activeHd && !this.headersDisabled){
                var hw = this.splitHandleWidth || 5;
                var r = this.activeHdRegion;
                var x = e.getPageX();
                var ss = this.activeHd.style;
                if(x - r.left <= hw && this.cm.isResizable(this.activeHdIndex-1)){
                    ss.cursor = Ext.isAir ? 'move' : Ext.isSafari ? 'e-resize' : 'col-resize';             }else if(r.right - x <= (!this.activeHdBtn ? hw : 2) && this.cm.isResizable(this.activeHdIndex)){
                    ss.cursor = Ext.isAir ? 'move' : Ext.isSafari ? 'w-resize' : 'col-resize';
                }else{
                    ss.cursor = '';
                }
            }
        },

            handleHdOut : function(e, t){
            var hd = this.findHeaderCell(t);
            if(hd && (!Ext.isIE || !e.within(hd, true))){
                this.activeHd = null;
                this.fly(hd).removeClass("x-grid3-hd-over");
                hd.style.cursor = '';
            }
        },

            hasRows : function(){
            var fc = this.mainBody.dom.firstChild;
            return fc && fc.className != 'x-grid-empty';
        },

            bind : function(d, c){
            this.initData(d, c);
        }
    });

    Ext.grid.GridView.SplitDragZone = function(grid, hd){
        this.grid = grid;
        this.view = grid.getView();
        this.marker = this.view.resizeMarker;
        this.proxy = this.view.resizeProxy;
        Ext.grid.GridView.SplitDragZone.superclass.constructor.call(this, hd,
            "gridSplitters" + this.grid.getGridEl().id, {
            dragElId : Ext.id(this.proxy.dom), resizeFrame:false
        });
        this.scroll = false;
        this.hw = this.view.splitHandleWidth || 5;
    };
    Ext.extend(Ext.grid.GridView.SplitDragZone, Ext.dd.DDProxy, {

        b4StartDrag : function(x, y){
            this.view.headersDisabled = true;
            var h = this.view.mainWrap.getHeight();
            this.marker.setHeight(h);
            this.marker.show();
            this.marker.alignTo(this.view.getHeaderCell(this.cellIndex), 'tl-tl', [-2, 0]);
            this.proxy.setHeight(h);
            var w = this.cm.getColumnWidth(this.cellIndex);
            var minw = Math.max(w-this.grid.minColumnWidth, 0);
            this.resetConstraints();
            this.setXConstraint(minw, 1000);
            this.setYConstraint(0, 0);
            this.minX = x - minw;
            this.maxX = x + 1000;
            this.startPos = x;
            Ext.dd.DDProxy.prototype.b4StartDrag.call(this, x, y);
        },

        handleMouseDown : function(e){
            var t = this.view.findHeaderCell(e.getTarget());
            if(t){
                var xy = this.view.fly(t).getXY(), x = xy[0], y = xy[1];
                var exy = e.getXY(), ex = exy[0], ey = exy[1];
                var w = t.offsetWidth, adjust = false;
                if((ex - x) <= this.hw){
                    adjust = -1;
                }else if((x+w) - ex <= this.hw){
                    adjust = 0;
                }
                if(adjust !== false){
                    this.cm = this.grid.colModel;
                    var ci = this.view.getCellIndex(t);
                    if(adjust == -1){
                      if (ci + adjust < 0) {
                        return;
                      }
                        while(this.cm.isHidden(ci+adjust)){
                            --adjust;
                            if(ci+adjust < 0){
                                return;
                            }
                        }
                    }
                    this.cellIndex = ci+adjust;
                    this.split = t.dom;
                    if(this.cm.isResizable(this.cellIndex) && !this.cm.isFixed(this.cellIndex)){
                        Ext.grid.GridView.SplitDragZone.superclass.handleMouseDown.apply(this, arguments);
                    }
                }else if(this.view.columnDrag){
                    this.view.columnDrag.callHandleMouseDown(e);
                }
            }
        },

        endDrag : function(e){
            this.marker.hide();
            var v = this.view;
            var endX = Math.max(this.minX, e.getPageX());
            var diff = endX - this.startPos;
            v.onColumnSplitterMoved(this.cellIndex, this.cm.getColumnWidth(this.cellIndex)+diff);
            setTimeout(function(){
                v.headersDisabled = false;
            }, 50);
        },

        autoOffset : function(){
            this.setDelta(0,0);
        }
    });

    Ext.grid.GroupingView = Ext.extend(Ext.grid.GridView, {

        hideGroupedColumn:false,

        showGroupName:true,

        startCollapsed:false,

        enableGrouping:true,

        enableGroupingMenu:true,

        enableNoGroups:true,

        emptyGroupText : '(None)',

        ignoreAdd: false,

        groupTextTpl : '{text}',

        gidSeed : 1000,

        initTemplates : function(){
            Ext.grid.GroupingView.superclass.initTemplates.call(this);
            this.state = {};

            var sm = this.grid.getSelectionModel();
            sm.on(sm.selectRow ? 'beforerowselect' : 'beforecellselect',
                    this.onBeforeRowSelect, this);

            if(!this.startGroup){
                this.startGroup = new Ext.XTemplate(
                    '',
                        '', this.groupTextTpl ,'',
                        ''
                );
            }
            this.startGroup.compile();
            this.endGroup = '';
        },

        findGroup : function(el){
            return Ext.fly(el).up('.x-grid-group', this.mainBody.dom);
        },

        getGroups : function(){
            return this.hasRows() ? this.mainBody.dom.childNodes : [];
        },

        onAdd : function(){
            if(this.enableGrouping && !this.ignoreAdd){
                var ss = this.getScrollState();
                this.refresh();
                this.restoreScroll(ss);
            }else if(!this.enableGrouping){
                Ext.grid.GroupingView.superclass.onAdd.apply(this, arguments);
            }
        },

        onRemove : function(ds, record, index, isUpdate){
            Ext.grid.GroupingView.superclass.onRemove.apply(this, arguments);
            var g = document.getElementById(record._groupId);
            if(g && g.childNodes[1].childNodes.length < 1){
                Ext.removeNode(g);
            }
            this.applyEmptyText();
        },

        refreshRow : function(record){
            if(this.ds.getCount()==1){
                this.refresh();
            }else{
                this.isUpdating = true;
                Ext.grid.GroupingView.superclass.refreshRow.apply(this, arguments);
                this.isUpdating = false;
            }
        },

        beforeMenuShow : function(){
            var field = this.getGroupField();
            var g = this.hmenu.items.get('groupBy');
            if(g){
                g.setDisabled(this.cm.config[this.hdCtxIndex].groupable === false);
            }
            var s = this.hmenu.items.get('showGroups');
            if(s){
                if (!!field){
                    s.setDisabled(this.cm.config[this.hdCtxIndex].groupable === false)
                }
                s.setChecked(!!field);
            }
        },

        renderUI : function(){
            Ext.grid.GroupingView.superclass.renderUI.call(this);
            this.mainBody.on('mousedown', this.interceptMouse, this);

            if(this.enableGroupingMenu && this.hmenu){
                this.hmenu.add('-',{
                    id:'groupBy',
                    text: this.groupByText,
                    handler: this.onGroupByClick,
                    scope: this,
                    iconCls:'x-group-by-icon'
                });
                if(this.enableNoGroups){
                    this.hmenu.add({
                        id:'showGroups',
                        text: this.showGroupsText,
                        checked: true,
                        checkHandler: this.onShowGroupsClick,
                        scope: this
                    });
                }
                this.hmenu.on('beforeshow', this.beforeMenuShow, this);
            }
        },

        onGroupByClick : function(){
            this.grid.store.groupBy(this.cm.getDataIndex(this.hdCtxIndex));
            this.beforeMenuShow();
        },

        onShowGroupsClick : function(mi, checked){
            if(checked){
                this.onGroupByClick();
            }else{
                this.grid.store.clearGrouping();
            }
        },

        toggleGroup : function(group, expanded){
            this.grid.stopEditing(true);
            group = Ext.getDom(group);
            var gel = Ext.fly(group);
            expanded = expanded !== undefined ?
                    expanded : gel.hasClass('x-grid-group-collapsed');

            this.state[gel.dom.id] = expanded;
            gel[expanded ? 'removeClass' : 'addClass']('x-grid-group-collapsed');
        },

        toggleAllGroups : function(expanded){
            var groups = this.getGroups();
            for(var i = 0, len = groups.length; i < len; i++){
                this.toggleGroup(groups[i], expanded);
            }
        },

        expandAllGroups : function(){
            this.toggleAllGroups(true);
        },

        collapseAllGroups : function(){
            this.toggleAllGroups(false);
        },

        interceptMouse : function(e){
            var hd = e.getTarget('.x-grid-group-hd', this.mainBody);
            if(hd){
                e.stopEvent();
                this.toggleGroup(hd.parentNode);
            }
        },

        getGroup : function(v, r, groupRenderer, rowIndex, colIndex, ds){
            var g = groupRenderer ? groupRenderer(v, {}, r, rowIndex, colIndex, ds) : String(v);
            if(g === ''){
                g = this.cm.config[colIndex].emptyGroupText || this.emptyGroupText;
            }
            return g;
        },

        getGroupField : function(){
            return this.grid.store.getGroupState();
        },

        renderRows : function(){
            var groupField = this.getGroupField();
            var eg = !!groupField;

            if(this.hideGroupedColumn) {
                var colIndex = this.cm.findColumnIndex(groupField);
                if(!eg && this.lastGroupField !== undefined) {
                    this.mainBody.update('');
                    this.cm.setHidden(this.cm.findColumnIndex(this.lastGroupField), false);
                    delete this.lastGroupField;
                }else if (eg && this.lastGroupField === undefined) {
                    this.lastGroupField = groupField;
                    this.cm.setHidden(colIndex, true);
                }else if (eg && this.lastGroupField !== undefined && groupField !== this.lastGroupField) {
                    this.mainBody.update('');
                    var oldIndex = this.cm.findColumnIndex(this.lastGroupField);
                    this.cm.setHidden(oldIndex, false);
                    this.lastGroupField = groupField;
                    this.cm.setHidden(colIndex, true);
                }
            }
            return Ext.grid.GroupingView.superclass.renderRows.apply(
                        this, arguments);
        },

        doRender : function(cs, rs, ds, startRow, colCount, stripe){
            if(rs.length < 1){
                return '';
            }
            var groupField = this.getGroupField();
            var colIndex = this.cm.findColumnIndex(groupField);

            this.enableGrouping = !!groupField;

            if(!this.enableGrouping || this.isUpdating){
                return Ext.grid.GroupingView.superclass.doRender.apply(
                        this, arguments);
            }
            var gstyle = 'width:'+this.getTotalWidth()+';';

            var gidPrefix = this.grid.getGridEl().id;
            var cfg = this.cm.config[colIndex];
            var groupRenderer = cfg.groupRenderer || cfg.renderer;
            var prefix = this.showGroupName ?
                         (cfg.groupName || cfg.header)+': ' : '';

            var groups = [], curGroup, i, len, gid;
            for(i = 0, len = rs.length; i < len; i++){
                var rowIndex = startRow + i;
                var r = rs[i],
                    gvalue = r.data[groupField],
                    g = this.getGroup(gvalue, r, groupRenderer, rowIndex, colIndex, ds);
                if(!curGroup || curGroup.group != g){
                    gid = gidPrefix + '-gp-' + groupField + '-' + Ext.util.Format.htmlEncode(g);

    				var isCollapsed  = typeof this.state[gid] !== 'undefined' ? !this.state[gid] : this.startCollapsed;
    				var gcls = isCollapsed ? 'x-grid-group-collapsed' : '';
                    curGroup = {
                        group: g,
                        gvalue: gvalue,
                        text: prefix + g,
                        groupId: gid,
                        startRow: rowIndex,
                        rs: [r],
                        cls: gcls,
                        style: gstyle
                    };
                    groups.push(curGroup);
                }else{
                    curGroup.rs.push(r);
                }
                r._groupId = gid;
            }

            var buf = [];
            for(i = 0, len = groups.length; i < len; i++){
                var g = groups[i];
                this.doGroupStart(buf, g, cs, ds, colCount);
                buf[buf.length] = Ext.grid.GroupingView.superclass.doRender.call(
                        this, cs, g.rs, ds, g.startRow, colCount, stripe);

                this.doGroupEnd(buf, g, cs, ds, colCount);
            }
            return buf.join('');
        },

        getGroupId : function(value){
            var gidPrefix = this.grid.getGridEl().id;
            var groupField = this.getGroupField();
            var colIndex = this.cm.findColumnIndex(groupField);
            var cfg = this.cm.config[colIndex];
            var groupRenderer = cfg.groupRenderer || cfg.renderer;
            var gtext = this.getGroup(value, {data:{}}, groupRenderer, 0, colIndex, this.ds);
            return gidPrefix + '-gp-' + groupField + '-' + Ext.util.Format.htmlEncode(value);
        },

        doGroupStart : function(buf, g, cs, ds, colCount){
            buf[buf.length] = this.startGroup.apply(g);
        },

        doGroupEnd : function(buf, g, cs, ds, colCount){
            buf[buf.length] = this.endGroup;
        },

        getRows : function(){
            if(!this.enableGrouping){
                return Ext.grid.GroupingView.superclass.getRows.call(this);
            }
            var r = [];
            var g, gs = this.getGroups();
            for(var i = 0, len = gs.length; i < len; i++){
                g = gs[i].childNodes[1].childNodes;
                for(var j = 0, jlen = g.length; j < jlen; j++){
                    r[r.length] = g[j];
                }
            }
            return r;
        },

        updateGroupWidths : function(){
            if(!this.enableGrouping || !this.hasRows()){
                return;
            }
            var tw = Math.max(this.cm.getTotalWidth(), this.el.dom.offsetWidth-this.scrollOffset) +'px';
            var gs = this.getGroups();
            for(var i = 0, len = gs.length; i < len; i++){
                gs[i].firstChild.style.width = tw;
            }
        },

        onColumnWidthUpdated : function(col, w, tw){
            this.updateGroupWidths();
        },

        onAllColumnWidthsUpdated : function(ws, tw){
            this.updateGroupWidths();
        },

        onColumnHiddenUpdated : function(col, hidden, tw){
            this.updateGroupWidths();
        },

        onLayout : function(){
            this.updateGroupWidths();
        },

        onBeforeRowSelect : function(sm, rowIndex){
            if(!this.enableGrouping){
                return;
            }
            var row = this.getRow(rowIndex);
            if(row && !row.offsetParent){
                var g = this.findGroup(row);
                this.toggleGroup(g, true);
            }
        },

        groupByText: 'Group By This Field',

        showGroupsText: 'Show in Groups'
    });

    Ext.grid.GroupingView.GROUP_ID = 1000;

    Ext.grid.HeaderDragZone = function(grid, hd, hd2){
        this.grid = grid;
        this.view = grid.getView();
        this.ddGroup = "gridHeader" + this.grid.getGridEl().id;
        Ext.grid.HeaderDragZone.superclass.constructor.call(this, hd);
        if(hd2){
            this.setHandleElId(Ext.id(hd));
            this.setOuterHandleElId(Ext.id(hd2));
        }
        this.scroll = false;
    };
    Ext.extend(Ext.grid.HeaderDragZone, Ext.dd.DragZone, {
        maxDragWidth: 120,
        getDragData : function(e){
            var t = Ext.lib.Event.getTarget(e);
            var h = this.view.findHeaderCell(t);
            if(h){
                return {ddel: h.firstChild, header:h};
            }
            return false;
        },

        onInitDrag : function(e){
            this.view.headersDisabled = true;
            var clone = this.dragData.ddel.cloneNode(true);
            clone.id = Ext.id();
            clone.style.width = Math.min(this.dragData.header.offsetWidth,this.maxDragWidth) + "px";
            this.proxy.update(clone);
            return true;
        },

        afterValidDrop : function(){
            var v = this.view;
            setTimeout(function(){
                v.headersDisabled = false;
            }, 50);
        },

        afterInvalidDrop : function(){
            var v = this.view;
            setTimeout(function(){
                v.headersDisabled = false;
            }, 50);
        }
    });

    Ext.grid.HeaderDropZone = function(grid, hd, hd2){
        this.grid = grid;
        this.view = grid.getView();

        this.proxyTop = Ext.DomHelper.append(document.body, {
            cls:"col-move-top", html:" "
        }, true);
        this.proxyBottom = Ext.DomHelper.append(document.body, {
            cls:"col-move-bottom", html:" "
        }, true);
        this.proxyTop.hide = this.proxyBottom.hide = function(){
            this.setLeftTop(-100,-100);
            this.setStyle("visibility", "hidden");
        };
        this.ddGroup = "gridHeader" + this.grid.getGridEl().id;

        Ext.grid.HeaderDropZone.superclass.constructor.call(this, grid.getGridEl().dom);
    };
    Ext.extend(Ext.grid.HeaderDropZone, Ext.dd.DropZone, {
        proxyOffsets : [-4, -9],
        fly: Ext.Element.fly,

        getTargetFromEvent : function(e){
            var t = Ext.lib.Event.getTarget(e);
            var cindex = this.view.findCellIndex(t);
            if(cindex !== false){
                return this.view.getHeaderCell(cindex);
            }
        },

        nextVisible : function(h){
            var v = this.view, cm = this.grid.colModel;
            h = h.nextSibling;
            while(h){
                if(!cm.isHidden(v.getCellIndex(h))){
                    return h;
                }
                h = h.nextSibling;
            }
            return null;
        },

        prevVisible : function(h){
            var v = this.view, cm = this.grid.colModel;
            h = h.prevSibling;
            while(h){
                if(!cm.isHidden(v.getCellIndex(h))){
                    return h;
                }
                h = h.prevSibling;
            }
            return null;
        },

        positionIndicator : function(h, n, e){
            var x = Ext.lib.Event.getPageX(e);
            var r = Ext.lib.Dom.getRegion(n.firstChild);
            var px, pt, py = r.top + this.proxyOffsets[1];
            if((r.right - x) <= (r.right-r.left)/2){
                px = r.right+this.view.borderWidth;
                pt = "after";
            }else{
                px = r.left;
                pt = "before";
            }
            var oldIndex = this.view.getCellIndex(h);
            var newIndex = this.view.getCellIndex(n);

            if(this.grid.colModel.isFixed(newIndex)){
                return false;
            }

            var locked = this.grid.colModel.isLocked(newIndex);

            if(pt == "after"){
                newIndex++;
            }
            if(oldIndex < newIndex){
                newIndex--;
            }
            if(oldIndex == newIndex && (locked == this.grid.colModel.isLocked(oldIndex))){
                return false;
            }
            px +=  this.proxyOffsets[0];
            this.proxyTop.setLeftTop(px, py);
            this.proxyTop.show();
            if(!this.bottomOffset){
                this.bottomOffset = this.view.mainHd.getHeight();
            }
            this.proxyBottom.setLeftTop(px, py+this.proxyTop.dom.offsetHeight+this.bottomOffset);
            this.proxyBottom.show();
            return pt;
        },

        onNodeEnter : function(n, dd, e, data){
            if(data.header != n){
                this.positionIndicator(data.header, n, e);
            }
        },

        onNodeOver : function(n, dd, e, data){
            var result = false;
            if(data.header != n){
                result = this.positionIndicator(data.header, n, e);
            }
            if(!result){
                this.proxyTop.hide();
                this.proxyBottom.hide();
            }
            return result ? this.dropAllowed : this.dropNotAllowed;
        },

        onNodeOut : function(n, dd, e, data){
            this.proxyTop.hide();
            this.proxyBottom.hide();
        },

        onNodeDrop : function(n, dd, e, data){
            var h = data.header;
            if(h != n){
                var cm = this.grid.colModel;
                var x = Ext.lib.Event.getPageX(e);
                var r = Ext.lib.Dom.getRegion(n.firstChild);
                var pt = (r.right - x) <= ((r.right-r.left)/2) ? "after" : "before";
                var oldIndex = this.view.getCellIndex(h);
                var newIndex = this.view.getCellIndex(n);
                var locked = cm.isLocked(newIndex);
                if(pt == "after"){
                    newIndex++;
                }
                if(oldIndex < newIndex){
                    newIndex--;
                }
                if(oldIndex == newIndex && (locked == cm.isLocked(oldIndex))){
                    return false;
                }
                cm.setLocked(oldIndex, locked, true);
                cm.moveColumn(oldIndex, newIndex);
                this.grid.fireEvent("columnmove", oldIndex, newIndex);
                return true;
            }
            return false;
        }
    });

    Ext.grid.GridView.ColumnDragZone = function(grid, hd){
        Ext.grid.GridView.ColumnDragZone.superclass.constructor.call(this, grid, hd, null);
        this.proxy.el.addClass('x-grid3-col-dd');
    };

    Ext.extend(Ext.grid.GridView.ColumnDragZone, Ext.grid.HeaderDragZone, {
        handleMouseDown : function(e){

        },

        callHandleMouseDown : function(e){
            Ext.grid.GridView.ColumnDragZone.superclass.handleMouseDown.call(this, e);
        }
    });
    Ext.grid.SplitDragZone = function(grid, hd, hd2){
        this.grid = grid;
        this.view = grid.getView();
        this.proxy = this.view.resizeProxy;
        Ext.grid.SplitDragZone.superclass.constructor.call(this, hd,
            "gridSplitters" + this.grid.getGridEl().id, {
            dragElId : Ext.id(this.proxy.dom), resizeFrame:false
        });
        this.setHandleElId(Ext.id(hd));
        this.setOuterHandleElId(Ext.id(hd2));
        this.scroll = false;
    };
    Ext.extend(Ext.grid.SplitDragZone, Ext.dd.DDProxy, {
        fly: Ext.Element.fly,

        b4StartDrag : function(x, y){
            this.view.headersDisabled = true;
            this.proxy.setHeight(this.view.mainWrap.getHeight());
            var w = this.cm.getColumnWidth(this.cellIndex);
            var minw = Math.max(w-this.grid.minColumnWidth, 0);
            this.resetConstraints();
            this.setXConstraint(minw, 1000);
            this.setYConstraint(0, 0);
            this.minX = x - minw;
            this.maxX = x + 1000;
            this.startPos = x;
            Ext.dd.DDProxy.prototype.b4StartDrag.call(this, x, y);
        },

        handleMouseDown : function(e){
            ev = Ext.EventObject.setEvent(e);
            var t = this.fly(ev.getTarget());
            if(t.hasClass("x-grid-split")){
                this.cellIndex = this.view.getCellIndex(t.dom);
                this.split = t.dom;
                this.cm = this.grid.colModel;
                if(this.cm.isResizable(this.cellIndex) && !this.cm.isFixed(this.cellIndex)){
                    Ext.grid.SplitDragZone.superclass.handleMouseDown.apply(this, arguments);
                }
            }
        },

        endDrag : function(e){
            this.view.headersDisabled = false;
            var endX = Math.max(this.minX, Ext.lib.Event.getPageX(e));
            var diff = endX - this.startPos;
            this.view.onColumnSplitterMoved(this.cellIndex, this.cm.getColumnWidth(this.cellIndex)+diff);
        },

        autoOffset : function(){
            this.setDelta(0,0);
        }
    });
    Ext.grid.GridDragZone = function(grid, config){
        this.view = grid.getView();
        Ext.grid.GridDragZone.superclass.constructor.call(this, this.view.mainBody.dom, config);
        if(this.view.lockedBody){
            this.setHandleElId(Ext.id(this.view.mainBody.dom));
            this.setOuterHandleElId(Ext.id(this.view.lockedBody.dom));
        }
        this.scroll = false;
        this.grid = grid;
        this.ddel = document.createElement('div');
        this.ddel.className = 'x-grid-dd-wrap';
    };

    Ext.extend(Ext.grid.GridDragZone, Ext.dd.DragZone, {
        ddGroup : "GridDD",

        getDragData : function(e){
            var t = Ext.lib.Event.getTarget(e);
            var rowIndex = this.view.findRowIndex(t);
            if(rowIndex !== false){
                var sm = this.grid.selModel;
                if(!sm.isSelected(rowIndex) || e.hasModifier()){
                    sm.handleMouseDown(this.grid, rowIndex, e);
                }
                return {grid: this.grid, ddel: this.ddel, rowIndex: rowIndex, selections:sm.getSelections()};
            }
            return false;
        },

        onInitDrag : function(e){
            var data = this.dragData;
            this.ddel.innerHTML = this.grid.getDragDropText();
            this.proxy.update(this.ddel);
                },

        afterRepair : function(){
            this.dragging = false;
        },

        getRepairXY : function(e, data){
            return false;
        },

        onEndDrag : function(data, e){
                },

        onValidDrop : function(dd, e, id){
                    this.hideProxy();
        },

        beforeInvalidDrop : function(e, id){

        }
    });

    Ext.grid.ColumnModel = function(config){

        this.defaultWidth = 100;

        this.defaultSortable = false;

        if(config.columns){
            Ext.apply(this, config);
            this.setConfig(config.columns, true);
        }else{
            this.setConfig(config, true);
        }
        this.addEvents(

    	    "widthchange",

    	    "headerchange",

    	    "hiddenchange",

            "columnmoved",

            "columnlockchange",

            "configchange"
        );
        Ext.grid.ColumnModel.superclass.constructor.call(this);
    };
    Ext.extend(Ext.grid.ColumnModel, Ext.util.Observable, {

        getColumnId : function(index){
            return this.config[index].id;
        },

        setConfig : function(config, initial){
            if(!initial){
                delete this.totalWidth;
                for(var i = 0, len = this.config.length; i < len; i++){
                    var c = this.config[i];
                    if(c.editor){
                        c.editor.destroy();
                    }
                }
            }
            this.config = config;
            this.lookup = {};

            for(var i = 0, len = config.length; i < len; i++){
                var c = config[i];
                if(typeof c.renderer == "string"){
                    c.renderer = Ext.util.Format[c.renderer];
                }
                if(typeof c.id == "undefined"){
                    c.id = i;
                }
                if(c.editor && c.editor.isFormField){
                    c.editor = new Ext.grid.GridEditor(c.editor);
                }
                this.lookup[c.id] = c;
            }
            if(!initial){
                this.fireEvent('configchange', this);
            }
        },

        getColumnById : function(id){
            return this.lookup[id];
        },

        getIndexById : function(id){
            for(var i = 0, len = this.config.length; i < len; i++){
                if(this.config[i].id == id){
                    return i;
                }
            }
            return -1;
        },

        moveColumn : function(oldIndex, newIndex){
            var c = this.config[oldIndex];
            this.config.splice(oldIndex, 1);
            this.config.splice(newIndex, 0, c);
            this.dataMap = null;
            this.fireEvent("columnmoved", this, oldIndex, newIndex);
        },

        isLocked : function(colIndex){
            return this.config[colIndex].locked === true;
        },

        setLocked : function(colIndex, value, suppressEvent){
            if(this.isLocked(colIndex) == value){
                return;
            }
            this.config[colIndex].locked = value;
            if(!suppressEvent){
                this.fireEvent("columnlockchange", this, colIndex, value);
            }
        },

        getTotalLockedWidth : function(){
            var totalWidth = 0;
            for(var i = 0; i < this.config.length; i++){
                if(this.isLocked(i) && !this.isHidden(i)){
                    this.totalWidth += this.getColumnWidth(i);
                }
            }
            return totalWidth;
        },

        getLockedCount : function(){
            for(var i = 0, len = this.config.length; i < len; i++){
                if(!this.isLocked(i)){
                    return i;
                }
            }
        },

        getColumnCount : function(visibleOnly){
            if(visibleOnly === true){
                var c = 0;
                for(var i = 0, len = this.config.length; i < len; i++){
                    if(!this.isHidden(i)){
                        c++;
                    }
                }
                return c;
            }
            return this.config.length;
        },

        getColumnsBy : function(fn, scope){
            var r = [];
            for(var i = 0, len = this.config.length; i < len; i++){
                var c = this.config[i];
                if(fn.call(scope||this, c, i) === true){
                    r[r.length] = c;
                }
            }
            return r;
        },

        isSortable : function(col){
            if(typeof this.config[col].sortable == "undefined"){
                return this.defaultSortable;
            }
            return this.config[col].sortable;
        },

        isMenuDisabled : function(col){
            return !!this.config[col].menuDisabled;
        },

        getRenderer : function(col){
            if(!this.config[col].renderer){
                return Ext.grid.ColumnModel.defaultRenderer;
            }
            return this.config[col].renderer;
        },

        setRenderer : function(col, fn){
            this.config[col].renderer = fn;
        },

        getColumnWidth : function(col){
            return this.config[col].width || this.defaultWidth;
        },

        setColumnWidth : function(col, width, suppressEvent){
            this.config[col].width = width;
            this.totalWidth = null;
            if(!suppressEvent){
                 this.fireEvent("widthchange", this, col, width);
            }
        },

        getTotalWidth : function(includeHidden){
            if(!this.totalWidth){
                this.totalWidth = 0;
                for(var i = 0, len = this.config.length; i < len; i++){
                    if(includeHidden || !this.isHidden(i)){
                        this.totalWidth += this.getColumnWidth(i);
                    }
                }
            }
            return this.totalWidth;
        },

        getColumnHeader : function(col){
            return this.config[col].header;
        },

        setColumnHeader : function(col, header){
            this.config[col].header = header;
            this.fireEvent("headerchange", this, col, header);
        },

        getColumnTooltip : function(col){
                return this.config[col].tooltip;
        },

        setColumnTooltip : function(col, tooltip){
                this.config[col].tooltip = tooltip;
        },

        getDataIndex : function(col){
            return this.config[col].dataIndex;
        },

        setDataIndex : function(col, dataIndex){
            this.config[col].dataIndex = dataIndex;
        },

        findColumnIndex : function(dataIndex){
            var c = this.config;
            for(var i = 0, len = c.length; i < len; i++){
                if(c[i].dataIndex == dataIndex){
                    return i;
                }
            }
            return -1;
        },

        isCellEditable : function(colIndex, rowIndex){
            return (this.config[colIndex].editable || (typeof this.config[colIndex].editable == "undefined" && this.config[colIndex].editor)) ? true : false;
        },

        getCellEditor : function(colIndex, rowIndex){
            return this.config[colIndex].editor;
        },

        setEditable : function(col, editable){
            this.config[col].editable = editable;
        },

        isHidden : function(colIndex){
            return this.config[colIndex].hidden;
        },

        isFixed : function(colIndex){
            return this.config[colIndex].fixed;
        },

        isResizable : function(colIndex){
            return colIndex >= 0 && this.config[colIndex].resizable !== false && this.config[colIndex].fixed !== true;
        },

        setHidden : function(colIndex, hidden){
            var c = this.config[colIndex];
            if(c.hidden !== hidden){
                c.hidden = hidden;
                this.totalWidth = null;
                this.fireEvent("hiddenchange", this, colIndex, hidden);
            }
        },

        setEditor : function(col, editor){
            this.config[col].editor = editor;
        }
    });

    Ext.grid.ColumnModel.defaultRenderer = function(value){
    	if(typeof value == "string" && value.length < 1){
    	    return " ";
    	}
    	return value;
    };

    Ext.grid.DefaultColumnModel = Ext.grid.ColumnModel;

    Ext.grid.AbstractSelectionModel = function(){
        this.locked = false;
        Ext.grid.AbstractSelectionModel.superclass.constructor.call(this);
    };

    Ext.extend(Ext.grid.AbstractSelectionModel, Ext.util.Observable,  {

        init : function(grid){
            this.grid = grid;
            this.initEvents();
        },

        lock : function(){
            this.locked = true;
        },

        unlock : function(){
            this.locked = false;
        },

        isLocked : function(){
            return this.locked;
        }
    });

    Ext.grid.RowSelectionModel = function(config){
        Ext.apply(this, config);
        this.selections = new Ext.util.MixedCollection(false, function(o){
            return o.id;
        });

        this.last = false;
        this.lastActive = false;

        this.addEvents(

    	    "selectionchange",

    	    "beforerowselect",

    	    "rowselect",

    	    "rowdeselect"
        );

        Ext.grid.RowSelectionModel.superclass.constructor.call(this);
    };

    Ext.extend(Ext.grid.RowSelectionModel, Ext.grid.AbstractSelectionModel,  {

        singleSelect : false,

            initEvents : function(){

            if(!this.grid.enableDragDrop && !this.grid.enableDrag){
                this.grid.on("rowmousedown", this.handleMouseDown, this);
            }else{             this.grid.on("rowclick", function(grid, rowIndex, e) {
                    if(e.button === 0 && !e.shiftKey && !e.ctrlKey) {
                        this.selectRow(rowIndex, false);
                        grid.view.focusRow(rowIndex);
                    }
                }, this);
            }

            this.rowNav = new Ext.KeyNav(this.grid.getGridEl(), {
                "up" : function(e){
                    if(!e.shiftKey){
                        this.selectPrevious(e.shiftKey);
                    }else if(this.last !== false && this.lastActive !== false){
                        var last = this.last;
                        this.selectRange(this.last,  this.lastActive-1);
                        this.grid.getView().focusRow(this.lastActive);
                        if(last !== false){
                            this.last = last;
                        }
                    }else{
                        this.selectFirstRow();
                    }
                },
                "down" : function(e){
                    if(!e.shiftKey){
                        this.selectNext(e.shiftKey);
                    }else if(this.last !== false && this.lastActive !== false){
                        var last = this.last;
                        this.selectRange(this.last,  this.lastActive+1);
                        this.grid.getView().focusRow(this.lastActive);
                        if(last !== false){
                            this.last = last;
                        }
                    }else{
                        this.selectFirstRow();
                    }
                },
                scope: this
            });

            var view = this.grid.view;
            view.on("refresh", this.onRefresh, this);
            view.on("rowupdated", this.onRowUpdated, this);
            view.on("rowremoved", this.onRemove, this);
        },

            onRefresh : function(){
            var ds = this.grid.store, index;
            var s = this.getSelections();
            this.clearSelections(true);
            for(var i = 0, len = s.length; i < len; i++){
                var r = s[i];
                if((index = ds.indexOfId(r.id)) != -1){
                    this.selectRow(index, true);
                }
            }
            if(s.length != this.selections.getCount()){
                this.fireEvent("selectionchange", this);
            }
        },

            onRemove : function(v, index, r){
            if(this.selections.remove(r) !== false){
                this.fireEvent('selectionchange', this);
            }
        },

            onRowUpdated : function(v, index, r){
            if(this.isSelected(r)){
                v.onRowSelect(index);
            }
        },

        selectRecords : function(records, keepExisting){
            if(!keepExisting){
                this.clearSelections();
            }
            var ds = this.grid.store;
            for(var i = 0, len = records.length; i < len; i++){
                this.selectRow(ds.indexOf(records[i]), true);
            }
        },

        getCount : function(){
            return this.selections.length;
        },

        selectFirstRow : function(){
            this.selectRow(0);
        },

        selectLastRow : function(keepExisting){
            this.selectRow(this.grid.store.getCount() - 1, keepExisting);
        },

        selectNext : function(keepExisting){
            if(this.hasNext()){
                this.selectRow(this.last+1, keepExisting);
                this.grid.getView().focusRow(this.last);
    			return true;
            }
    		return false;
        },

        selectPrevious : function(keepExisting){
            if(this.hasPrevious()){
                this.selectRow(this.last-1, keepExisting);
                this.grid.getView().focusRow(this.last);
    			return true;
            }
    		return false;
        },

        hasNext : function(){
            return this.last !== false && (this.last+1) < this.grid.store.getCount();
        },

        hasPrevious : function(){
            return !!this.last;
        },

        getSelections : function(){
            return [].concat(this.selections.items);
        },

        getSelected : function(){
            return this.selections.itemAt(0);
        },

        each : function(fn, scope){
            var s = this.getSelections();
            for(var i = 0, len = s.length; i < len; i++){
                if(fn.call(scope || this, s[i], i) === false){
                    return false;
                }
            }
            return true;
        },

        clearSelections : function(fast){
            if(this.locked) return;
            if(fast !== true){
                var ds = this.grid.store;
                var s = this.selections;
                s.each(function(r){
                    this.deselectRow(ds.indexOfId(r.id));
                }, this);
                s.clear();
            }else{
                this.selections.clear();
            }
            this.last = false;
        },

        selectAll : function(){
            if(this.locked) return;
            this.selections.clear();
            for(var i = 0, len = this.grid.store.getCount(); i < len; i++){
                this.selectRow(i, true);
            }
        },

        hasSelection : function(){
            return this.selections.length > 0;
        },

        isSelected : function(index){
            var r = typeof index == "number" ? this.grid.store.getAt(index) : index;
            return (r && this.selections.key(r.id) ? true : false);
        },

        isIdSelected : function(id){
            return (this.selections.key(id) ? true : false);
        },

            handleMouseDown : function(g, rowIndex, e){
            if(e.button !== 0 || this.isLocked()){
                return;
            };
            var view = this.grid.getView();
            if(e.shiftKey && this.last !== false){
                var last = this.last;
                this.selectRange(last, rowIndex, e.ctrlKey);
                this.last = last;             view.focusRow(rowIndex);
            }else{
                var isSelected = this.isSelected(rowIndex);
                if(e.ctrlKey && isSelected){
                    this.deselectRow(rowIndex);
                }else if(!isSelected || this.getCount() > 1){
                    this.selectRow(rowIndex, e.ctrlKey || e.shiftKey);
                    view.focusRow(rowIndex);
                }
            }
        },

        selectRows : function(rows, keepExisting){
            if(!keepExisting){
                this.clearSelections();
            }
            for(var i = 0, len = rows.length; i < len; i++){
                this.selectRow(rows[i], true);
            }
        },

        selectRange : function(startRow, endRow, keepExisting){
            if(this.locked) return;
            if(!keepExisting){
                this.clearSelections();
            }
            if(startRow <= endRow){
                for(var i = startRow; i <= endRow; i++){
                    this.selectRow(i, true);
                }
            }else{
                for(var i = startRow; i >= endRow; i--){
                    this.selectRow(i, true);
                }
            }
        },

        deselectRange : function(startRow, endRow, preventViewNotify){
            if(this.locked) return;
            for(var i = startRow; i <= endRow; i++){
                this.deselectRow(i, preventViewNotify);
            }
        },

        selectRow : function(index, keepExisting, preventViewNotify){
            if(this.locked || (index < 0 || index >= this.grid.store.getCount())) return;
            var r = this.grid.store.getAt(index);
            if(r && this.fireEvent("beforerowselect", this, index, keepExisting, r) !== false){
                if(!keepExisting || this.singleSelect){
                    this.clearSelections();
                }
                this.selections.add(r);
                this.last = this.lastActive = index;
                if(!preventViewNotify){
                    this.grid.getView().onRowSelect(index);
                }
                this.fireEvent("rowselect", this, index, r);
                this.fireEvent("selectionchange", this);
            }
        },

        deselectRow : function(index, preventViewNotify){
            if(this.locked) return;
            if(this.last == index){
                this.last = false;
            }
            if(this.lastActive == index){
                this.lastActive = false;
            }
            var r = this.grid.store.getAt(index);
            if(r){
                this.selections.remove(r);
                if(!preventViewNotify){
                    this.grid.getView().onRowDeselect(index);
                }
                this.fireEvent("rowdeselect", this, index, r);
                this.fireEvent("selectionchange", this);
            }
        },

            restoreLast : function(){
            if(this._last){
                this.last = this._last;
            }
        },

            acceptsNav : function(row, col, cm){
            return !cm.isHidden(col) && cm.isCellEditable(col, row);
        },

            onEditorKey : function(field, e){
            var k = e.getKey(), newCell, g = this.grid, ed = g.activeEditor;
            var shift = e.shiftKey;
            if(k == e.TAB){
                e.stopEvent();
                ed.completeEdit();
                if(shift){
                    newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
                }else{
                    newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
                }
            }else if(k == e.ENTER){
                e.stopEvent();
                ed.completeEdit();
    			if(this.moveEditorOnEnter !== false){
    				if(shift){
    					newCell = g.walkCells(ed.row - 1, ed.col, -1, this.acceptsNav, this);
    				}else{
    					newCell = g.walkCells(ed.row + 1, ed.col, 1, this.acceptsNav, this);
    				}
    			}
            }else if(k == e.ESC){
                ed.cancelEdit();
            }
            if(newCell){
                g.startEditing(newCell[0], newCell[1]);
            }
        }
    });

    Ext.grid.CellSelectionModel = function(config){
        Ext.apply(this, config);

        this.selection = null;

        this.addEvents(

    	    "beforecellselect",

    	    "cellselect",

    	    "selectionchange"
        );

        Ext.grid.CellSelectionModel.superclass.constructor.call(this);
    };

    Ext.extend(Ext.grid.CellSelectionModel, Ext.grid.AbstractSelectionModel,  {

        initEvents : function(){
            this.grid.on("cellmousedown", this.handleMouseDown, this);
            this.grid.getGridEl().on(Ext.isIE ? "keydown" : "keypress", this.handleKeyDown, this);
            var view = this.grid.view;
            view.on("refresh", this.onViewChange, this);
            view.on("rowupdated", this.onRowUpdated, this);
            view.on("beforerowremoved", this.clearSelections, this);
            view.on("beforerowsinserted", this.clearSelections, this);
            if(this.grid.isEditor){
                this.grid.on("beforeedit", this.beforeEdit,  this);
            }
        },

    	    beforeEdit : function(e){
            this.select(e.row, e.column, false, true, e.record);
        },

    	    onRowUpdated : function(v, index, r){
            if(this.selection && this.selection.record == r){
                v.onCellSelect(index, this.selection.cell[1]);
            }
        },

    	    onViewChange : function(){
            this.clearSelections(true);
        },

        getSelectedCell : function(){
            return this.selection ? this.selection.cell : null;
        },

        clearSelections : function(preventNotify){
            var s = this.selection;
            if(s){
                if(preventNotify !== true){
                    this.grid.view.onCellDeselect(s.cell[0], s.cell[1]);
                }
                this.selection = null;
                this.fireEvent("selectionchange", this, null);
            }
        },

        hasSelection : function(){
            return this.selection ? true : false;
        },

        handleMouseDown : function(g, row, cell, e){
            if(e.button !== 0 || this.isLocked()){
                return;
            };
            this.select(row, cell);
        },

        select : function(rowIndex, colIndex, preventViewNotify, preventFocus,  r){
            if(this.fireEvent("beforecellselect", this, rowIndex, colIndex) !== false){
                this.clearSelections();
                r = r || this.grid.store.getAt(rowIndex);
                this.selection = {
                    record : r,
                    cell : [rowIndex, colIndex]
                };
                if(!preventViewNotify){
                    var v = this.grid.getView();
                    v.onCellSelect(rowIndex, colIndex);
                    if(preventFocus !== true){
                        v.focusCell(rowIndex, colIndex);
                    }
                }
                this.fireEvent("cellselect", this, rowIndex, colIndex);
                this.fireEvent("selectionchange", this, this.selection);
            }
        },

    	    isSelectable : function(rowIndex, colIndex, cm){
            return !cm.isHidden(colIndex);
        },

        handleKeyDown : function(e){
            if(!e.isNavKeyPress()){
                return;
            }
            var g = this.grid, s = this.selection;
            if(!s){
                e.stopEvent();
                var cell = g.walkCells(0, 0, 1, this.isSelectable,  this);
                if(cell){
                    this.select(cell[0], cell[1]);
                }
                return;
            }
            var sm = this;
            var walk = function(row, col, step){
                return g.walkCells(row, col, step, sm.isSelectable,  sm);
            };
            var k = e.getKey(), r = s.cell[0], c = s.cell[1];
            var newCell;

            switch(k){
                 case e.TAB:
                     if(e.shiftKey){
                         newCell = walk(r, c-1, -1);
                     }else{
                         newCell = walk(r, c+1, 1);
                     }
                 break;
                 case e.DOWN:
                     newCell = walk(r+1, c, 1);
                 break;
                 case e.UP:
                     newCell = walk(r-1, c, -1);
                 break;
                 case e.RIGHT:
                     newCell = walk(r, c+1, 1);
                 break;
                 case e.LEFT:
                     newCell = walk(r, c-1, -1);
                 break;
                 case e.ENTER:
                     if(g.isEditor && !g.editing){
                        g.startEditing(r, c);
                        e.stopEvent();
                        return;
                    }
                 break;
            };
            if(newCell){
                this.select(newCell[0], newCell[1]);
                e.stopEvent();
            }
        },

        acceptsNav : function(row, col, cm){
            return !cm.isHidden(col) && cm.isCellEditable(col, row);
        },

        onEditorKey : function(field, e){
            var k = e.getKey(), newCell, g = this.grid, ed = g.activeEditor;
            if(k == e.TAB){
                if(e.shiftKey){
                    newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
                }else{
                    newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
                }
                e.stopEvent();
            }else if(k == e.ENTER){
                ed.completeEdit();
                e.stopEvent();
            }else if(k == e.ESC){
            	e.stopEvent();
                ed.cancelEdit();
            }
            if(newCell){
                g.startEditing(newCell[0], newCell[1]);
            }
        }
    });

    Ext.grid.EditorGridPanel = Ext.extend(Ext.grid.GridPanel, {

        clicksToEdit: 2,

        isEditor : true,

        detectEdit: false,

    	autoEncode : false,

        trackMouseOver: false,

        initComponent : function(){
            Ext.grid.EditorGridPanel.superclass.initComponent.call(this);

            if(!this.selModel){
                this.selModel = new Ext.grid.CellSelectionModel();
            }

            this.activeEditor = null;

    	    this.addEvents(

                "beforeedit",

                "afteredit",

                "validateedit"
            );
        },

        initEvents : function(){
            Ext.grid.EditorGridPanel.superclass.initEvents.call(this);

            this.on("bodyscroll", this.stopEditing, this, [true]);

            if(this.clicksToEdit == 1){
                this.on("cellclick", this.onCellDblClick, this);
            }else {
                if(this.clicksToEdit == 'auto' && this.view.mainBody){
                    this.view.mainBody.on("mousedown", this.onAutoEditClick, this);
                }
                this.on("celldblclick", this.onCellDblClick, this);
            }
            this.getGridEl().addClass("xedit-grid");
        },

        onCellDblClick : function(g, row, col){
            this.startEditing(row, col);
        },

        onAutoEditClick : function(e, t){
            if(e.button !== 0){
                return;
            }
            var row = this.view.findRowIndex(t);
            var col = this.view.findCellIndex(t);
            if(row !== false && col !== false){
                this.stopEditing();
                if(this.selModel.getSelectedCell){
                    var sc = this.selModel.getSelectedCell();
                    if(sc && sc.cell[0] === row && sc.cell[1] === col){
                        this.startEditing(row, col);
                    }
                }else{
                    if(this.selModel.isSelected(row)){
                        this.startEditing(row, col);
                    }
                }
            }
        },

        onEditComplete : function(ed, value, startValue){
            this.editing = false;
            this.activeEditor = null;
            ed.un("specialkey", this.selModel.onEditorKey, this.selModel);
    		var r = ed.record;
            var field = this.colModel.getDataIndex(ed.col);
            value = this.postEditValue(value, startValue, r, field);
            if(String(value) !== String(startValue)){
                var e = {
                    grid: this,
                    record: r,
                    field: field,
                    originalValue: startValue,
                    value: value,
                    row: ed.row,
                    column: ed.col,
                    cancel:false
                };
                if(this.fireEvent("validateedit", e) !== false && !e.cancel){
                    r.set(field, e.value);
                    delete e.cancel;
                    this.fireEvent("afteredit", e);
                }
            }
            this.view.focusCell(ed.row, ed.col);
        },

        startEditing : function(row, col){
            this.stopEditing();
            if(this.colModel.isCellEditable(col, row)){
                this.view.ensureVisible(row, col, true);
                var r = this.store.getAt(row);
                var field = this.colModel.getDataIndex(col);
                var e = {
                    grid: this,
                    record: r,
                    field: field,
                    value: r.data[field],
                    row: row,
                    column: col,
                    cancel:false
                };
                if(this.fireEvent("beforeedit", e) !== false && !e.cancel){
                    this.editing = true;
                    var ed = this.colModel.getCellEditor(col, row);
                    if(!ed.rendered){
                        ed.render(this.view.getEditorParent(ed));
                    }
                    (function(){
                        ed.row = row;
                        ed.col = col;
                        ed.record = r;
                        ed.on("complete", this.onEditComplete, this, {single: true});
                        ed.on("specialkey", this.selModel.onEditorKey, this.selModel);
                        this.activeEditor = ed;
                        var v = this.preEditValue(r, field);
                        ed.startEdit(this.view.getCell(row, col), v);
                    }).defer(50, this);
                }
            }
        },

    	preEditValue : function(r, field){
    		return this.autoEncode && typeof value == 'string' ? Ext.util.Format.htmlDecode(r.data[field]) : r.data[field];
    	},

    	postEditValue : function(value, originalValue, r, field){
    		return this.autoEncode && typeof value == 'string' ? Ext.util.Format.htmlEncode(value) : value;
    	},

        stopEditing : function(cancel){
            if(this.activeEditor){
                this.activeEditor[cancel === true ? 'cancelEdit' : 'completeEdit']();
            }
            this.activeEditor = null;
        }
    });
    Ext.reg('editorgrid', Ext.grid.EditorGridPanel);
    Ext.grid.GridEditor = function(field, config){
        Ext.grid.GridEditor.superclass.constructor.call(this, field, config);
        field.monitorTab = false;
    };

    Ext.extend(Ext.grid.GridEditor, Ext.Editor, {
        alignment: "tl-tl",
        autoSize: "width",
        hideEl : false,
        cls: "x-small-editor x-grid-editor",
        shim:false,
        shadow:false
    });

    Ext.grid.PropertyRecord = Ext.data.Record.create([
        {name:'name',type:'string'}, 'value'
    ]);

    Ext.grid.PropertyStore = function(grid, source){
        this.grid = grid;
        this.store = new Ext.data.Store({
            recordType : Ext.grid.PropertyRecord
        });
        this.store.on('update', this.onUpdate,  this);
        if(source){
            this.setSource(source);
        }
        Ext.grid.PropertyStore.superclass.constructor.call(this);
    };
    Ext.extend(Ext.grid.PropertyStore, Ext.util.Observable, {
            setSource : function(o){
            this.source = o;
            this.store.removeAll();
            var data = [];
            for(var k in o){
                if(this.isEditableValue(o[k])){
                    data.push(new Ext.grid.PropertyRecord({name: k, value: o[k]}, k));
                }
            }
            this.store.loadRecords({records: data}, {}, true);
        },

            onUpdate : function(ds, record, type){
            if(type == Ext.data.Record.EDIT){
                var v = record.data['value'];
                var oldValue = record.modified['value'];
                if(this.grid.fireEvent('beforepropertychange', this.source, record.id, v, oldValue) !== false){
                    this.source[record.id] = v;
                    record.commit();
                    this.grid.fireEvent('propertychange', this.source, record.id, v, oldValue);
                }else{
                    record.reject();
                }
            }
        },

            getProperty : function(row){
           return this.store.getAt(row);
        },

            isEditableValue: function(val){
            if(Ext.isDate(val)){
                return true;
            }else if(typeof val == 'object' || typeof val == 'function'){
                return false;
            }
            return true;
        },

            setValue : function(prop, value){
            this.source[prop] = value;
            this.store.getById(prop).set('value', value);
        },

            getSource : function(){
            return this.source;
        }
    });

    Ext.grid.PropertyColumnModel = function(grid, store){
        this.grid = grid;
        var g = Ext.grid;
        g.PropertyColumnModel.superclass.constructor.call(this, [
            {header: this.nameText, width:50, sortable: true, dataIndex:'name', id: 'name', menuDisabled:true},
            {header: this.valueText, width:50, resizable:false, dataIndex: 'value', id: 'value', menuDisabled:true}
        ]);
        this.store = store;
        this.bselect = Ext.DomHelper.append(document.body, {
            tag: 'select', cls: 'x-grid-editor x-hide-display', children: [
                {tag: 'option', value: 'true', html: 'true'},
                {tag: 'option', value: 'false', html: 'false'}
            ]
        });
        var f = Ext.form;

        var bfield = new f.Field({
            el:this.bselect,
            bselect : this.bselect,
            autoShow: true,
            getValue : function(){
                return this.bselect.value == 'true';
            }
        });
        this.editors = {
            'date' : new g.GridEditor(new f.DateField({selectOnFocus:true})),
            'string' : new g.GridEditor(new f.TextField({selectOnFocus:true})),
            'number' : new g.GridEditor(new f.NumberField({selectOnFocus:true, style:'text-align:left;'})),
            'boolean' : new g.GridEditor(bfield)
        };
        this.renderCellDelegate = this.renderCell.createDelegate(this);
        this.renderPropDelegate = this.renderProp.createDelegate(this);
    };

    Ext.extend(Ext.grid.PropertyColumnModel, Ext.grid.ColumnModel, {
            nameText : 'Name',
        valueText : 'Value',
        dateFormat : 'm/j/Y',

            renderDate : function(dateVal){
            return dateVal.dateFormat(this.dateFormat);
        },

            renderBool : function(bVal){
            return bVal ? 'true' : 'false';
        },

            isCellEditable : function(colIndex, rowIndex){
            return colIndex == 1;
        },

            getRenderer : function(col){
            return col == 1 ?
                this.renderCellDelegate : this.renderPropDelegate;
        },

            renderProp : function(v){
            return this.getPropertyName(v);
        },

            renderCell : function(val){
            var rv = val;
            if(Ext.isDate(val)){
                rv = this.renderDate(val);
            }else if(typeof val == 'boolean'){
                rv = this.renderBool(val);
            }
            return Ext.util.Format.htmlEncode(rv);
        },

            getPropertyName : function(name){
            var pn = this.grid.propertyNames;
            return pn && pn[name] ? pn[name] : name;
        },

            getCellEditor : function(colIndex, rowIndex){
            var p = this.store.getProperty(rowIndex);
            var n = p.data['name'], val = p.data['value'];
            if(this.grid.customEditors[n]){
                return this.grid.customEditors[n];
            }
            if(Ext.isDate(val)){
                return this.editors['date'];
            }else if(typeof val == 'number'){
                return this.editors['number'];
            }else if(typeof val == 'boolean'){
                return this.editors['boolean'];
            }else{
                return this.editors['string'];
            }
        }
    });

    Ext.grid.PropertyGrid = Ext.extend(Ext.grid.EditorGridPanel, {

            enableColumnMove:false,
        stripeRows:false,
        trackMouseOver: false,
        clicksToEdit:1,
        enableHdMenu : false,
        viewConfig : {
            forceFit:true
        },

            initComponent : function(){
            this.customEditors = this.customEditors || {};
            this.lastEditRow = null;
            var store = new Ext.grid.PropertyStore(this);
            this.propStore = store;
            var cm = new Ext.grid.PropertyColumnModel(this, store);
            store.store.sort('name', 'ASC');
            this.addEvents(

                'beforepropertychange',

                'propertychange'
            );
            this.cm = cm;
            this.ds = store.store;
            Ext.grid.PropertyGrid.superclass.initComponent.call(this);

            this.selModel.on('beforecellselect', function(sm, rowIndex, colIndex){
                if(colIndex === 0){
                    this.startEditing.defer(200, this, [rowIndex, 1]);
                    return false;
                }
            }, this);
        },

            onRender : function(){
            Ext.grid.PropertyGrid.superclass.onRender.apply(this, arguments);

            this.getGridEl().addClass('x-props-grid');
        },

            afterRender: function(){
            Ext.grid.PropertyGrid.superclass.afterRender.apply(this, arguments);
            if(this.source){
                this.setSource(this.source);
            }
        },

        setSource : function(source){
            this.propStore.setSource(source);
        },

        getSource : function(){
            return this.propStore.getSource();
        }
    });

    Ext.grid.RowNumberer = function(config){
        Ext.apply(this, config);
        if(this.rowspan){
            this.renderer = this.renderer.createDelegate(this);
        }
    };

    Ext.grid.RowNumberer.prototype = {

        header: "",

        width: 23,

        sortable: false,

        fixed:true,
        menuDisabled:true,
        dataIndex: '',
        id: 'numberer',
        rowspan: undefined,

        renderer : function(v, p, record, rowIndex){
            if(this.rowspan){
                p.cellAttr = 'rowspan="'+this.rowspan+'"';
            }
            return rowIndex+1;
        }
    };

    Ext.grid.CheckboxSelectionModel = Ext.extend(Ext.grid.RowSelectionModel, {

        header: ' ',

        width: 20,

        sortable: false,

        menuDisabled:true,
        fixed:true,
        dataIndex: '',
        id: 'checker',

        initEvents : function(){
            Ext.grid.CheckboxSelectionModel.superclass.initEvents.call(this);
            this.grid.on('render', function(){
                var view = this.grid.getView();
                view.mainBody.on('mousedown', this.onMouseDown, this);
                Ext.fly(view.innerHd).on('mousedown', this.onHdMouseDown, this);

            }, this);
        },

        onMouseDown : function(e, t){
            if(e.button === 0 && t.className == 'x-grid3-row-checker'){
                e.stopEvent();
                var row = e.getTarget('.x-grid3-row');
                if(row){
                    var index = row.rowIndex;
                    if(this.isSelected(index)){
                        this.deselectRow(index);
                    }else{
                        this.selectRow(index, true);
                    }
                }
            }
        },

        onHdMouseDown : function(e, t){
            if(t.className == 'x-grid3-hd-checker'){
                e.stopEvent();
                var hd = Ext.fly(t.parentNode);
                var isChecked = hd.hasClass('x-grid3-hd-checker-on');
                if(isChecked){
                    hd.removeClass('x-grid3-hd-checker-on');
                    this.clearSelections();
                }else{
                    hd.addClass('x-grid3-hd-checker-on');
                    this.selectAll();
                }
            }
        },

        renderer : function(v, p, record){
            return ' ';
        }
    });

    Ext.LoadMask = function(el, config){
        this.el = Ext.get(el);
        Ext.apply(this, config);
        if(this.store){
            this.store.on('beforeload', this.onBeforeLoad, this);
            this.store.on('load', this.onLoad, this);
            this.store.on('loadexception', this.onLoad, this);
            this.removeMask = Ext.value(this.removeMask, false);
        }else{
            var um = this.el.getUpdater();
            um.showLoadIndicator = false;         um.on('beforeupdate', this.onBeforeLoad, this);
            um.on('update', this.onLoad, this);
            um.on('failure', this.onLoad, this);
            this.removeMask = Ext.value(this.removeMask, true);
        }
    };

    Ext.LoadMask.prototype = {

        msg : 'Loading...',

        msgCls : 'x-mask-loading',

        disabled: false,

        disable : function(){
           this.disabled = true;
        },

        enable : function(){
            this.disabled = false;
        },

            onLoad : function(){
            this.el.unmask(this.removeMask);
        },

            onBeforeLoad : function(){
            if(!this.disabled){
                this.el.mask(this.msg, this.msgCls);
            }
        },

        show: function(){
            this.onBeforeLoad();
        },

        hide: function(){
            this.onLoad();
        },

            destroy : function(){
            if(this.store){
                this.store.un('beforeload', this.onBeforeLoad, this);
                this.store.un('load', this.onLoad, this);
                this.store.un('loadexception', this.onLoad, this);
            }else{
                var um = this.el.getUpdater();
                um.un('beforeupdate', this.onBeforeLoad, this);
                um.un('update', this.onLoad, this);
                um.un('failure', this.onLoad, this);
            }
        }
    };

    Ext.ProgressBar = Ext.extend(Ext.BoxComponent, {

        baseCls : 'x-progress',

        waitTimer : null,

        initComponent : function(){
            Ext.ProgressBar.superclass.initComponent.call(this);
            this.addEvents(

                "update"
            );
        },

        onRender : function(ct, position){
            Ext.ProgressBar.superclass.onRender.call(this, ct, position);

            var tpl = new Ext.Template(
                '',
                    '',
                        '',
                            '',
                                ' ',
                            '',
                        '',
                        '',
                            ' ',
                        '',
                    '',
                ''
            );

            if(position){
                this.el = tpl.insertBefore(position, {cls: this.baseCls}, true);
            }else{
                this.el = tpl.append(ct, {cls: this.baseCls}, true);
            }
            if(this.id){
                this.el.dom.id = this.id;
            }
            var inner = this.el.dom.firstChild;
            this.progressBar = Ext.get(inner.firstChild);

            if(this.textEl){

                this.textEl = Ext.get(this.textEl);
                delete this.textTopEl;
            }else{

                this.textTopEl = Ext.get(this.progressBar.dom.firstChild);
                var textBackEl = Ext.get(inner.childNodes[1]);
                this.textTopEl.setStyle("z-index", 99).addClass('x-hidden');
                this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, textBackEl.dom.firstChild]);
                this.textEl.setWidth(inner.offsetWidth);
            }
            if(this.value){
                this.updateProgress(this.value, this.text);
            }else{
                this.updateText(this.text);
            }
            this.setSize(this.width || 'auto', 'auto');
            this.progressBar.setHeight(inner.offsetHeight);
        },

        updateProgress : function(value, text){
            this.value = value || 0;
            if(text){
                this.updateText(text);
            }
            var w = Math.floor(value*this.el.dom.firstChild.offsetWidth);
            this.progressBar.setWidth(w);
            if(this.textTopEl){

                this.textTopEl.removeClass('x-hidden').setWidth(w);
            }
            this.fireEvent('update', this, value, text);
            return this;
        },

        wait : function(o){
            if(!this.waitTimer){
                var scope = this;
                o = o || {};
                this.waitTimer = Ext.TaskMgr.start({
                    run: function(i){
                        var inc = o.increment || 10;
                        this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*.01);
                    },
                    interval: o.interval || 1000,
                    duration: o.duration,
                    onStop: function(){
                        if(o.fn){
                            o.fn.apply(o.scope || this);
                        }
                        this.reset();
                    },
                    scope: scope
                });
            }
            return this;
        },

        isWaiting : function(){
            return this.waitTimer != null;
        },

        updateText : function(text){
            this.text = text || ' ';
            this.textEl.update(this.text);
            return this;
        },

        setSize : function(w, h){
            Ext.ProgressBar.superclass.setSize.call(this, w, h);
            if(this.textTopEl){
                var inner = this.el.dom.firstChild;
                this.textEl.setSize(inner.offsetWidth, inner.offsetHeight);
            }
            return this;
        },

        reset : function(hide){
            this.updateProgress(0);
            if(this.textTopEl){
                this.textTopEl.addClass('x-hidden');
            }
            if(this.waitTimer){
                this.waitTimer.onStop = null;
                Ext.TaskMgr.stop(this.waitTimer);
                this.waitTimer = null;
            }
            if(hide === true){
                this.hide();
            }
            return this;
        }
    });
    Ext.reg('progress', Ext.ProgressBar);
    Ext.debug = {};

    (function(){

    var cp;

    function createConsole(){

        var scriptPanel = new Ext.debug.ScriptsPanel();
        var logView = new Ext.debug.LogPanel();
        var tree = new Ext.debug.DomTree();

        var tabs = new Ext.TabPanel({
            activeTab: 0,
            border: false,
            tabPosition: 'bottom',
            items: [{
                title: 'Debug Console',
                layout:'border',
                items: [logView, scriptPanel]
            },{
                title: 'DOM Inspector',
                layout:'border',
                items: [tree]
            }]
        });

        cp = new Ext.Panel({
            id: 'x-debug-browser',
            title: 'Console',
            collapsible: true,
            animCollapse: false,
            style: 'position:absolute;left:0;bottom:0;',
            height:200,
            logView: logView,
            layout: 'fit',

            tools:[{
                id: 'close',
                handler: function(){
                    cp.destroy();
                    cp = null;
                    Ext.EventManager.removeResizeListener(handleResize);
                }
            }],

            items: tabs
        });

        cp.render(document.body);

        cp.resizer = new Ext.Resizable(cp.el, {
            minHeight:50,
            handles: "n",
            pinned: true,
            transparent:true,
            resizeElement : function(){
                var box = this.proxy.getBox();
                this.proxy.hide();
                cp.setHeight(box.height);
                return box;
            }
        });

        function handleResize(){
            cp.setWidth(Ext.getBody().getViewSize().width);
        }
        Ext.EventManager.onWindowResize(handleResize);

        handleResize();
    }

    Ext.apply(Ext, {
        log : function(){
            if(!cp){
                createConsole();
            }
            cp.logView.log.apply(cp.logView, arguments);
        },

        logf : function(format, arg1, arg2, etc){
            Ext.log(String.format.apply(String, arguments));
        },

        dump : function(o){
            if(typeof o == 'string' || typeof o == 'number' || typeof o == 'undefined' || Ext.isDate(o)){
                Ext.log(o);
            }else if(!o){
                Ext.log("null");
            }else if(typeof o != "object"){
                Ext.log('Unknown return type');
            }else if(Ext.isArray(o)){
                Ext.log('['+o.join(',')+']');
            }else{
                var b = ["{\n"];
                for(var key in o){
                    var to = typeof o[key];
                    if(to != "function" && to != "object"){
                        b.push(String.format("  {0}: {1},\n", key, o[key]));
                    }
                }
                var s = b.join("");
                if(s.length > 3){
                    s = s.substr(0, s.length-2);
                }
                Ext.log(s + "\n}");
            }
        },

        _timers : {},

        time : function(name){
            name = name || "def";
            Ext._timers[name] = new Date().getTime();
        },

        timeEnd : function(name, printResults){
            var t = new Date().getTime();
            name = name || "def";
            var v = String.format("{0} ms", t-Ext._timers[name]);
            Ext._timers[name] = new Date().getTime();
            if(printResults !== false){
                Ext.log('Timer ' + (name == "def" ? v : name + ": " + v));
            }
            return v;
        }
    });

    })();

    Ext.debug.ScriptsPanel = Ext.extend(Ext.Panel, {
        id:'x-debug-scripts',
        region: 'east',
        minWidth: 200,
        split: true,
        width: 350,
        border: false,
        layout:'anchor',
        style:'border-width:0 0 0 1px;',

        initComponent : function(){

            this.scriptField = new Ext.form.TextArea({
                anchor: '100% -26',
                style:'border-width:0;'
            });

            this.trapBox = new Ext.form.Checkbox({
                id: 'console-trap',
                boxLabel: 'Trap Errors',
                checked: true
            });

            this.toolbar = new Ext.Toolbar([{
                    text: 'Run',
                    scope: this,
                    handler: this.evalScript
                },{
                    text: 'Clear',
                    scope: this,
                    handler: this.clear
                },
                '->',
                this.trapBox,
                ' ', ' '
            ]);

            this.items = [this.toolbar, this.scriptField];

            Ext.debug.ScriptsPanel.superclass.initComponent.call(this);
        },

        evalScript : function(){
            var s = this.scriptField.getValue();
            if(this.trapBox.getValue()){
                try{
                    var rt = eval(s);
                    Ext.dump(rt === undefined? '(no return)' : rt);
                }catch(e){
                    Ext.log(e.message || e.descript);
                }
            }else{
                var rt = eval(s);
                Ext.dump(rt === undefined? '(no return)' : rt);
            }
        },

        clear : function(){
            this.scriptField.setValue('');
            this.scriptField.focus();
        }

    });

    Ext.debug.LogPanel = Ext.extend(Ext.Panel, {
        autoScroll: true,
        region: 'center',
        border: false,
        style:'border-width:0 1px 0 0',

        log : function(){
            var markup = [  '',
                        Ext.util.Format.htmlEncode(Array.prototype.join.call(arguments, ', ')).replace(/\n/g, '
    ').replace(/\s/g, ' '),
                        ''].join('');

            this.body.insertHtml('beforeend', markup);
            this.body.scrollTo('top', 100000);
        },

        clear : function(){
            this.body.update('');
            this.body.dom.scrollTop = 0;
        }
    });

    Ext.debug.DomTree = Ext.extend(Ext.tree.TreePanel, {
        enableDD:false ,
        lines:false,
        rootVisible:false,
        animate:false,
        hlColor:'ffff9c',
        autoScroll: true,
        region:'center',
        border:false,

        initComponent : function(){

            Ext.debug.DomTree.superclass.initComponent.call(this);

                    var styles = false, hnode;
            var nonSpace = /^\s*$/;
            var html = Ext.util.Format.htmlEncode;
            var ellipsis = Ext.util.Format.ellipsis;
            var styleRe = /\s?([a-z\-]*)\:([^;]*)(?:[;\s\n\r]*)/gi;

            function findNode(n){
                if(!n || n.nodeType != 1 || n == document.body || n == document){
                    return false;
                }
                var pn = [n], p = n;
                while((p = p.parentNode) && p.nodeType == 1 && p.tagName.toUpperCase() != 'HTML'){
                    pn.unshift(p);
                }
                var cn = hnode;
                for(var i = 0, len = pn.length; i < len; i++){
                    cn.expand();
                    cn = cn.findChild('htmlNode', pn[i]);
                    if(!cn){                     return false;
                    }
                }
                cn.select();
                var a = cn.ui.anchor;
                treeEl.dom.scrollTop = Math.max(0 ,a.offsetTop-10);
                            cn.highlight();
                return true;
            }

            function nodeTitle(n){
                var s = n.tagName;
                if(n.id){
                    s += '#'+n.id;
                }else if(n.className){
                    s += '.'+n.className;
                }
                return s;
            }

            function onNodeSelect(t, n, last){
                return;
                if(last && last.unframe){
                    last.unframe();
                }
                var props = {};
                if(n && n.htmlNode){
                    if(frameEl.pressed){
                        n.frame();
                    }
                    if(inspecting){
                        return;
                    }
                    addStyle.enable();
                    reload.setDisabled(n.leaf);
                    var dom = n.htmlNode;
                    stylePanel.setTitle(nodeTitle(dom));
                    if(styles && !showAll.pressed){
                        var s = dom.style ? dom.style.cssText : '';
                        if(s){
                            var m;
                            while ((m = styleRe.exec(s)) != null){
                                props[m[1].toLowerCase()] = m[2];
                            }
                        }
                    }else if(styles){
                        var cl = Ext.debug.cssList;
                        var s = dom.style, fly = Ext.fly(dom);
                        if(s){
                            for(var i = 0, len = cl.length; i' + ellipsis(html(String(c.nodeValue)), 35) + '',
                            cls: 'x-tree-noicon'
                        }));
                    }
                }
                cb();
            };

            this.root = this.setRootNode(new Ext.tree.TreeNode('Ext'));

            hnode = this.root.appendChild(new Ext.debug.HtmlNode(
                    document.getElementsByTagName('html')[0]
            ));

        }
    });

    Ext.debug.HtmlNode = function(){
        var html = Ext.util.Format.htmlEncode;
        var ellipsis = Ext.util.Format.ellipsis;
        var nonSpace = /^\s*$/;

        var attrs = [
            {n: 'id', v: 'id'},
            {n: 'className', v: 'class'},
            {n: 'name', v: 'name'},
            {n: 'type', v: 'type'},
            {n: 'src', v: 'src'},
            {n: 'href', v: 'href'}
        ];

        function hasChild(n){
            for(var i = 0, c; c = n.childNodes[i]; i++){
                if(c.nodeType == 1){
                    return true;
                }
            }
            return false;
        }

        function renderNode(n, leaf){
            var tag = n.tagName.toLowerCase();
            var s = '<' + tag;
            for(var i = 0, len = attrs.length; i < len; i++){
                var a = attrs[i];
                var v = n[a.n];
                if(v && !nonSpace.test(v)){
                    s += ' ' + a.v + '="' + html(v) +'"';
                }
            }
            var style = n.style ? n.style.cssText : '';
            if(style){
                s += ' style="' + html(style.toLowerCase()) +'"';
            }
            if(leaf && n.childNodes.length > 0){
                s+='>' + ellipsis(html(String(n.innerHTML)), 35) + '</'+tag+'>';
            }else if(leaf){
                s += ' />';
            }else{
                s += '>';
            }
            return s;
        }

        var HtmlNode = function(n){
            var leaf = !hasChild(n);
            this.htmlNode = n;
            this.tagName = n.tagName.toLowerCase();
            var attr = {
                text : renderNode(n, leaf),
                leaf : leaf,
                cls: 'x-tree-noicon'
            };
            HtmlNode.superclass.constructor.call(this, attr);
            this.attributes.htmlNode = n;         if(!leaf){
                this.on('expand', this.onExpand,  this);
                this.on('collapse', this.onCollapse,  this);
            }
        };

        Ext.extend(HtmlNode, Ext.tree.AsyncTreeNode, {
            cls: 'x-tree-noicon',
            preventHScroll: true,
            refresh : function(highlight){
                var leaf = !hasChild(this.htmlNode);
                this.setText(renderNode(this.htmlNode, leaf));
                if(highlight){
                    Ext.fly(this.ui.textNode).highlight();
                }
            },

            onExpand : function(){
                if(!this.closeNode && this.parentNode){
                    this.closeNode = this.parentNode.insertBefore(new Ext.tree.TreeNode({
                        text:'</' + this.tagName + '>',
                        cls: 'x-tree-noicon'
                    }), this.nextSibling);
                }else if(this.closeNode){
                    this.closeNode.ui.show();
                }
            },

            onCollapse : function(){
                if(this.closeNode){
                    this.closeNode.ui.hide();
                }
            },

            render : function(bulkRender){
                HtmlNode.superclass.render.call(this, bulkRender);
            },

            highlightNode : function(){
                        },

            highlight : function(){
                        },

            frame : function(){
                this.htmlNode.style.border = '1px solid #0000ff';
                        },

            unframe : function(){
                            this.htmlNode.style.border = '';
            }
        });

        return HtmlNode;
    }();