/********
* @version: 0.8.0 - Professional Edition (Coolite Commercial License)
* @author: Coolite Inc. http://www.coolite.com/
* @date: 2009-03-19
* @copyright: Copyright (c) 2006-2009, Coolite Inc. (http://www.coolite.com/). All rights reserved.
* @license: See license.txt and http://www.coolite.com/license/. 
* @website: http://www.coolite.com/
********/

Ext.ns("Coolite", "Coolite.Ext");

Coolite.Ext.Version = "0.8.0";

Ext.isEmptyObj = function (o) {
    if (!(!Ext.isEmpty(o) && typeof o == "object")) {
        return false;
    }
    
    for (var p in o) {
        return false;
    }
    return true;
};

Coolite.Ext.Viewport = Ext.extend(Ext.Container, {
    initComponent: function () {
        Coolite.Ext.Viewport.superclass.initComponent.call(this);
        var html = document.getElementsByTagName("html")[0];
        html.className += " x-viewport";
        html.style.height = "100%";
        this.el = Ext.get(document.forms[0]);
        this.el.setHeight = this.el.setWidth = this.el.setSize = Ext.emptyFn;
        this.el.dom.scroll = "no";
        this.allowDomMove = false;
        this.autoWidth = this.autoHeight = true;
        Ext.EventManager.onWindowResize(this.fireResize, this);
        this.renderTo = this.el;
        Ext.getBody().applyStyles({
            overflow: "hidden",
            margin: "0",
            padding: "0",
            border: "0px none",
            height: "100%"
        });
        this.el.applyStyles({ height: "100%", width: "100%" });
    },

    fireResize: function (w, h) {
        this.fireEvent("resize", this, w, h, w, h);
    }
});

Ext.reg("cooliteviewport", Coolite.Ext.Viewport);

//Ext.layout.Accordion.prototype.renderItem = Ext.layout.Accordion.prototype.renderItem.createSequence(function(c){
//    if (this.keepActive) {
//        c.on('beforecollapse', this.beforeCollapse, this);
//    }
//});

//Ext.override(Ext.layout.Accordion, {
//    beforeExpand: function(p, anim) {
//        this.changing = true;
//        var ai = this.activeItem;
//        if (ai) {
//            if (this.sequence) {
//                delete this.activeItem;
//                if (!ai.collapsed) {
//                    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.changing = false;
//        this.layout();
//    },

//    beforeCollapse: function(p) {
//        return this.changing || (p !== this.activeItem);
//    },

//    renderAll: function(ct, target) {
//        Ext.layout.Accordion.superclass.renderAll.call(this, ct, target);

//        var items = ct.items;
//        if (this.keepActive && !this.activeItem && items && items.getCount() > 0) {
//            this.setActiveItem(0);
//        }
//    }
//});


Coolite.Ext.AnchorLayout = Ext.extend(Ext.layout.AnchorLayout, {
    monitorResize: true,
    getAnchorViewSize: function (ct, target) {
    return ((target.dom == Ext.getBody().dom) || (target.dom == document.forms[0])) ?
                   target.getViewSize() : target.getStyleSize();
    }
});

Ext.reg("cooliteanchor", Coolite.Ext.AnchorLayout);

Ext.Container.LAYOUTS.cooliteanchor = Coolite.Ext.AnchorLayout;

Coolite.Ext.FitLayout = Ext.extend(Ext.layout.FitLayout, {
    onLayout: function(ct, target) {
        Ext.layout.FitLayout.superclass.onLayout.call(this, ct, target);
        if (!this.container.collapsed) {
            if (target.dom == Ext.getBody().dom || target.dom == document.forms[0]) {
                this.setItemSize(this.activeItem || ct.items.itemAt(0), target.getViewSize());
            } else {
                this.setItemSize(this.activeItem || ct.items.itemAt(0), target.getStyleSize());
            }
        }
    }
});

Ext.reg("coolitefit", Coolite.Ext.FitLayout);

Ext.Container.LAYOUTS.coolitefit = Coolite.Ext.FitLayout;

Coolite.Ext.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {
    monitorResize: true,
    extraCls: "x-column",
    scrollOffset: 0,
    margin: 0,
    split: false,
    fitHeight: false,

    // private
    isValidParent: function (c, target) {
        return c.getEl().dom.parentNode == this.innerCt.dom;
    },

    renderAll: function (ct, target) {
        if (this.split && !this.splitBars) {
            this.splitBars = [];
            this.margin = 5;
        }

        Coolite.Ext.ColumnLayout.superclass.renderAll.apply(this, arguments);
    },

    // private
    onLayout: function (ct, target) {
        var cs = ct.items.items, len = cs.length, c, cel, 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 = Ext.isIE && ((target.dom != Ext.getBody().dom) && (target.dom != document.forms[0])) ? target.getStyleSize() : target.getViewSize();

        if (size.width < 1 && size.height < 1) { // display none?
            return;
        }

        var w = size.width - target.getPadding("lr") - this.scrollOffset,
            h = size.height - target.getPadding("tb");
        this.availableWidth = w;
        var pw = this.availableWidth;

        if (this.split) {
            this.minWidth = Math.min(pw / len, 100);
            this.maxWidth = pw - ((this.minWidth + 5) * (len ? (len - 1) : 1));
        }

        if (this.fitHeight) {
            this.innerCt.setSize(w, h);
        }
        else {
            this.innerCt.setWidth(w);
        }

        var lastProportionedColumn;
        for (i = 0; i < len; i++) {
            c = cs[i];
            cel = c.getEl();

            if (this.margin && (i < (len - 1))) {
                cel.setStyle("margin-right", this.margin + "px");
            }
            if (c.columnWidth) {
                lastProportionedColumn = i;
            } else {
                pw -= (c.getSize().width + cel.getMargins("lr"));
            }
        }

        var remaining = (pw = pw < 0 ? 0 : pw);

        var splitterPos = 0, cw;
        for (i = 0; i < len; i++) {
            c = cs[i];
            cel = c.getEl();
            if (c.columnWidth) {
                cw = (i == lastProportionedColumn) ? remaining : Math.floor(c.columnWidth * pw);
                if (this.fitHeight) {
                    c.setSize(cw - cel.getMargins("lr"), h);
                }
                else {
                    c.setSize(cw - cel.getMargins("lr"));
                }
                //c.setSize(cw - cel.getMargins("lr"), this.fitHeight ? h : null);
                remaining -= cw;
            } else if (this.fitHeight) {
                c.setHeight(h);
            }

            if (this.split) {
                cw = cel.getWidth();

                if (i < (len - 1)) {
                    splitterPos += cw;
                    if (this.splitBars[i]) {
                        this.splitBars[i].el.setHeight(h);
                    } else {
                        this.splitBars[i] = new Ext.SplitBar(this.innerCt.createChild({
                            cls: "x-layout-split x-layout-split-west",
                            style: {
                                top: "0px",
                                left: splitterPos + "px",
                                height: h + "px"
                            }
                        }), cel);
                        this.splitBars[i].index = i;
                        this.splitBars[i].leftComponent = c;
                        this.splitBars[i].addListener("resize", this.onColumnResize, this);
                        this.splitBars[i].minSize = this.minWidth;
                    }

                    splitterPos += this.splitBars[i].el.getWidth();
                }

                delete c.columnWidth;
            }
        }

        if (this.split) {
            this.setMaxWidths();
        }
    },

    //  On column resize, explicitly size the Components to the left and right of the SplitBar
    onColumnResize: function (sb, newWidth) {
        if (sb.dragSpecs.startSize) {
            sb.leftComponent.setWidth(newWidth);
            var items = this.container.items.items;
            var expansion = newWidth - sb.dragSpecs.startSize;
            for (var i = sb.index + 1, len = items.length; expansion && i < len; i++) {
                var c = items[i];
                var w = c.el.getWidth();
                newWidth = w - expansion;
                if (newWidth < this.minWidth) {
                    c.setWidth(this.minWidth);
                } else if (newWidth > this.maxWidth) {
                    expansion -= (newWidth - this.maxWidth);
                    c.setWidth(this.maxWidth);
                } else {
                    c.setWidth(c.el.getWidth() - expansion);
                    break;
                }
            }
            this.setMaxWidths();
        }
    },

    setMaxWidths: function () {
        var items = this.container.items.items;

        var spare = items[items.length - 1].el.dom.offsetWidth - 100;

        for (var i = items.length - 2; i > -1; i--) {
            var sb = this.splitBars[i], sbel = sb.el, c = items[i], cel = c.el;
            var itemWidth = cel.dom.offsetWidth;
            sbel.setStyle("left", (cel.getX() - Ext.fly(cel.dom.parentNode).getX() + itemWidth) + "px");
            sb.maxSize = itemWidth + spare;
            spare = itemWidth - 100;
        }
    },

    onResize: function () {
        if (this.split) {
            var items = this.container.items.items;
            if (items[0].rendered) {
                var tw = 0, c;
                for (var i = 0; i < items.length; i++) {
                    c = items[i];
                    tw += c.el.getWidth() + c.el.getMargins("lr");
                }
                for (var j = 0; j < items.length; j++) {
                    c = items[j];
                    c.columnWidth = (c.el.getWidth() + c.el.getMargins("lr")) / tw;
                }
            }
        }
        Coolite.Ext.ColumnLayout.superclass.onResize.apply(this, arguments);
    }
});
Ext.reg("coolitecolumn", Coolite.Ext.ColumnLayout);
Ext.Container.LAYOUTS.coolitecolumn = Coolite.Ext.ColumnLayout;

Ext.apply(Ext.lib.Ajax, {
    serializeForm: function (form) {
        if (typeof form == "string") {
            form = (document.getElementById(form) || document.forms[form]);
        }

        var el, name, val, disabled, data = "", hasSubmit = false;
        hasSubmit = form.ignoreAllSubmitFields || false;
        for (var i = 0; i < form.elements.length; i++) {
            el = form.elements[i];
            disabled = form.elements[i].disabled;
            name = form.elements[i].name;
            val = form.elements[i].value;

            if (!disabled && name) {
                switch (el.type) {
                    case "select-one":
                    case "select-multiple":
                        for (var j = 0; j < el.options.length; j++) {
                            if (el.options[j].selected) {
                                if (Ext.isIE) {
                                    data += encodeURIComponent(name) + "=" + encodeURIComponent(el.options[j].attributes.value.specified ? el.options[j].value : el.options[j].text) + "&";
                                } else {
                                    data += encodeURIComponent(name) + "=" + encodeURIComponent(el.options[j].hasAttribute("value") ? el.options[j].value : el.options[j].text) + "&";
                                }
                            }
                        }
                        break;
                    case "radio":
                    case "checkbox":
                        if (el.checked) {
                            data += encodeURIComponent(name) + "=" + encodeURIComponent(val) + "&";
                        }
                        break;
                    case "file":
                    case undefined:
                    case "reset":
                    case "button":
                        break;
                    case "submit":
                        if (hasSubmit === false) {
                            data += encodeURIComponent(name) + "=" + encodeURIComponent(val) + "&";
                            hasSubmit = true;
                        }
                        break;
                    default:
                        data += encodeURIComponent(name) + "=" + encodeURIComponent(val) + "&";
                        break;
                }
            }
        }
        data = data.substr(0, data.length - 1);
        return data;
    }
});

Coolite.Ext.on = function (target, eventName, handler, scope, mode, cfg) {
    var el = target;
    if (typeof target == "string") {
        el = Ext.get(target);
    }

    if (!Ext.isEmpty(el)) {
        if (mode && mode == "client") {
            el.on(eventName, handler.fn, scope, handler);
        } else {
            el.on(eventName, handler, scope, cfg);
        }
    }
};

Ext.form.Hidden.override({
    setValue: function (v) {
        var temp = this.rendered ? this.el.dom.value : this.value;
        this.value = v;        
        if (this.rendered) {
            this.el.dom.value = (v === null || v === undefined ? "" : v);
            this.validate();
        }
        if (v != temp) {
            this.fireEvent("change");
        }
    }
});

Ext.form.Label.override({
    iconAlign: "left",
    isFormField: true,

    // for correct FormPanel reset
    reset: function() {
    },
    validate: function() {
        return true;
    },

    valueElement: function() {
        var textEl = document.createElement("span");
        textEl.className = "x-label-value";
        textEl.innerHTML = this.text ? Ext.util.Format.htmlEncode(this.text) : (this.html || "");
        this.textEl = textEl;

        return textEl;
    },

    onRender: function(ct, position) {
        if (!this.el) {
            this.el = document.createElement(this.forId ? "label" : "span");
            this.el.id = this.getId();

            var img = document.createElement("img");
            img.src = Ext.BLANK_IMAGE_URL;
            img.className = "x-label-icon " + (this.iconCls || "");

            if (Ext.isEmpty(this.iconCls)) {
                img.style.display = "none";
            }

            if (this.iconAlign == "left") {
                this.el.appendChild(img);
            }

            this.el.appendChild(this.valueElement());

            if (this.iconAlign == "right") {
                this.el.appendChild(img);
            }

            if (this.forId) {
                this.el.setAttribute("htmlFor", this.forId);
            }
        }
        Ext.form.Label.superclass.onRender.call(this, ct, position);
    },

    getText: function(encode) {
        return this.rendered ? encode === true ? Ext.util.Format.htmlEncode(this.textEl.innerHTML) : this.textEl.innerHTML : this.text;
    },

    setText: function(t, encode) {
        this.text = t;
        if (this.rendered) {
            this.textEl.innerHTML = encode !== false ? Ext.util.Format.htmlEncode(t) : t;
        }
        return this;
    },

    setIconClass: function(cls) {
        var oldCls = this.iconCls;
        this.iconCls = cls;
        if (this.rendered) {
            var img = this.el.child("img.x-label-icon");
            img.replaceClass(oldCls, this.iconCls);
            img.dom.style.display = (cls === "") ? "none" : "inline";
        }
    }
});

Coolite.Ext.HyperLink = Ext.extend(Ext.form.Label, {
    cls: "",
    url: "#",

    valueElement: function () {
        var textEl = document.createElement("a");
        textEl.style.verticalAlign = "middle";
        if (!Ext.isEmpty(this.cls, false)) {
            textEl.className = this.cls;
        }

        textEl.setAttribute("href", this.url);

        if (this.disabled) {
            textEl.setAttribute("disabled", "1");
            textEl.removeAttribute("href");
        }

        if (!Ext.isEmpty(this.target, false)) {
            textEl.setAttribute("target", this.target);
        }

        if (this.imageUrl) {
            textEl.innerHTML = '<img src="' + this.imageUrl + '" />';
        }
        else {
            textEl.innerHTML = this.text ? Ext.util.Format.htmlEncode(this.text) : (this.html || "");
        }
        this.textEl = textEl;
        return this.textEl;
    },

    setDisabled: function (disabled) {
        Coolite.Ext.HyperLink.superclass.setDisabled.apply(this, arguments);
        if (disabled) {
            this.textEl.setAttribute("disabled", "1");
            this.textEl.removeAttribute("href");
        }
        else {
            this.textEl.removeAttribute("disabled");
            this.textEl.setAttribute("href", this.url);
        }
    },

    setImageUrl: function (imageUrl) {
        this.imageUrl = imageUrl;
        this.textEl.innerHTML = '<img style="border:0px;" src="' + this.imageUrl + '" />';
    },

    setUrl: function (url) {
        this.url = url;
        this.textEl.setAttribute("href", this.url);
    },

    setTarget: function (target) {
        this.target = target;
        this.textEl.setAttribute("target", this.target);
    }
});

Ext.reg("hyperlink", Coolite.Ext.HyperLink);

Coolite.Ext.Image = Ext.extend(Ext.form.Label, {
    cls: "",

    onRender: function (ct, position) {
        if (!this.el) {
            this.el = document.createElement("img");
            this.el.id = this.getId();
            this.el.src = this.imageUrl;
            this.el.style.border = "none";

            if (this.altText) {
                this.el.setAttribute("alt", this.altText);
            }

            if (this.align && this.align !== "notset") {
                this.el.setAttribute("align", this.align);
            }

            if (!Ext.isEmpty(this.cls, false)) {
                this.el.className = this.cls;
            }
        }
        Coolite.Ext.Image.superclass.onRender.call(this, ct, position);
    },

    setImageUrl: function (imageUrl) {
        this.imageUrl = imageUrl;
        if (this.rendered) {
            this.el.dom.removeAttribute("width");
            this.el.dom.removeAttribute("height");
            this.el.dom.src = this.imageUrl;
        }
    },

    setAlign: function (align) {
        this.align = align;
        if (this.rendered) {
            this.el.dom.setAttribute("align", this.align);
        }
    },

    setAltText: function (altText) {
        this.altText = altText;
        if (this.rendered) {
            this.el.dom.setAttribute("altText", this.altText);
        }
    }
});
Ext.reg("image", Coolite.Ext.Image);

Ext.form.ComboBox.prototype.initComponent = Ext.form.ComboBox.prototype.initComponent.createSequence(function() {
    this.initMerge();
});

Ext.form.ComboBox.prototype.onRender = Ext.form.ComboBox.prototype.onRender.createSequence(function (el) {
    this.getEl().dom.setAttribute("name", this.uniqueName || this.id);
    this.getSelectedIndexField().render(this.el.parent() || this.el);
    this.on("focus", function (el) {
        this.oldValue = this.getValue();
        var t = this.getEl().dom.value.trim();
        this.oldText = (t === this.emptyText) ? "" : t;
    });
});

Ext.form.ComboBox.prototype.onBlur = Ext.form.ComboBox.prototype.onBlur.createInterceptor(function (el) {
    var t = this.getEl().dom.value.trim(), v = this.getValue();
    this.changed = false;
    if (this.oldValue !== v || (t !== this.oldText && t !== this.emptyText)) {
        if (!Ext.isEmpty(this.selValue) && this.selText != t && this.selValue == this.getValue()) {
            this.hiddenField.value = "";
        }

        var val = this.el.dom.value,
            r = this.findRecordByText(this.displayField, val);

        this.setValue(!Ext.isEmpty(r) ? r.data[this.valueField] : this.forceSelection ? this.oldText : val);

        this.getSelectedIndexField().setValue(this.getSelectedIndex());
        this.changed = true;
    }
});

Ext.form.ComboBox.override({
    alwaysMergeItems: true,
    initMerge: function() {
        if (this.mergeItems) {
            if (this.store.getCount() > 0) {
                this.doMerge();
            }

            if (this.store.getCount() == 0 || this.alwaysMergeItems) {
                this.store.on("load", this.doMerge, this, { single: !this.alwaysMergeItems })
            }
        }
    },

    doMerge: function() {
        for (var mi = this.mergeItems.getCount() - 1; mi > -1; mi--) {
            var f = this.store.recordType.prototype.fields, dv = [];
            for (var i = 0; i < f.length; i++) {
                dv[f.items[i].name] = f.items[i].defaultValue;
            }
            if (!Ext.isEmpty(this.displayField, false)) {
                dv[this.displayField] = this.mergeItems.getAt(mi).data.text;
            }
            if (!Ext.isEmpty(this.valueField, false) && this.displayField != this.valueField) {
                dv[this.valueField] = this.mergeItems.getAt(mi).data.value;
            }
            var record = new this.store.recordType(dv);
            this.store.insert(0, record);
        }
    },

    getSelectedIndexField: function() {
        if (!this.selectedIndexField) {
            this.selectedIndexField = new Ext.form.Hidden({ id: this.id + "_SelIndex", name: this.id + "_SelIndex" });
        }
        return this.selectedIndexField;
    },

    getText: function() {
        return this.el.getValue();
    },
    getSelectedItem: function() {
        return { text: this.getText(), value: this.getValue() };
    },
    initSelect: false,
    setValueAndFireSelect: function(v) {
        this.setValue(v);

        var r = this.findRecord(this.valueField, v);

        if (!Ext.isEmpty(r)) {
            var index = this.store.indexOf(r);

            this.getSelectedIndexField().setValue(this.getSelectedIndex());

            this.initSelect = true;
            this.fireEvent("select", this, r, index);
            this.initSelect = false;
        }
    },
    findRecordByText: function(prop, text) {
        var record;
        if (this.store.getCount() > 0) {
            this.store.each(function(r) {
                if (r.data[prop] == text) {
                    record = r;
                    return false;
                }
            });
        }
        return record;
    },
    findRecordEx: function(prop, value) {
        if (this.store.snapshot && this.store.snapshot.getCount() > 0) {
            var record;
            if (this.store.snapshot.getCount() > 0) {
                this.store.snapshot.each(function(r) {
                    if (r.data[prop] == value) {
                        record = r;
                        return false;
                    }
                });
            }
            return record;
        }

        return this.findRecord(prop, value);
    },
    indexOfEx: function(record) {
        if (this.store.snapshot && this.store.snapshot.getCount() > 0) {
            return this.store.snapshot.indexOf(record);
        }

        return this.store.data.indexOf(record);
    },
    getSelectedIndex: function() {
        var r = this.findRecordEx(this.valueField, this.getValue());
        return (!Ext.isEmpty(r)) ? this.indexOfEx(r) : -1;
    },
    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.monitorTab = false;
                this.onViewClick(false);
                this.triggerBlur();
                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);
        }
    },
    onSelect: function(record, index) {
        if (this.fireEvent("beforeselect", this, record, index) !== false) {
            this.setValue(record.data[this.valueField || this.displayField]);
            this.collapse();

            this.getSelectedIndexField().setValue(this.getSelectedIndex());

            this.selValue = this.getValue();
            this.selText = this.el.dom.value;

            this.fireEvent("select", this, record, index);
        }
    },

    setInitValue: function(value) {
        if (this.store.getCount() > 0) {
            this.setLoadedValue(value);
        }
        else {
            this.setValue(value);
            this.store.on("load", this.setLoadedValue.createDelegate(this, [value]), this, { single: true });
        }
    },

    setLoadedValue: function(value) {
        this[this.fireSelectOnLoad ? "setValueAndFireSelect" : "setValue"](value);
        this.clearInvalid();
    }

});

Ext.ns("Ext.ux.layout");

Ext.ux.layout.CenterLayout = Ext.extend(Coolite.Ext.FitLayout, {
    // private
    setItemSize: function (item, size) {
        this.container.addClass("ux-layout-center");
        item.addClass("ux-layout-center-item");
        if (item && size.height > 0) {
            if (item.width) {
                size.width = item.width;
            }
            item.setSize(size);
        }
    }
});
Ext.Container.LAYOUTS["ux.center"] = Ext.ux.layout.CenterLayout;

Ext.ux.RowLayout = Ext.extend(Ext.layout.ContainerLayout, {
    monitorResize: true,
    //extraCls: "x-column",
    scrollOffset: 0,
    margin: 0,
    split: false,

    // private
    isValidParent: function(c, target) {
        return c.getEl().dom.parentNode == this.innerCt.dom;
    },

    renderAll: function(ct, target) {
        if (this.split && !this.splitBars) {
            this.splitBars = [];
            this.margin = 5;
        }

        Ext.ux.RowLayout.superclass.renderAll.apply(this, arguments);
    },

    // private
    onLayout: function(ct, target) {
        var cs = ct.items.items, len = cs.length, c, cel, 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 = Ext.isIE && ((target.dom != Ext.getBody().dom) && (target.dom != document.forms[0])) ? target.getStyleSize() : target.getViewSize();

        if (size.height < 1 && size.height < 1) { // display none?
            return;
        }

        var w = size.height - target.getPadding("tb");
        this.availableHeight = w;
        var pw = this.availableHeight;

        if (this.split) {
            this.minHeight = Math.min(pw / len, 100);
            this.maxHeight = pw - ((this.minHeight + 5) * (len ? (len - 1) : 1));
        }

        this.innerCt.setHeight(w);

        var lastProportionedColumn;
        for (i = 0; i < len; i++) {
            c = cs[i];
            cel = c.getEl();

            if (this.margin && (i < (len - 1))) {
                cel.setStyle("margin-bottom", this.margin + "px");
            }
            if (c.rowHeight) {
                lastProportionedColumn = i;
            } else {
                pw -= (c.getSize().height + cel.getMargins("tb"));
            }
        }

        var remaining = (pw = pw < 0 ? 0 : pw);

        var splitterPos = 0, cw;
        for (i = 0; i < len; i++) {
            c = cs[i];
            cel = c.getEl();
            if (c.rowHeight) {
                cw = (i == lastProportionedColumn) ? remaining : Math.floor(c.rowHeight * pw);
                c.setHeight(cw - cel.getMargins("tb"));
                if (Ext.isEmpty(c.width)) {
                    var elWidth = size.width - target.getPadding("lr") - this.scrollOffset;
                    c.setWidth(elWidth);
                }
                //c.setSize(cw - cel.getMargins("tb"), this.fitHeight ? h : null);
                remaining -= cw;
            }

            if (this.split) {
                cw = cel.getHeight();

                if (i < (len - 1)) {
                    splitterPos += cw;
                    this.splitBars[i] = new Ext.SplitBar(this.innerCt.createChild({
                        cls: "x-layout-split x-layout-split-north",
                        style: {
                            left: "0px",
                            top: splitterPos + "px",
                            width: "100%",
                            height: this.margin + "px"
                        }
                    }), cel, Ext.SplitBar.VERTICAL, Ext.SplitBar.TOP);
                    this.splitBars[i].index = i;
                    this.splitBars[i].topComponent = c;
                    this.splitBars[i].addListener("resize", this.onColumnResize, this);
                    this.splitBars[i].minSize = this.minHeight;

                    splitterPos += this.splitBars[i].el.getHeight();
                }

                delete c.rowHeight;
            }
        }

        if (this.split) {
            this.setMaxHeights();
        }
    },

    //  On column resize, explicitly size the Components to the left and right of the SplitBar
    onColumnResize: function(sb, newHeight) {
        if (sb.dragSpecs.startSize) {
            sb.topComponent.el.setStyle("height", "");
            sb.topComponent.setHeight(newHeight);
            var items = this.container.items.items;
            var expansion = newHeight - sb.dragSpecs.startSize;
            for (var i = sb.index + 1, len = items.length; expansion && i < len; i++) {
                var c = items[i];
                var w = c.el.getHeight();
                newHeight = w - expansion;
                if (newHeight < this.minHeight) {
                    c.setHeight(this.minHeight);
                } else if (newHeight > this.maxHeight) {
                    expansion -= (newHeight - this.maxHeight);
                    c.setHeight(this.maxHeight);
                } else {
                    c.setHeight(c.el.getHeight() - expansion);
                    break;
                }
            }
            this.setMaxHeights();
        }
    },

    setMaxHeights: function() {
        var items = this.container.items.items;

        var spare = items[items.length - 1].el.dom.offsetHeight - 100;

        for (var i = items.length - 2; i > -1; i--) {
            var sb = this.splitBars[i], sbel = sb.el, c = items[i], cel = c.el;
            var itemHeight = cel.dom.offsetHeight;
            sbel.setStyle("top", (cel.getY() - Ext.fly(cel.dom.parentNode).getY() + itemHeight) + "px");
            sb.maxSize = itemHeight + spare;
            spare = itemHeight - 100;
        }
    },

    onResize: function() {
        if (this.split) {
            var items = this.container.items.items;
            if (items[0].rendered) {
                var tw = 0, c;
                for (var i = 0; i < items.length; i++) {
                    c = items[i];
                    tw += c.el.getHeight() + c.el.getMargins("tb");
                }
                for (var j = 0; j < items.length; j++) {
                    c = items[j];
                    c.rowHeight = (c.el.getHeight() + c.el.getMargins("tb")) / tw;
                }
            }
        }
        Ext.ux.RowLayout.superclass.onResize.apply(this, arguments);
    },

    renderItem: function(c) {
        Ext.ux.RowLayout.superclass.renderItem.apply(this, arguments);
        c.on("collapse", function() { this.layout(); }, this);
        c.on("expand", function() { this.layout(); }, this);
    }
});

Ext.Container.LAYOUTS["ux.row"] = Ext.ux.RowLayout;

Ext.Toolbar.HtmlElement = function (config) {
    Ext.Toolbar.HtmlElement.superclass.constructor.call(this, config.target);
};

Ext.extend(Ext.Toolbar.HtmlElement, Ext.Toolbar.Item, {});

Ext.reg("coolitetbhtml", Ext.Toolbar.HtmlElement);

Coolite.Ext.ToolbarSpacer = function(config) {
    Coolite.Ext.ToolbarSpacer.superclass.constructor.call(this);
    config = config || {};
    this.width = config.width;

    this.render = function(td) {
        if (!Ext.isEmpty(this.width)) {
            td.style.width = this.width;
        }
        Coolite.Ext.ToolbarSpacer.superclass.render.call(this, td);
    };
};

Ext.extend(Coolite.Ext.ToolbarSpacer, Ext.Toolbar.Spacer);

Ext.reg("coolitetbspacer", Coolite.Ext.ToolbarSpacer);

Ext.override(Ext.Component, {
    addPlugins: function (plugins) {
        if (Ext.isEmpty(this.plugins)) {
            this.plugins = [];
        } else if (!Ext.isArray(this.plugins)) {
            this.plugins = [this.plugins];
        }
        if (Ext.isArray(plugins)) {
            for (var i = 0; i < plugins.length; i++) {
                this.plugins.push(this.initPlugin(plugins[i]));
            }
        } else {
            this.plugins.push(this.initPlugin(plugins));
        }
    },
    getForm: function (id) {
        var form = Ext.isEmpty(id) ? this.el.up("form") : Ext.get(id);
        if (!Ext.isEmpty(form)) {
            Ext.apply(form, form.dom);
            form.submit = function () {
                form.dom.submit();
            };
        }
        return form;
    }
});

Coolite.Ext.DateItem = function (config) {
    Coolite.Ext.DateItem.superclass.constructor.call(this, new Ext.DatePicker(config.picker || {}), 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(Coolite.Ext.DateItem, Ext.menu.Adapter, {
    // private
    onSelect: function (picker, date) {
        this.fireEvent("select", this, date, picker);
        Coolite.Ext.DateItem.superclass.handleClick.call(this);
    }
});

Coolite.Ext.DateMenu = function (config) {
    Coolite.Ext.DateMenu.superclass.constructor.call(this, config);
    this.plain = true;

    var ae = config.ajaxEvents;
    var listeners = config.listeners;
    config.ajaxEvents = undefined;
    config.listeners = undefined;
    
    var di = new Coolite.Ext.DateItem(config);

    config.ajaxEvents = ae;
    config.listeners = listeners;
    
    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(Coolite.Ext.DateMenu, Ext.menu.Menu, {
    cls: "x-date-menu",

    // private
    beforeDestroy: function () {
        this.picker.destroy();
    }
});

Ext.override(Ext.ColorPalette, {
    silentSelect: 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;
        }
    }
});

Coolite.Ext.ColorItem = function (config) {
    Coolite.Ext.ColorItem.superclass.constructor.call(this, new Ext.ColorPalette(config.palette), config);
    this.palette = this.component;
    this.relayEvents(this.palette, ["select"]);
    if (this.selectHandler) {
        this.on("select", this.selectHandler, this.scope);
    }
};
Ext.extend(Coolite.Ext.ColorItem, Ext.menu.Adapter);

Coolite.Ext.ColorMenu = function (config) {
    Coolite.Ext.ColorMenu.superclass.constructor.call(this, config);
    this.plain = true;
    var ci = new Coolite.Ext.ColorItem(config);
    this.add(ci);
    this.palette = ci.palette;
    //this.relayEvents(ci, ["select"]);
};
Ext.extend(Coolite.Ext.ColorMenu, Ext.menu.Menu);

Ext.override(Ext.Button, {
    setTooltip: function (tooltip) {
        this.tooltip = tooltip;
        var btnEl = this.getEl().child(this.buttonSelector);
        if (typeof tooltip == "object") {
            Ext.QuickTips.register(Ext.apply({
                target: btnEl.id
            }, tooltip));
        } else {
            btnEl.dom[this.tooltipType] = tooltip;
        }
    }
});

Ext.override(Ext.CycleButton, {
    initComponent: function () {
        this.addEvents("change");

        if (this.changeHandler) {
            this.on("change", this.changeHandler, this.scope || this);
            delete this.changeHandler;
        }

        this.itemCount = this.menu.items.length;

        this.menu.cls = "x-cycle-menu";
        var checked;
        for (var i = 0, len = this.itemCount; i < len; i++) {
            var item = this.menu.items.itemAt(i);

            item.group = item.group || this.id;

            item.itemIndex = i;
            item.on("checkchange", this.checkHandler, this);
            item.scope = this;
            item.setChecked(item.checked || false, true);

            if (item.checked) {
                checked = item;
            }
        }
        this.setActiveItem(checked, true);
        Ext.CycleButton.superclass.initComponent.call(this);

        this.on("click", this.toggleSelected, this);
    }
});

Ext.override(Ext.menu.Menu, {
    lastTargetIn: function (cmp) {
        var el = cmp.getEl ? cmp.getEl() : cmp;
        return Ext.fly(el).contains(this.trg);
    },

    createEl: function () {
        var frm = document.body;
        if (document.forms.length > 0) {
            frm = document.forms[0];
        }
        return new Ext.Layer({
            cls: "x-menu",
            shadow: this.shadow,
            shim: this.shim || true,
            constrain: false,
            parentEl: this.parentEl || frm,
            zindex: 15000
        });
    }
});

Coolite.Ext.ElementMenuItem = function (cfg) {
    this.target = cfg.target;
    Coolite.Ext.ElementMenuItem.superclass.constructor.call(this, cfg);
};

Ext.extend(Coolite.Ext.ElementMenuItem, Ext.menu.BaseItem, {
    hideOnClick: false,
    itemCls: "x-menu-item",
    shift: true,

    getComponent: function () {
        if (Ext.isEmpty(this.el.id)) {
            return null;
        }
        var cmp = Ext.getCmp(this.el.id);
        if (Ext.isEmpty(cmp)) {
            return null;
        }
        return cmp;
    },

    // private
    onRender: function (container) {

        if (this.target.getEl) {
            this.el = this.target.getEl();
        }
        else {
            this.el = Ext.get(this.target);
        }

        var cmp = Ext.getCmp(this.el.id);
        this.parentMenu.on("show", function () {
            if (!Ext.isEmpty(cmp)) {
                if (cmp.doLayout) {
                    cmp.doLayout();
                }

                if (cmp.syncSize) {
                    cmp.syncSize();
                }
            }
        });

        if (Ext.isIE) {
            this.parentMenu.shadow = false;
            this.parentMenu.el.shadow = false;

            if (!Ext.isEmpty(cmp)) {
                cmp.shadow = false;
                cmp.el.shadow = false;
            }
        }

        if (this.shift) {
            this.el.applyStyles({ "margin-left": "23px" });
        }

        this.el.swallowEvent(["keydown", "keypress"]);
        Ext.each(["keydown", "keypress"], function (eventName) {
            this.el.on(eventName, function (e) {
                if (e.isNavKeyPress()) {
                    e.stopPropagation();
                }
            }, this);
        }, this);

        if (Ext.isGecko) {
            container.removeClass("x-menu-list-item");
            container.setStyle({ width: "", height: "" });
            if (this.shift) {
                this.el.applyStyles({ "margin-left": "24px" });
            }
        }

        Coolite.Ext.ElementMenuItem.superclass.onRender.apply(this, arguments);
    },

    activate: function () {
        if (this.disabled) {
            return false;
        }

        var cmp = this.getComponent();
        if (Ext.isEmpty(cmp)) {
            return false;
        }

        this.cmp.focus();
        this.fireEvent("activate", this);
        return true;
    },

    // private
    deactivate: function () {
        this.fireEvent("deactivate", this);
    },

    // private
    disable: function () {
        var cmp = this.getComponent();
        if (Ext.isEmpty(cmp)) {
            return;
        }
        this.cmp.disable();
        Coolite.Ext.ElementMenuItem.superclass.disable.call(this);
    },

    // private
    enable: function () {
        var cmp = this.getComponent();
        if (Ext.isEmpty(cmp)) {
            return;
        }
        this.cmp.enable();
        Coolite.Ext.ElementMenuItem.superclass.enable.call(this);
    }
});

Coolite.Ext.ComboMenuItem = function (config) {
    Coolite.Ext.ComboMenuItem.superclass.constructor.call(this, new Ext.form.ComboBox(config.combobox), config);
    this.combo = this.component;
    this.addEvents("select");
    this.combo.on("render", function (combo) {
        combo.getEl().swallowEvent("click");
        combo.list.applyStyles("z-index:99999");
        combo.list.on("mousedown", function (e) {
            Ext.lib.Event.stopPropagation(e);
        });
    });
};

Ext.extend(Coolite.Ext.ComboMenuItem, Ext.menu.Adapter, {
    hideOnClick: false,
    onSelect: function (combo, record) {
        this.fireEvent("select", this, record);
        Coolite.Ext.ComboMenuItem.superclass.handleClick.call(this);
    },
    onRender: function (container) {
        Coolite.Ext.ComboMenuItem.superclass.onRender.call(this, container);

        if (Ext.isIE) {
            this.combo.list.shadow = false;
        }

        this.el.swallowEvent(["keydown", "keypress"]);
        Ext.each(["keydown", "keypress"], function (eventName) {
            this.el.on(eventName, function (e) {
                if (e.isNavKeyPress()) {
                    e.stopPropagation();
                }
            }, this);
        }, this);

        if (Ext.isGecko) {
            container.setOverflow("auto");
            var containerSize = container.getSize();
            this.combo.wrap.setStyle("position", "fixed");
            container.setSize(containerSize);
        }
    }
});

Coolite.Ext.DateFieldMenuItem = function (config) {
    Coolite.Ext.DateFieldMenuItem.superclass.constructor.call(this, new Ext.form.DateField(config.dateField), config);
    this.dateField = this.component;
    this.dateField.menu = new Ext.menu.DateMenu({
        allowOtherMenus: true
    });

    this.dateField.on("render", function (dateField) {
        dateField.getEl().swallowEvent("click");
    });
};

Ext.extend(Coolite.Ext.DateFieldMenuItem, Ext.menu.Adapter, {
    hideOnClick: false,
    canActivate: false,
    onRender: function (container) {
        Coolite.Ext.DateFieldMenuItem.superclass.onRender.call(this, container);

        this.el.swallowEvent(["keydown", "keypress"]);
        Ext.each(["keydown", "keypress"], function (eventName) {
            this.el.on(eventName, function (e) {
                if (e.isNavKeyPress()) {
                    e.stopPropagation();
                }
            }, this);
        }, this);

        if (Ext.isGecko) {
            container.setOverflow("auto");
            var containerSize = container.getSize();
            this.dateField.wrap.setStyle("position", "fixed");
            container.setSize(containerSize);
        }
    }
});

Coolite.Ext.EditMenuItem = function (config) {
    Coolite.Ext.EditMenuItem.superclass.constructor.call(this, new Ext.form.TextField(config.textbox), config);
    this.textbox = this.component;
    this.addEvents("select");
    this.textbox.on("render", function (textbox) {
        textbox.getEl().swallowEvent("click");
    });
};

Ext.extend(Coolite.Ext.EditMenuItem, Ext.menu.Adapter, {
    onRender: function (container) {
        Coolite.Ext.EditMenuItem.superclass.onRender.call(this, container);

        this.el.swallowEvent(["keydown", "keypress"]);
        Ext.each(["keydown", "keypress"], function (eventName) {
            this.el.on(eventName, function (e) {
                if (e.isNavKeyPress()) {
                    e.stopPropagation();
                }
            }, this);
        }, this);

        if (Ext.isGecko) {
            this.el.setOverflow("auto");
            var containerSize = container.getSize();
            this.textbox.getEl().setStyle("position", "fixed");
            container.setSize(containerSize);
        }
    }
});

Coolite.Ext.MenuPanel = function (config) {
    Coolite.Ext.MenuPanel.superclass.constructor.call(this, config);
    this.menu.on("itemclick", this.setSelection, this);
};

Ext.extend(Coolite.Ext.MenuPanel, Ext.Panel, {
    saveSelection: true,
    selectedIndex: -1,

    initComponent: function() {
        Coolite.Ext.MenuPanel.superclass.initComponent.call(this);

        if (this.selectedIndex > -1) {
            this.menu.items.get(this.selectedIndex).ctCls = "x-menu-item-active";
        }

        this.menu.on("mouseout", this.onMenuMouseOut, this);
    },

    onMenuMouseOut: function(menu, e, t) {
        if (!this.saveSelection) {
            return;
        }
        var index = this.menu.items.indexOf(t);
        var selIndex = this.getSelIndexField().getValue()
        if (selIndex.length > 0 && index == selIndex) {
            t.container.addClass("x-menu-item-active");
        }
    },

    setSelectedIndex: function(index) {
        this.setSelection(this.menu.items.get(index));
    },

    getSelIndexField: function() {
        if (!this.selIndexField) {
            this.selIndexField = new Ext.form.Hidden({ id: this.id + "_SelIndex", name: this.id + "_SelIndex" });
        }
        return this.selIndexField;
    },

    setSelection: function(item, e) {
        if (this.saveSelection) {
            this.menu.items.each(function(item) {
                item.container.removeClass("x-menu-item-active");
            }, this.menu);

            item.container.addClass("x-menu-item-active");
        }

        this.getSelIndexField().setValue(this.menu.items.indexOf(item));
    },

    afterRender: function() {
        Coolite.Ext.MenuPanel.superclass.afterRender.call(this);
        var layer = this.menu.getEl();
        if (Ext.isIE) {
            layer.shadow = false;
        }

        this.body.appendChild(layer);
        layer.clearPositioning("auto");
        layer.setWidth("auto");
        layer.setHeight("100%");
        layer.applyStyles({ border: "0px" });
        layer.show();
        this.getSelIndexField().render(this.el.parent() || this.el);
    }
});

Ext.reg("coolitemenupanel", Coolite.Ext.MenuPanel);

// HACK: monkey-patch Toolbar.Item .getEl() to return a typeof Element
Ext.Toolbar.Item.prototype.getEl = function () {
    return Ext.get(this.el);
};

Ext.Toolbar.TextItem.override({
    setText: function(text) {
        this.el.innerHTML = text;
    },
    getText: function() {
        return this.el.innerHTML;
    }
});

Ext.override(Ext.form.TextField, {
    truncate: true,
    afterRender: function () {
        Ext.form.TextField.superclass.afterRender.call(this);
        if (this.maxLength !== Number.MAX_VALUE && this.truncate) {
            this.el.dom.setAttribute("maxlength", this.maxLength);
        }
    }
});

Coolite.Ext.TreePanel = function (config) {
    Coolite.Ext.TreePanel.superclass.constructor.call(this, config);
};

Ext.extend(Coolite.Ext.TreePanel, Ext.tree.TreePanel, {
    initComponent: function () {
        Coolite.Ext.TreePanel.superclass.initComponent.call(this);
        this.initChildren(this.nodes);
    },

    initChildren: function (nodes) {
        if (!Ext.isEmpty(nodes) && nodes.length > 0) {
            var root = nodes[0];
            var rootNode = this.createNode(root);
            this.setRootNode(rootNode);

            if (root.children) {
                this.setChildren(root, rootNode);
            }
        }
    },

    setChildren: function (parent, node) {
        for (var i = 0; i < parent.children.length; i++) {
            var child = parent.children[i];
            var childNode = this.createNode(child);
            node.appendChild(childNode);
            if (child.children) {
                this.setChildren(child, childNode);
            }
        }
    },

    createNode: function (config) {
        var type = config.nodeType || "node";
        if (type == "node") {
            return new Ext.tree.TreeNode(config);
        }

        return new Ext.tree.AsyncTreeNode(config);
    }
});

Ext.reg("coolitetreepanel", Coolite.Ext.TreePanel);

Ext.override(Ext.tree.TreeNodeUI, {
    setIconClass: function (cls) {
        if (this.iconNode) {
            Ext.fly(this.iconNode).replaceClass(this.node.attributes.cls, cls);
        }
        this.node.attributes.cls = cls;
    }
});

Ext.override(Ext.util.Observable, {
    fireEvent: function() {
        if (!(this.isAjaxInit || false)) {
            this.isAjaxInit = true;
            this.ajaxListeners = {};
            if (this.ajaxEvents) {
                this.addAjaxListener(this.ajaxEvents);
            }
        }

        if (this.eventsSuspended !== true) {
            var ce = this.events[arguments[0].toLowerCase()];
            var answer = true;
            if (typeof ce == "object") {
                answer = ce.fire.apply(ce, Array.prototype.slice.call(arguments, 1));
            }

            if (answer !== false) {
                var ace = this.ajaxListeners[arguments[0].toLowerCase()];
                if (typeof ace == "object") {
                    return ace.fire.apply(ace, Array.prototype.slice.call(arguments, 1));
                }
            }

            return answer;
        }
        return true;
    },

    addAjaxListener: 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") {
                    // shared options
                    this.addAjaxListener(e, o[e], o.scope, o);
                } else {
                    // individual options
                    this.addAjaxListener(e, o[e].fn, o[e].scope, o[e]);
                }
            }
            return;
        }
        o = (!o || typeof o == "boolean") ? {} : o;
        eventName = eventName.toLowerCase();
        var ce = this.ajaxListeners[eventName] || true;
        if (typeof ce == "boolean") {
            ce = new Ext.util.Event(this, eventName);
            this.ajaxListeners[eventName] = ce;
        }
        ce.addListener(fn, scope, o);
    }
});

Coolite.AjaxEvent = new Ext.data.Connection({
    autoAbort: false,
    confirmTitle: "Confirmation",
    confirmMessage: "Are you sure?",

    confirmRequest: function(ajaxEventConfig) {
        ajaxEventConfig = ajaxEventConfig || {};
        if (ajaxEventConfig.confirmation && ajaxEventConfig.confirmation.confirmRequest) {
            Ext.Msg.confirm(
                ajaxEventConfig.confirmation.title || this.confirmTitle,
                ajaxEventConfig.confirmation.message || this.confirmMessage,
                this.confirmAnswer.createDelegate(this, [ajaxEventConfig], true),
                this);
        } else {
            Coolite.AjaxEvent.request(ajaxEventConfig);
        }
    },

    confirmAnswer: function(btn, text, buttonConfig, ajaxEventConfig) {
        if (btn == "yes") {
            Coolite.AjaxEvent.request(ajaxEventConfig);
        }
    },

    serializeForm: function(form) {
        return Ext.lib.Ajax.serializeForm(form);
    },
    setValue: function(form, name, value) {
        var input = null;
        if (form[name]) {
            input = form[name];
        } else {
            input = document.createElement("input");
            input.setAttribute("name", name);
            input.setAttribute("type", "hidden");
        }
        input.setAttribute("value", value);
        var parentElement = input.parentElement ? input.parentElement : input.parentNode;
        if (Ext.isEmpty(parentElement)) {
            form.appendChild(input);
            form[name] = input;
        }
    },
    delayedF: function(el, remove) {
        if (!Ext.isEmpty(el)) {
            el.unmask();
            if (remove === true) {
                el.remove();
            }
        }
    },
    showFailure: function(response, errorMsg) {
        var bodySize = Ext.getBody().getViewSize();
        var width = (bodySize.width < 500) ? bodySize.width - 50 : 500;
        var height = (bodySize.height < 300) ? bodySize.height - 50 : 300;

        if (Ext.isEmpty(errorMsg)) {
            errorMsg = response.responseText;
        }

        var win = new Ext.Window({ modal: true, width: width, height: height, title: "Request Failure", layout: "fit", maximizable: true,
            listeners: {
                "maximize": {
                    fn: function(el) {
                        var v = Ext.getBody().getViewSize();
                        el.setSize(v.width, v.height);
                    },
                    scope: this
                },

                "resize": {
                    fn: function(wnd) {
                        var editor = Ext.getCmp("__ErrorMessageEditor");
                        var sz = wnd.body.getViewSize();
                        editor.setSize(sz.width, sz.height - 42);
                    }
                }
            },
            items: new Ext.form.FormPanel({
                baseCls: "x-plain",
                layout: "absolute",
                defaultType: "label",
                items: [
                {
                    x: 5,
                    y: 5,
                    html: '<div class="x-window-dlg"><div class="ext-mb-error" style="width:32px;height:32px"></div></div>'
                }, {
                    x: 42,
                    y: 6,
                    html: "<b>Status code: </b>"
                }, {
                    x: 125,
                    y: 6,
                    text: response.status
                }, {
                    x: 42,
                    y: 25,
                    html: "<b>Status text: </b>"
                }, {
                    x: 125,
                    y: 25,
                    text: response.statusText
                }, {
                    x: 0,
                    y: 42,
                    id: "__ErrorMessageEditor",
                    xtype: "htmleditor",
                    enableAlignments: false,
                    enableColors: false,
                    enableFont: false,
                    enableFontSize: false,
                    enableFormat: false,
                    enableLinks: false,
                    enableLists: false,
                    enableSourceEdit: false,
                    readOnly: true,
                    value: errorMsg
}]
                })
            });
            win.show();
        },
        parseResponse: function(response) {
            var text = response.responseText,
            xmlTpl = "<?xml",
            result = {},
            exception = false;

            result.success = true;

            try {
                if (response.responseText.match(/^<\?xml/) == xmlTpl) {
                    //xml parsing      
                    var xmlData = response.responseXML;
                    var root = xmlData.documentElement || xmlData;
                    var q = Ext.DomQuery;

                    if (root.nodeName == "AjaxResponse") {
                        //root = q.select("AjaxResponse", root);
                        //success
                        var sv = q.selectValue("Success", root, true);
                        var pSuccess = sv !== false && sv !== "false",
                            pErrorMessage = q.selectValue("ErrorMessage", root, ""),
                            pScript = q.selectValue("Script", root, ""),
                            pViewState = q.selectValue("ViewState", root, ""),
                            pViewStateEncrypted = q.selectValue("ViewStateEncrypted", root, ""),
                            pEventValidation = q.selectValue("EventValidation", root, ""),
                            pServiceResponse = q.selectValue("ServiceResponse", root, ""),
                            pUserParamsResponse = q.selectValue("ExtraParamsResponse", root, ""),
                            pResult = q.selectValue("Result", root, "");

                        if (!Ext.isEmpty(pSuccess)) {
                            Ext.apply(result, { success: pSuccess });
                        }

                        if (!Ext.isEmpty(pErrorMessage)) {
                            Ext.apply(result, { errorMessage: pErrorMessage });
                        }

                        if (!Ext.isEmpty(pScript)) {
                            Ext.apply(result, { script: pScript });
                        }

                        if (!Ext.isEmpty(pViewState)) {
                            Ext.apply(result, { viewState: pViewState });
                        }

                        if (!Ext.isEmpty(pViewStateEncrypted)) {
                            Ext.apply(result, { viewStateEncrypted: pViewStateEncrypted });
                        }

                        if (!Ext.isEmpty(pEventValidation)) {
                            Ext.apply(result, { eventValidation: pEventValidation });
                        }

                        if (!Ext.isEmpty(pServiceResponse)) {
                            Ext.apply(result, { serviceResponse: eval("(" + pServiceResponse + ")") });
                        }

                        if (!Ext.isEmpty(pUserParamsResponse)) {
                            Ext.apply(result, { extraParamsResponse: eval("(" + pUserParamsResponse + ")") });
                        }

                        if (!Ext.isEmpty(pResult)) {
                            Ext.apply(result, { result: eval("(" + pResult + ")") });
                        }

                        return { result: result, exception: false };
                    }
                    else {
                        return { result: response.responseXML, exception: false }; // root.text || root.textContent;
                    }
                }

                //json parsing
                result = eval("(" + text + ")");

            } catch (e) {
                result.success = false;
                exception = true;
                if (response.responseText.length === 0) {
                    result.errorMessage = "NORESPONSE";
                } else {
                    result.errorMessage = "BADRESPONSE: " + e.message;
                    result.responseText = response.responseText;
                }

                response.statusText = result.errorMessage;
            }

            return { result: result, exception: exception };
        },

        listeners: {
            beforerequest: {
                fn: function(conn, options) {
                    o = options || {};
                    o.eventType = o.eventType || "event";

                    var isStatic = o.eventType == "static",
                        isInstance = o.eventType == "public",
                        isRequired = o.eventType == "event" || o.eventType == "custom" || o.eventType == "proxy" || o.eventType == "postback";

                    var submitConfig = {};
                    o.extraParams = o.extraParams || {};

                    switch (o.eventType) {
                        case "event":
                        case "custom":
                        case "proxy":
                        case "postback":
                        case "public":
                            if (isInstance) {
                                o.action = o.name;
                            }

                            o.control = o.control || {};
                            o.type = o.type || "submit";
                            o.viewStateMode = o.viewStateMode || "default";
                            o.action = o.action || "Click";
                            o.headers = { "X-Coolite": "delta=true" };

                            if (o.type == "submit") {
                                o.form = Ext.get(o.formProxyArg);

                                if (Ext.isEmpty(o.form) && !Ext.isEmpty(o.control.el)) {
                                    if (Ext.isEmpty(o.control.isComposite) || o.control.isComposite === false) {
                                        o.form = o.control.el.up("form");
                                    } else {
                                        o.form = Ext.get(o.control.elements[0]).up("form");
                                    }
                                }
                            } else if (o.type == "load" && Ext.isEmpty(o.method)) {
                                o.method = "GET";
                            }

                            if (Ext.isEmpty(o.form) && Ext.isEmpty(o.url)) {
                                var forms = Ext.select("form").elements;

                                if (forms.length > 0) {
                                    if (o.type == "submit") {
                                        o.form = (forms.length > 0) ? Ext.get(forms[0]) : undefined;
                                    }
                                    else {
                                        o.url = (forms.length > 0) ? forms[0].action : Coolite.Ext.Url || window.location.href;
                                    }
                                }
                            }

                            var argument = String.format("{0}|{1}|{2}", o.proxyId || o.control.proxyId || o.control.id || "-", o.eventType, o.action);

                            if (!Ext.isEmpty(o.form)) {
                                this.setValue(o.form.dom, "__EVENTTARGET", Coolite.Ext.ScriptManagerUniqueID);
                                this.setValue(o.form.dom, "__EVENTARGUMENT", argument);
                                Ext.getDom(o.form).ignoreAllSubmitFields = true;
                            } else {
                                o.url = o.url || Coolite.Ext.Url || window.location.href;
                                Ext.apply(submitConfig, { __EVENTTARGET: Coolite.Ext.ScriptManagerUniqueID, __EVENTARGUMENT: argument });
                            }

                            if (o.viewStateMode != "default") {
                                Ext.apply(submitConfig, { viewStateMode: o.viewStateMode });
                            }

                            if (o.before) {
                                if (o.before(o.control, o.eventType, o.action, o.extraParams) === false) {
                                    return false;
                                }
                            }

                            Ext.apply(submitConfig, { extraParams: o.extraParams || {} });

                            if (!Ext.isEmpty(o.serviceParams)) {
                                Ext.apply(submitConfig, { serviceParams: o.serviceParams });
                            }

                            o.params = { submitAjaxEventConfig: Ext.encode({ config: submitConfig }) };
                            if (!Ext.isEmpty(o.form)) {
                                var enctype = Ext.getDom(o.form).getAttribute("enctype");
                                if ((enctype && enctype.toLowerCase() == "multipart/form-data") || o.isUpload) {
                                    Ext.apply(o.params, { "__CooliteAjaxEventMarker": "delta=true" });
                                }
                            }

                            if (o.cleanRequest) {
                                o.params = Ext.apply({}, o.extraParams || {});
                            }

                            if (!Ext.isEmpty(o.form)) {
                                o.form.dom.action = o.form.dom.action || o.form.action || o.url || Coolite.Ext.Url || window.location.href;
                            }

                            break;
                        case "static":
                            o.headers = { "X-Coolite": "delta=true,staticmethod=true" };

                            if (Ext.isEmpty(o.form) && Ext.isEmpty(o.url)) {
                                var forms = Ext.select("form").elements;
                                o.url = (forms.length > 0) ? forms[0].action : Coolite.Ext.Url || window.location.href;
                            }

                            if (o.before) {
                                if (o.before(o.control, o.eventType, o.action, o.extraParams) === false) {
                                    return false;
                                }
                            }

                            o.params = Ext.apply(o.extraParams, { "_methodName_": o.name });
                            break;
                    }

                    o.scope = this;

                    //--Common part----------------------------------------------------------

                    var el, em = o.eventMask || {};
                    if ((em.showMask === true)) {
                        switch (em.target || "page") {
                            case "this":
                                if (o.control.getEl) {
                                    el = o.control.getEl();
                                } else if (o.control.dom) {
                                    el = o.control;
                                }
                                break;
                            case "parent":
                                if (o.control.getEl) {
                                    el = o.control.getEl().parent();
                                } else if (o.control.parent) {
                                    el = o.control.parent();
                                }
                                break;
                            case "page":
                                var theHeight = "100%";
                                if (window.innerHeight) {
                                    theHeight = window.innerHeight + "px";
                                }
                                else if (document.documentElement && document.documentElement.clientHeight) {
                                    theHeight = document.documentElement.clientHeight + "px";
                                }
                                else if (document.body) {
                                    theHeight = document.body.clientHeight + "px";
                                }

                                el = Ext.getBody().createChild({ style: "position:absolute;left:0;top:0;width:100%;height:" + theHeight + ";z-index:20000;background-color:Transparent;" });
                                var scroll = Ext.getBody().getScroll();
                                el.setLeftTop(scroll.left, scroll.top);
                                break;
                            case "customtarget":
                                var trg = em.customTarget || "";
                                el = Ext.get(trg);
                                if (Ext.isEmpty(el)) {
                                    el = trg.getEl ? trg.getEl() : null;
                                }
                                break;
                        }

                        if (el !== undefined && el !== null) {
                            el.mask(em.msg || "Working...", em.msgCls || "x-mask-loading");
                            o.el = el;
                        }
                    }

                    var removeMask = function(o) {
                        if (o.el !== undefined && o.el !== null) {
                            var delay = 0,
                                em = o.eventMask || {};
                            if (em && em.minDelay) {
                                delay = em.minDelay;
                            }

                            var remove = (em.target || "page") == "page",
                            task = new Ext.util.DelayedTask(
                                function(o, remove) {
                                    o.scope.delayedF(o.el, remove);
                                },
                                o.scope,
                                [o, remove]
                            ).delay(delay);
                        }
                    };

                    var executeScript = function(o, result, response) {
                        var delay = 0;
                        var em = o.eventMask || {};
                        if (em.minDelay) {
                            delay = em.minDelay;
                        }

                        var task = new Ext.util.DelayedTask(
                            function(o, result, response) {
                                if (result.script && result.script.length > 0) {
                                    eval(result.script);
                                }

                                if (o.userSuccess) {
                                    o.userSuccess(response, result, o.control, o.eventType, o.action, o.extraParams, o);
                                }
                            },
                            o.scope, [o, result, response]).delay(delay);
                    };


                    o.failure = function(response, options) {
                        var o = options;
                        removeMask(o);
                        if (o.userFailure && (Ext.isEmpty(o.enforceFailureWarning) || !o.enforceFailureWarning)) {
                            o.userFailure(response, { "errorMessage": response.statusText }, o.control, o.eventType, o.action, o.extraParams, o);
                        } else if (o.showWarningOnFailure !== false) {
                            o.scope.showFailure(response, "");
                        }
                    };

                    o.success = function(response, options) {
                        var o = options;
                        removeMask(o);

                        var parsedResponse = o.scope.parseResponse(response);

                        if (!Ext.isEmpty(parsedResponse.result.documentElement)) {
                            executeScript(o, parsedResponse.result, response);
                            return;
                        }
                        var result = parsedResponse.result,
                            exception = parsedResponse.exception;

                        if (result.success === false) {
                            if (o.userFailure && (Ext.isEmpty(o.enforceFailureWarning) || !o.enforceFailureWarning)) {
                                o.userFailure(response, result, o.control, o.eventType, o.action, o.extraParams, o);
                            } else {
                                if (o.showWarningOnFailure !== false) {
                                    var errorMsg = "";
                                    if (!exception && result.errorMessage && result.errorMessage.length > 0) {
                                        errorMsg = result.errorMessage;
                                    }
                                    o.scope.showFailure(response, errorMsg);
                                }
                            }

                            return;
                        }

                        if (!Ext.isEmpty(result.viewState) && o.form !== null) {
                            o.scope.setValue(o.form.dom, "__VIEWSTATE", result.viewState);

                            if (!Ext.isEmpty(result.viewStateEncrypted) && o.form !== null) {
                                o.scope.setValue(o.form.dom, "__VIEWSTATEENCRYPTED", result.viewStateEncrypted);
                            }

                            if (!Ext.isEmpty(result.eventValidation) && o.form !== null) {
                                o.scope.setValue(o.form.dom, "__EVENTVALIDATION", result.eventValidation);
                            }
                        }

                        executeScript(o, result, response);
                    };
                }
            }
        }
    });

    Coolite.AjaxMethod = {
        request: function (name, options) {
            options = options || {};

            if (typeof options !== "object") {
                throw { message: "The AjaxMethod options object is an invalid type: typeof " + typeof options };
            }
            
            if (!Ext.isEmpty(name) && typeof name === "object" && Ext.isEmptyObj(options)) {
                options = name;
            }

            var obj = {
                name: options.name || name,
                control: Ext.isEmpty(options.control) ? null : { id: options.control },
                eventType: options.specifier || "public",
                type: options.type || "submit",
                method: options.method || "POST",
                eventMask: options.eventMask,
                extraParams: options.params,
                ajaxMethodSuccess: options.success,
                ajaxMethodFailure: options.failure,
                userSuccess: function (response, result, control, eventType, action, extraParams, o) {
                    if (!Ext.isEmpty(o.ajaxMethodSuccess)) {
                        o.ajaxMethodSuccess(Ext.isEmpty(result.result) ? result : result.result, response, extraParams);
                    }
                },
                userFailure: function (response, result, control, eventType, action, extraParams, o) {
                    if (!Ext.isEmpty(o.ajaxMethodFailure)) {
                        o.ajaxMethodFailure(result.errorMessage, response, extraParams);
                    }
                }
            };

            Coolite.AjaxEvent.request(Ext.apply(options, obj));
        }
    };

    Ext.Panel.override({
        getCollapsedField: function() {
            if (!this.collapsedField) {
                this.collapsedField = new Ext.form.Hidden({ id: this.id + "_Collapsed", name: this.id + "_Collapsed", value: this.collapsed || false });
                this.collapsedField.render(this.el.parent() || this.el);
            }
            return this.collapsedField.el;
        },

        getBody: function() {
            return Ext.get(this.id + "_Body") || this.body;
        },

        setAutoScroll: function() {
            if (this.rendered && this.autoScroll) {
                var el = this.body || this.el;
                if (el) {
                    el.setOverflow("auto");
                    // Following line required to fix autoScroll
                    el.dom.style.position = "relative";
                }
            }
            return this;
        },

        // private
        isIFrame: function(cfg) {
            var frame = false;
            if (typeof cfg == "string" && cfg.indexOf("://") >= 0) {
                frame = true;
            } else if (cfg.mode) {
                if (cfg.mode == "iframe") {
                    frame = true;
                }
            } else if (cfg.url && cfg.url.indexOf("://") >= 0) {
                frame = true;
            } else if ((this.getAutoLoad().url && this.autoLoad.url.indexOf("://") >= 0) || (this.getAutoLoad().mode && this.autoLoad.mode == "iframe")) {
                frame = true;
            }

            return frame;
        },

        load: function(config) {
            if (!Ext.isEmpty(config) && !Ext.isEmptyObj(config)) {
                if (config.passParentSize) {
                    config.params = config.params || {};
                    config.params.width = this.body.getWidth(true);
                    config.params.height = this.body.getHeight(true);
                }
                if (this.isIFrame(config)) {
                    return this.loadIFrame(config);
                }

                var um = this.body.getUpdater();
                um.update.apply(um, arguments);
            }
            return this;
        },

        //do not remove and uncomment body
        doAutoLoad: function() {
            //this.load(this.getAutoLoad());
        },

        reload: function(nocache) {
            this.getAutoLoad().nocache = nocache || this.autoLoad.nocache;
            this.load(this.getAutoLoad());
        },

        getAutoLoad: function() {
            this.autoLoad = this.autoLoad || {};
            return this.autoLoad;
        },

        clearLoadedContent: function() {
            if (this.iframe) {
                this.iframe.remove();
                delete this.iframe;
            }
            else {
                this.body.innerHTML = "";
            }
        },

        // private
        loadIFrame: function(config) {
            var al = this.getAutoLoad(), url;

            if (typeof config == "string") {
                al.url = config;
            } else if (typeof config == "object") {
                Ext.apply(al, config);
            }

            url = al.url;

            if (al.nocache === true) {
                url = url + ((url.indexOf("?") > -1) ? "&" : "?") + new Date().getTime();
            }

            if (al.params) {
                var params = Ext.urlEncode(al.params);
                url = url + ((url.indexOf("?") > -1) ? "&" : "?") + params;
            }

            if (Ext.isEmpty(this.iframe)) {
                var iframeObj = {
                    tag: "iframe",
                    width: "100%",
                    height: "100%",
                    frameborder: 0,
                    id: this.id + "_IFrame",
                    name: this.id + "_IFrame",
                    src: url
                };
                this.iframe = Ext.get(Ext.DomHelper.insertFirst(this.body, iframeObj));
                this.iframe.on("load", this.afterLoad, this);
                this.fireEvent("beforeupdate", this, { url: url, iframe: this.iframe });
            } else {
                this.iframe.dom.src = "javascript:false";
                this.fireEvent("beforeupdate", this, { url: this.iframe.dom.src, iframe: this.iframe });
                this.iframe.dom.src = url;
            }

            if (al.showMask) {
                this.body.mask(al.maskMsg || "Loading...", al.maskCls || "x-mask-loading");
            }
            this.autoLoad = al;
            return this;
        },

        afterLoad: function() {
            if (this.autoLoad.showMask) {
                this.body.unmask();
            }
            this.fireEvent("update", this, { iframe: this.iframe, url: this.iframe.dom.src });
        },

        autoLoadBeforeUpdate: function(el, url, params) {
            this.fireEvent("beforeupdate", this, { url: url, params: params });
            if (this.autoLoad.showMask) {
                this.body.mask(this.autoLoad.maskMsg || "Loading...", this.autoLoad.maskCls || "x-mask-loading");
            }
        },

        autoLoadUpdate: function(el, response) {
            if (this.autoLoad.showMask) {
                this.body.unmask();
            }
            this.fireEvent("update", this, { response: response });
        },

        autoLoadFailure: function(el, response) {
            if (this.autoLoad.showMask) {
                this.body.unmask();
            }
            this.fireEvent("failure", this, { response: response });
        },

        show: function() {
            Ext.Panel.superclass.show.call(this);
            if (Ext.isIE && this.hideMode == "offsets" && this.el) {
                this.el.repaint();
            }
        }
    });

    Ext.Panel.prototype.beforeDestroy = Ext.Panel.prototype.beforeDestroy.createInterceptor(function () {
        if (this.iframe) {
            if (Ext.isIE) {
                this.iframe.dom.src = "javascript:false";
                Ext.removeNode(this.iframe.dom);
            }
            this.iframe.remove();
        }
    });

    Ext.Panel.prototype.initComponent = Ext.Panel.prototype.initComponent.createSequence(function() {
        this.addEvents("beforeupdate", "update", "failure");

        if (this.autoLoad) {
            this.on("render", function() {
                var udr = this.getUpdater();
                udr.showLoadIndicator = false;

                udr.on("beforeupdate", this.autoLoadBeforeUpdate, this);
                udr.on("update", this.autoLoadUpdate, this);
                udr.on("failure", this.autoLoadFailure, this);
            }, this);

            var loadConfig = { delay: 10, single: true };
            var triggerEvent = this.autoLoad.triggerEvent || "render";
            loadConfig.single = !(this.autoLoad.reloadOnEvent || false);

            if (Ext.isEmpty(this.autoLoad.manuallyTriggered) || this.autoLoad.manuallyTriggered !== true) {
                this.on(triggerEvent, function() {
                    this.load(this.getAutoLoad());
                }, this, loadConfig);
            }
        }
    });

    Ext.Panel.prototype.onCollapse = Ext.Panel.prototype.onCollapse.createSequence(function (doAnim, animArg) {
        var f = this.getCollapsedField();
        if (!Ext.isEmpty(f)) {
            f.dom.value = "true";
        }        
    });

    Ext.Panel.prototype.onExpand = Ext.Panel.prototype.onExpand.createSequence(function (doAnim, animArg) {
        var f = this.getCollapsedField();
        if (!Ext.isEmpty(f)) {
            f.dom.value = "false";
        }
    });

    Ext.form.FieldSet.prototype.onCollapse = Ext.form.FieldSet.prototype.onCollapse.createSequence(function (doAnim, animArg) {
        var f = this.getCollapsedField();
        if (!Ext.isEmpty(f)) {
            f.dom.value = "true";
        }
    });

    Ext.form.FieldSet.prototype.onExpand = Ext.form.FieldSet.prototype.onExpand.createSequence(function (doAnim, animArg) {
        var f = this.getCollapsedField();
        if (!Ext.isEmpty(f)) {
            f.dom.value = "false";
        }
    });

    Coolite.Ext.TaskResponse = { stopTask: -1, stopAjax: -2 };

    Coolite.Ext.TaskManager = function (config) {
        Coolite.Ext.TaskManager.superclass.constructor.call(this);
        Ext.apply(this, config);
        return new Ext.util.DelayedTask(this.initManager, this).delay(this.autoRunDelay || 50);
    };

    Ext.extend(Coolite.Ext.TaskManager, Ext.util.Observable, {
        tasksConfig: [],
        tasks: [],

        getTasks: function () { return this.tasks; },

        initManager: function () {
            this.runner = new Ext.util.TaskRunner(this.interval || 10);
            var task;
            for (var i = 0; i < this.tasksConfig.length; i++) {
                task = this.createTask(this.tasksConfig[i]);
                this.tasks.push(task);
                if (task.executing && task.autoRun) {
                    this.startTask(task);
                }
            }
        },

        getTask: function (id) {
            if (typeof id == "object") {
                return id;
            } else if (typeof id == "string") {
                for (var i = 0; this.tasks.length; i++) {
                    if (this.tasks[i].id == id) {
                        return this.tasks[i];
                    }
                }
            } else if (typeof id == "number") {
                return this.tasks[id];
            }
            return null;
        },

        startTask: function (task) {
            if (this.executing) {
                return;
            }

            task = this.getTask(task);

            if (task.onstart) {
                task.onstart.apply(task.scope || task);
            }

            this.runner.start(task);
        },

        stopTask: function (task) { this.runner.stop(this.getTask(task)); },

        startAll: function () {
            for (var i = 0; i < this.tasks.length; i++) {
                this.startTask(this.tasks[i]);
            }
        },

        stopAll: function () { this.runner.stopAll(); },

        //private
        createTask: function (config) {
            return Ext.apply({}, config, {
                owner: this,
                executing: true,
                interval: 1000,
                autoRun: true,
                onStop: function (t) {
                    this.executing = false;
                    if (this.onstop) {
                        this.onstop();
                    }
                },
                run: function () {
                    if (this.clientRun) {
                        var rt = this.clientRun.apply(arguments);

                        if (rt === Coolite.Ext.TaskResponse.stopAjax) {
                            return;
                        } else if (rt === Coolite.Ext.TaskResponse.stopTask) {
                            return false;
                        }
                    }
                    if (this.serverRun) {
                        var params = arguments;
                        this.serverRun.control = this.owner;
                        Coolite.AjaxEvent.request(this.serverRun);
                    }
                }
            });
        }
    });

    Ext.tree.TreeLoader.override({
        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,
                    timeout: this.timeout || 30000,
                    argument: { callback: callback, node: node },
                    params: this.getParams(node)
                });
            } else {
                if (typeof callback == "function") {
                    callback();
                }
            }
        },
        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);
            }

            var node;
            if (attr.nodeType) {
                node = new Ext.tree.TreePanel.nodeTypes[attr.nodeType](attr);
            } else {
                node = attr.leaf ?
                            new Ext.tree.TreeNode(attr) :
                            new Ext.tree.AsyncTreeNode(attr);
            }

            if (this.preloadChildren) {
                this.doPreload(node);
            }

            return node;
        }
    });

    Coolite.Ext.WebServiceTreeLoader = Ext.extend(Ext.tree.TreeLoader, {
        // private override
        processResponse: function (response, node, callback) {
            var xmlData = response.responseXML;
            var root = xmlData.documentElement || xmlData;
            var json = Ext.DomQuery.selectValue("json", root, "");

            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);
            }
        }
    });

    Coolite.Ext.PageTreeLoader = Ext.extend(Ext.tree.TreeLoader, {
        load: function (node, callback) {
            if (this.clearOnLoad) {
                while (node.firstChild) {
                    node.removeChild(node.firstChild);
                }
            }
            if (this.doPreload(node)) {
                if (typeof callback == "function") {
                    callback();
                }
            } else {
                this.requestData(node, callback);
            }
        },

        requestData: function (node, callback) {
            if (this.fireEvent("beforeload", this, node, callback) !== false) {
                var config = {};

                Ext.apply(config, {
                    control: node.getOwnerTree(),
                    eventType: "postback",
                    action: "nodeload",
                    userSuccess: this.handleSuccess,
                    userFailure: this.handleFailure,
                    argument: { callback: callback, node: node },
                    extraParams: this.getParams(node),
                    method: this.method,
                    timeout: this.timeout || 30000,
                    isUpload: this.isUpload,
                    viewStateMode: this.viewStateMode,
                    type: this.type,
                    url: this.url,
                    formProxyArg: this.formProxyArg,
                    eventMask: this.eventMask
                });
                Coolite.AjaxEvent.request(config);

            } else {
                if (typeof callback == "function") {
                    callback();
                }
            }
        },

        handleFailure: function (response, result, context, type, action, extraParams) {
            var loader = context.getLoader();
            loader.transId = false;
            var a = response.argument;
            loader.fireEvent("loadexception", loader, a.node, response, result.errorMessage || response.statusText);
            if (typeof a.callback == "function") {
                a.callback(loader, a.node);
            }
        },

        handleSuccess: function (response, result, context, type, action, extraParams) {
            var loader = context.getLoader();
            var serviceResponse = result.serviceResponse || {};

            loader.transId = false;
            var a = response.argument;
            loader.processResponse(response, serviceResponse.Data || [], a.node, a.callback);
            loader.fireEvent("load", loader, a.node, response);
        },

        getParams: function (node) {
            var buf = {}, bp = this.baseParams;
            for (var key in bp) {
                if (typeof bp[key] != "function") {
                    buf[key] = bp[key];
                }
            }
            buf.node = node.id;
            return buf;
        },

        processResponse: function (response, data, node, callback) {
            try {
                var o = data;
                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);
            }
        }
    });

    Ext.tree.AsyncTreeNode.override({
        loadNodes: function (nodes) {
            this.beginUpdate();

            for (var i = 0, len = nodes.length; i < len; i++) {
                var n = this.getOwnerTree().getLoader().createNode(nodes[i]);

                if (!Ext.isEmpty(n)) {
                    this.appendChild(n);
                }
            }
            
            this.endUpdate();
            this.loadComplete();
        }
    });

    Coolite.Ext.lazyInit = function(controls) {
        if (!Ext.isArray(controls)) { return; }
        var cmp;
        for (var i = 0; i < controls.length; i++) {
            cmp = Ext.getCmp(controls[i]);
            if(!Ext.isEmpty(cmp)){
                window[controls[i]] = cmp;
            }
        }
    };

    Coolite.Ext.setValues = function (controls) {
        if (!Ext.isArray(controls)) { return; }
        for (var i = 0; i < controls.length; i++) {
            controls[i][0].setValue(controls[i][1]);
            controls[i][0].clearInvalid();
        }
    };

    Coolite.Ext.doPostBack = function (config) {
        if (config.before) {
            if (config.before(config.control, config.extraParams || {}) === false) {
                return;
            }
        }

        if (config.extraParams) {
            var form = document.forms[0];
            if (!Ext.isEmpty(form)) {
                form = Ext.get(form);
                var id = "__CoolitePostBackParams";
                var el = form.insertFirst({ tag: "input", id: id, name: id, type: "hidden" });
                el.dom.value = Ext.encode(config.extraParams);
            }
        }

        config.fn();
    };

    Ext.form.TriggerField.override({
        syncSize: function () {
            delete this.lastSize;

            this.setSize(this.autoWidth ? undefined : this.el.getWidth(), this.autoHeight ? undefined : this.el.getHeight());
            this.wrap.setWidth(this.el.getWidth() + this.trigger.getWidth());
            this.el.setWidth(this.el.getWidth() + this.trigger.getWidth());

            if (this.list && this.listWidth === undefined) {
                this.syncList();
            }
            else if (this.initList) {
                this.initList();
                this.syncList();
            }

            return this;
        },

        syncList: function () {
            var lw = Math.max(this.el.getWidth() + this.trigger.getWidth(), this.minListWidth);
            this.list.setWidth(lw);
            this.innerList.setWidth(lw - this.list.getFrameWidth("lr"));
        }
    });

    Coolite.Ext.TriggerField = Ext.extend(Ext.form.TriggerField, {
        initComponent: function () {
            Coolite.Ext.TriggerField.superclass.initComponent.call(this);

            this.addEvents("triggerclick");

            if (this.triggersConfig) {

                var cn = [];
                for (var i = 0; i < this.triggersConfig.length; i++) {
                    var trigger = this.triggersConfig[i];
                    var triggerCfg = {
                        tag: "img",
                        "ext:qtip": trigger.qtip || "",
                        src: Ext.BLANK_IMAGE_URL,
                        cls: "x-form-trigger" + (trigger.triggerCls || "") + " " + (trigger.iconCls || "x-form-ellipsis-trigger")
                    };

                    if (trigger.hideTrigger) {
                        Ext.apply(triggerCfg, { style: "display:none" });
                    }
                    cn.push(triggerCfg);
                }

                this.triggerConfig = { tag: "span", cls: "x-form-twin-triggers", cn: cn };
            }
        },

        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());
                };

                t.on("click", this.onTriggerClick, this, { index: index, t: t, preventDefault: true });
                t.addClassOnOver("x-form-trigger-over");
                t.addClassOnClick("x-form-trigger-click");
            }, this);
            this.triggers = ts.elements;
        },

        onTriggerClick: function (evt, el, o) {
            this.fireEvent("triggerclick", this, o.t, o.index);
        }
    });

    Ext.reg("coolitetrigger", Coolite.Ext.TriggerField);

    Ext.form.DateField.override({
        onTriggerClick: function () {
            if (this.disabled) {
                return;
            }
            if (Ext.isEmpty(this.menu)) {
                this.menu = new Ext.menu.DateMenu();
            }

            if (this.menu.isVisible()) {
                this.menu.hide();
                return;
            }

            Ext.apply(this.menu.picker, {
                minDate: this.minValue,
                maxDate: this.maxValue,
                disabledDatesRE: this.disabledDatesRE,
                disabledDatesText: this.disabledDatesText,
                disabledDays: this.disabledDays,
                disabledDaysText: this.disabledDaysText,
                format: this.format,
                showToday: this.showToday,
                minText: String.format(this.minText, this.formatDate(this.minValue)),
                maxText: String.format(this.maxText, this.formatDate(this.maxValue))
            });

            if (this.cancelText) {
                Ext.apply(this.menu.picker, { cancelText: this.cancelText });
            }
            if (this.dayNames) {
                Ext.apply(this.menu.picker, { dayNames: this.dayNames });
            }
            if (this.monthNames) {
                Ext.apply(this.menu.picker, { monthNames: this.monthNames });
            }
            if (this.monthYearText) {
                Ext.apply(this.menu.picker, { monthYearText: this.monthYearText });
            }
            if (this.nextText) {
                Ext.apply(this.menu.picker, { nextText: this.nextText });
            }
            if (this.okText) {
                Ext.apply(this.menu.picker, { okText: this.okText });
            }
            if (this.prevText) {
                Ext.apply(this.menu.picker, { prevText: this.prevText });
            }
            if (this.startDay) {
                Ext.apply(this.menu.picker, { startDay: this.startDay });
            }
            if (this.todayText) {
                Ext.apply(this.menu.picker, { todayText: this.todayText });
            }
            if (this.todayTip) {
                Ext.apply(this.menu.picker, { todayTip: this.todayTip });
            }

            this.menu.on(Ext.apply({}, this.menuListeners, {
                scope: this
            }));
            this.menu.picker.setValue(this.getValue() || new Date());
            this.menu.show(this.el, "tl-bl?");
        }
    });

    Ext.layout.FormLayout.override({
        // private
        renderItem: function(c, position, target) {
            if (c && !c.rendered && c.isFormField && c.inputType != "hidden") {
                var args = [
                       c.id, c.fieldLabel,
                       (this.labelStyle || "") + ";" + (c.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",
                       c.labelCls || ""
                ];
                if (typeof position == "number") {
                    position = target.dom.childNodes[position] || null;
                }
                if (position) {
                    c.formItem = this.fieldTpl.insertBefore(position, args);
                } else {
                    c.formItem = this.fieldTpl.append(target, args);
                }
                c.label = Ext.get(c.formItem).child("label.x-form-item-label");
                c.render("x-form-el-" + c.id);
            } else {
                Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments);
            }
        },

        setContainer: function(ct) {
            Ext.layout.FormLayout.superclass.setContainer.call(this, ct);

            if (ct.labelAlign) {
                ct.addClass("x-form-label-" + ct.labelAlign);
            }

            this.elementStyle = this.elementStyle || "";
            this.labelStyle = this.labelStyle || "";

            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) {
                // the default field template used by all form layouts
                var t = new Ext.Template(
                    '<div class="x-form-item {5}" tabIndex="-1">',
                        '<label for="{0}" style="{2}" class="x-form-item-label {7}">{1}{4}</label>',
                        '<div class="x-form-element" id="x-form-el-{0}" style="{3}">',
                        '</div><div class="{6}"></div>',
                    '</div>');
                t.disableFormats = true;
                t.compile();
                Ext.layout.FormLayout.prototype.fieldTpl = t;
            }
        }
    });

    Ext.ns("Ext.ux.layout");

    Ext.form.Field.override({
        setReadOnly: function (readOnly) {
            if (this.rendered) {
                this.el.dom.setAttribute("readOnly", readOnly);
                this.el.dom.readOnly = readOnly;
            }
            else {
                this.readOnly = readOnly;
            }
        },
        getReadOnly: function () {
            return this.rendered ? this.el.dom.readOnly : this.readOnly;
        }
    });

    Ext.TabPanel.prototype.initComponent = Ext.TabPanel.prototype.initComponent.createSequence(function() {
        this.addEvents("beforetabclose", "beforetabhide", "tabclose");
        this.on("render", function() {
            this.getActiveTabField().render(this.el.parent() || this.el);
        }, this);
    });

    Ext.TabPanel.override({
        getActiveTabField: function() {
            if (!this.activeTabField) {
                this.activeTabField = new Ext.form.Hidden({ id: this.id + "_ActiveTab", name: this.id + "_ActiveTab", value: this.activeTab || 0 });
            }

            return this.activeTabField;
        },

        onStripMouseDown: function(e) {
            if (e.button !== 0) {
                return;
            }
            e.preventDefault();
            var t = this.findTargets(e);
            if (t.close) {
                this.closeTab(t.item);
                return;
            }
            if (t.item && t.item != this.activeTab) {
                this.setActiveTab(t.item);
            }
        },

        closeTab: function(tab, closeAction) {
            if (typeof tab == "string") {
                tab = this.getItem(tab);
            }
            else if (typeof tab == "number") {
                tab = this.items.get(tab);
            }

            if (Ext.isEmpty(tab)) {
                return;
            }

            var eventName = tab.closeAction || closeAction || "close";
            var destroy = eventName == "close";

            if (this.fireEvent("beforetab" + eventName, tab) === false) {
                return;
            }

            if (tab.fireEvent("before" + eventName, tab) === false) {
                return;
            }

            if (destroy) {
                tab.fireEvent("close", tab);
            }
            this.remove(tab, destroy);
            this.hideTabStripItem(tab);
            tab.addClass("x-hide-display");
            this.fireEvent("tabclose", tab);
            if (!destroy) {
                tab.fireEvent("close", tab);
            }
        },

        addTab: function(tab, index, activate) {
            config = {};

            if (!Ext.isEmpty(index)) {
                if (typeof index == "object") {
                    config = index;
                }
                else if (typeof index == "number") {
                    config.index = index;
                }
                else {
                    config.activate = index;
                }
            }

            if (!Ext.isEmpty(activate)) {
                config.activate = activate;
            }

            if (this.items.getCount() === 0) {
                this.activeTab = null;
            }

            if (!Ext.isEmpty(config.index) && config.index >= 0) {
                tab = this.insert(config.index, tab);
            }
            else {
                tab = this.add(tab);
            }

            if (config.activate !== false) {
                this.setActiveTab(tab);
            }
        }
    });

    Ext.form.HtmlEditor.override({
        escapeValue: true,
        syncValue: function () {
            if (this.initialized) {
                var bd = this.getEditorBody();
                var html = bd.innerHTML;
                if (Ext.isSafari) {
                    var bs = bd.getAttribute("style"); // Safari puts text-align styles on the body element!
                    var m = bs.match(/text-align:(.*?);/i);
                    if (m && m[1]) {
                        html = '<div style="' + m[0] + '">' + html + "</div>";
                    }
                }
                html = this.cleanHtml(html);
                if (this.fireEvent("beforesync", this, html) !== false) {
                    this.el.dom.value = this.escapeValue ? escape(html) : html;
                    this.fireEvent("sync", this, html);
                }
            }
        },

        setValue: function (v) {
            Ext.form.HtmlEditor.superclass.setValue.call(this, this.escapeValue ? escape(v) : v);
            this.pushValue();
        },

        getValue: function () {
            if (!this.rendered) {
                return this.value;
            }
            var v = this.el.getValue();
            if (v === this.emptyText || v === undefined) {
                v = "";
            }
            return this.escapeValue ? unescape(v) : v;
        },

        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();
                if (this.escapeValue) {
                    this.el.dom.value = unescape(this.el.dom.value);
                }
                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();
                if (this.escapeValue) {
                    this.el.dom.value = escape(this.el.dom.value);
                }
                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);
        },

        pushValue: function () {
            if (this.initialized) {
                var v = this.escapeValue ? unescape(this.el.dom.value) : this.el.dom.value;
                if (!this.activated && v.length < 1) {
                    v = "&nbsp;";
                }
                if (this.fireEvent("beforepush", this, v) !== false) {
                    this.getEditorBody().innerHTML = v;
                    this.fireEvent("push", this, v);
                }
            }
        }
    });

    Coolite.Ext.ImageButton = Ext.extend(Ext.Button, {
        buttonSelector: "img",
        cls: "",
        iconAlign: "left",

        initComponent: function() {
            Coolite.Ext.ImageButton.superclass.initComponent.call(this);
            preload_image_object = new Image();
            if (this.imageUrl) {
                preload_image_object.src = this.imageUrl;
            }

            if (this.overImageUrl) {
                preload_image_object.src = this.overImageUrl;
            }

            if (this.disabledImageUrl) {
                preload_image_object.src = this.disabledImageUrl;
            }

            if (this.pressedImageUrl) {
                preload_image_object.src = this.pressedImageUrl;
            }
        },

        onRender: function(ct, position) {
            if (!this.el) {
                //var el = document.createElement("span");
                //el.id = this.getId();

                var img = document.createElement("img");
                img.id = this.getId();
                img.src = this.imageUrl;
                img.style.border = "none";
                img.style.cursor = "pointer";

                //el.appendChild(img);
                this.imgEl = Ext.get(img);
                //this.el = el;
                this.el = img;

                if (!Ext.isEmpty(this.imgEl.getAttributeNS("", "width"), false) ||
                    !Ext.isEmpty(this.imgEl.getAttributeNS("", "height"), false)) {
                    img.removeAttribute("width");
                    img.removeAttribute("height");
                }

                if (this.altText) {
                    img.setAttribute("alt", this.altText);
                }

                if (this.align && this.align !== "notset") {
                    img.setAttribute("align", this.align);
                }

                if (this.pressed && this.pressedImageUrl) {
                    img.src = this.pressedImageUrl;
                }

                if (this.disabled && this.disabledImageUrl) {
                    img.src = this.disabledImageUrl;
                }

                if (this.tabIndex !== undefined) {
                    img.tabIndex = this.tabIndex;
                }

                if (this.menu) {
                    this.menu.on("show", this.onMenuShow, this);
                    this.menu.on("hide", this.onMenuHide, this);
                }

                if (this.repeat) {
                    var repeater = new Ext.util.ClickRepeater(this.imgEl,
                        typeof this.repeat == "object" ? this.repeat : {}
                    );
                    repeater.on("click", this.onClick, this);
                }

                this.imgEl.on(this.clickEvent, this.onClick, this);

                if (this.handleMouseEvents) {
                    this.imgEl.on("mouseover", this.onMouseOver, this);
                    this.imgEl.on("mousedown", this.onMouseDown, this);
                }

                if (!Ext.isEmpty(this.cls, false)) {
                    this.el.className = this.cls;
                }

                Ext.BoxComponent.superclass.onRender.call(this, ct, position);
            }

            if (this.tooltip) {
                if (typeof this.tooltip == "object") {
                    Ext.QuickTips.register(Ext.apply({
                        target: this.imgEl.id
                    }, this.tooltip));
                } else {
                    this.imgEl.dom[this.tooltipType] = this.tooltip;
                }
            }


            Ext.ButtonToggleMgr.register(this);
        },

        afterRender: function() {
            Ext.Button.superclass.afterRender.call(this);
        },

        // private
        onMenuShow: function(e) {
            this.ignoreNextClick = 0;
            this.fireEvent("menushow", this, this.menu);
        },
        // private
        onMenuHide: function(e) {
            this.ignoreNextClick = this.restoreClick.defer(250, this);
            this.fireEvent("menuhide", this, this.menu);
        },

        toggle: function(state) {
            state = state === undefined ? !this.pressed : state;
            if (state != this.pressed) {
                if (state) {
                    if (this.pressedImageUrl) {
                        this.imgEl.dom.src = this.pressedImageUrl;
                    }
                    this.pressed = true;
                    this.fireEvent("toggle", this, true);
                } else {
                    if (this.monitoringMouseOver) {
                        this.imgEl.dom.src = this.overImageUrl;
                    }
                    else {
                        this.imgEl.dom.src = this.imageUrl;
                    }
                    this.pressed = false;
                    this.fireEvent("toggle", this, false);
                }
                if (this.toggleHandler) {
                    this.toggleHandler.call(this.scope || this, this, state);
                }
            }
        },

        setText: function(t, encode) {
        },

        setDisabled: function(disabled) {
            this.disabled = disabled;
            if (disabled) {
                if (this.disabledImageUrl) {
                    this.imgEl.dom.src = this.disabledImageUrl;
                }
            }
            else {
                this.imgEl.dom.src = this.imageUrl;
            }
        },

        // private
        onMouseOver: function(e) {
            if (!this.disabled) {
                var internal = e.within(this.el, true);
                if (!internal) {

                    if (this.overImageUrl && !this.pressed) {
                        this.imgEl.dom.src = this.overImageUrl;
                    }

                    if (!this.monitoringMouseOver) {
                        Ext.getDoc().on("mouseover", this.monitorMouseOver, this);
                        this.monitoringMouseOver = true;
                    }
                }
            }
            this.fireEvent("mouseover", this, e);
        },

        // private
        onMouseOut: function(e) {
            if (!this.disabled && !this.pressed) {
                var internal = e.within(this.el) && e.target != this.el.dom;
                this.imgEl.dom.src = this.imageUrl;
            }
            this.fireEvent("mouseout", this, e);
        },

        onMouseDown: function(e) {
            if (!this.disabled && e.button == 0) {
                if (this.pressedImageUrl) {
                    this.imgEl.dom.src = this.pressedImageUrl;
                }
                Ext.getDoc().on("mouseup", this.onMouseUp, this);
            }
        },
        // private
        onMouseUp: function(e) {
            if (e.button == 0) {
                if (this.overImageUrl && this.monitoringMouseOver) {
                    this.imgEl.dom.src = this.overImageUrl;
                }
                else {
                    this.imgEl.dom.src = this.imageUrl;
                }

                Ext.getDoc().un("mouseup", this.onMouseUp, this);
            }
        }
    });
    Ext.reg("imagebutton", Coolite.Ext.ImageButton);


    Coolite.Ext.LinkButton = Ext.extend(Ext.Button, {
        buttonSelector: "a:first",
        cls: "",
        iconAlign: "left",

        valueElement: function () {
            var textEl = document.createElement("a");
            textEl.style.verticalAlign = "middle";
            textEl.id = Ext.id();
            if (!Ext.isEmpty(this.cls, false)) {
                textEl.className = this.cls;
            }

            textEl.setAttribute("href", "#");


            if (this.disabled || this.pressed) {
                textEl.setAttribute("disabled", "1");
                textEl.removeAttribute("href");

                if (this.pressed && this.allowDepress !== false) {
                    textEl.style.cursor = "pointer";
                }
            }

            if (this.tabIndex !== undefined) {
                textEl.tabIndex = this.tabIndex;
            }
            if (this.tooltip) {
                if (typeof this.tooltip == "object") {
                    Ext.QuickTips.register(Ext.apply({
                        target: textEl.id
                    }, this.tooltip));
                } else {
                    textEl[this.tooltipType] = this.tooltip;
                }
            }

            textEl.innerHTML = this.text;
            var txt = Ext.get(textEl);

            if (this.menu) {
                this.menu.on("show", this.onMenuShow, this);
                this.menu.on("hide", this.onMenuHide, this);
            }

            if (this.repeat) {
                var repeater = new Ext.util.ClickRepeater(txt,
                    typeof this.repeat == "object" ? this.repeat : {}
                );
                repeater.on("click", this.onClick, this);
            }

            txt.on(this.clickEvent, this.onClick, this);

            this.textEl = textEl;
            return this.textEl;
        },

        // private
        onMenuShow: function (e) {
            this.ignoreNextClick = 0;
            this.fireEvent("menushow", this, this.menu);
        },
        // private
        onMenuHide: function (e) {
            this.ignoreNextClick = this.restoreClick.defer(250, this);
            this.fireEvent("menuhide", this, this.menu);
        },

        toggle: function (state) {
            state = state === undefined ? !this.pressed : state;
            if (state != this.pressed) {
                if (state) {
                    this.setDisabled(true);
                    this.disabled = false;
                    this.pressed = true;
                    if (this.allowDepress !== false) {
                        this.textEl.style.cursor = "pointer";
                        this.el.dom.style.cursor = "pointer";
                    }
                    this.fireEvent("toggle", this, true);
                } else {
                    this.setDisabled(false);
                    this.pressed = false;
                    this.fireEvent("toggle", this, false);
                }
                if (this.toggleHandler) {
                    this.toggleHandler.call(this.scope || this, this, state);
                }
            }
        },

        onRender: function (ct, position) {
            if (!this.el) {
                var el = document.createElement("span");
                el.id = this.getId();

                var img = document.createElement("img");
                img.src = Ext.BLANK_IMAGE_URL;
                img.className = "x-label-icon " + (this.iconCls || "");

                if (Ext.isEmpty(this.iconCls)) {
                    img.style.display = "none";
                }

                if (this.iconAlign == "left") {
                    el.appendChild(img);
                }

                el.appendChild(this.valueElement());

                if (this.iconAlign == "right") {
                    el.appendChild(img);
                }

                this.el = el;
                Ext.BoxComponent.superclass.onRender.call(this, ct, position);
            }

            if (this.pressed && this.allowDepress !== false) {
                this.setDisabled(true);
                this.disabled = false;
                this.el.dom.style.cursor = "pointer";
            }

            Ext.ButtonToggleMgr.register(this);
        },
        setText: function (t, encode) {
            this.text = t;
            if (this.rendered) {
                this.textEl.innerHTML = encode !== false ? Ext.util.Format.htmlEncode(t) : t;
            }
            return this;
        },
        setIconClass: function (cls) {
            var oldCls = this.iconCls;
            this.iconCls = cls;
            if (this.rendered) {
                var img = this.el.child("img.x-label-icon");
                img.replaceClass(oldCls, this.iconCls);
                img.dom.style.display = (cls === "") ? "none" : "inline";
            }
        },
        setDisabled: function (disabled) {
            Coolite.Ext.LinkButton.superclass.setDisabled.apply(this, arguments);
            if (disabled) {
                this.textEl.setAttribute("disabled", "1");
                this.textEl.removeAttribute("href");
            }
            else {
                this.textEl.removeAttribute("disabled");
                this.textEl.setAttribute("href", "#");
            }
        }
    });

    Ext.reg("linkbutton", Coolite.Ext.LinkButton);

    Ext.form.FormPanel.override({
        initComponent: function() {
            this.form = this.createForm();

            this.bodyCfg = {
                tag: 'form',
                cls: this.baseCls + '-body',
                method: this.method || 'POST',
                id: this.formId || Ext.id()
            };
            if (this.fileUpload) {
                this.bodyCfg.enctype = 'multipart/form-data';
            }

            if (this.isInForm) {
                this.bodyCfg.tag = "div";
            }

            Ext.FormPanel.superclass.initComponent.call(this);

            this.initItems();

            this.addEvents(
            /**
            * @event clientvalidation
            * If the monitorValid config option is true, this event fires repetitively to notify of valid state
            * @param {Ext.form.FormPanel} this
            * @param {Boolean} valid true if the form has passed client-side validation
            */
                'clientvalidation'
            );

            this.relayEvents(this.form, ['beforeaction', 'actionfailed', 'actioncomplete']);
        }
    });

    Ext.Spotlight = function (config) {
        Ext.apply(this, config);
    };
    
    Ext.Spotlight.prototype = {
        active: false,
        animate: true,
        animated: false,
        duration: 0.25,
        easing: "easeNone",

        createElements: function () {
            var bd = Ext.getBody();

            this.right = bd.createChild({ cls: "x-spotlight" });
            this.left = bd.createChild({ cls: "x-spotlight" });
            this.top = bd.createChild({ cls: "x-spotlight" });
            this.bottom = bd.createChild({ cls: "x-spotlight" });

            this.all = new Ext.CompositeElement([this.right, this.left, this.top, this.bottom]);
        },

        show: function (el, callback, scope) {
            if (this.animated) {
                this.show.defer(50, this, [el, callback, scope]);
                return;
            }
            this.el = Coolite.Ext.getEl(el);
            if (!this.right) {
                this.createElements();
            }
            if (!this.active) {
                this.all.setDisplayed("");
                this.applyBounds(true, false);
                this.active = true;
                Ext.EventManager.onWindowResize(this.syncSize, this);
                this.applyBounds(false, this.animate, false, callback, scope);
            } else {
                this.applyBounds(false, false, false, callback, scope); // all these booleans look hideous
            }
        },

        hide: function (callback, scope) {
            if (this.animated) {
                this.hide.defer(50, this, [callback, scope]);
                return;
            }
            Ext.EventManager.removeResizeListener(this.syncSize, this);
            this.applyBounds(true, this.animate, true, callback, scope);
        },

        doHide: function () {
            this.active = false;
            this.all.setDisplayed(false);
        },

        syncSize: function () {
            this.applyBounds(false, false);
        },

        applyBounds: function (basePts, anim, doHide, callback, scope) {

            var rg = this.el.getRegion();

            var dw = Ext.lib.Dom.getViewWidth(true);
            var dh = Ext.lib.Dom.getViewHeight(true);

            var c = 0, cb = false;
            if (anim) {
                cb = {
                    callback: function () {
                        c++;
                        if (c == 4) {
                            this.animated = false;
                            if (doHide) {
                                this.doHide();
                            }
                            Ext.callback(callback, scope, [this]);
                        }
                    },
                    scope: this,
                    duration: this.duration,
                    easing: this.easing
                };
                this.animated = true;
            }

            this.right.setBounds(
                rg.right,
                basePts ? dh : rg.top,
                dw - rg.right,
                basePts ? 0 : (dh - rg.top),
                cb);

            this.left.setBounds(
                0,
                0,
                rg.left,
                basePts ? 0 : rg.bottom,
                cb);

            this.top.setBounds(
                basePts ? dw : rg.left,
                0,
                basePts ? 0 : dw - rg.left,
                rg.top,
                cb);

            this.bottom.setBounds(
                0,
                rg.bottom,
                basePts ? 0 : rg.right,
                dh - rg.bottom,
                cb);

            if (!anim) {
                if (doHide) {
                    this.doHide();
                }
                if (callback) {
                    Ext.callback(callback, scope, [this]);
                }
            }
        },

        destroy: function () {
            this.doHide();
            Ext.destroy(
                this.right,
                this.left,
                this.top,
                this.bottom);
            delete this.el;
            delete this.all;
        }
    };

    Ext.ToolTip.override({
        initTarget: function() {
            targetEl = Ext.get(this.target);
            if (!Ext.isEmpty(targetEl)) {
                this.initTargetEvents(targetEl);
            }
            else {
                var getTargetTask = new Ext.util.DelayedTask(function(task) {
                    targetEl = Ext.get(this.target);
                    if (!Ext.isEmpty(targetEl)) {
                        this.initTargetEvents(targetEl);
                        task.cancel();
                    } else {
                        task.delay(500, undefined, this, [task]);
                    }
                }, this);
                getTargetTask.delay(1, undefined, this, [getTargetTask]);
            }
        },

        initTargetEvents: function(targetEl) {
            this.target = targetEl;
            this.target.on('mouseover', this.onTargetOver, this);
            this.target.on('mouseout', this.onTargetOut, this);
            this.target.on('mousemove', this.onMouseMove, this);
        }
    });

    Ext.DatePicker.prototype.initComponent = Ext.DatePicker.prototype.initComponent.createSequence(function() {
        var fn = function() { this.getInputField().setValue(this.getValue().dateFormat("Y-m-d\\Th:i:s")); };
        this.on("render", fn, this);
        this.on("select", fn, this);
    });

    Ext.DatePicker.prototype.onRender = Ext.DatePicker.prototype.onRender.createSequence(function(el) {
        this.getInputField().render(this.el.parent() || this.el);
    });

    Ext.DatePicker.override({
        getInputField: function() {
            if (!this.inputField) {
                this.inputField = new Ext.form.Hidden({ id: this.id + "_Input", name: this.id + "_Input" });            
            }
            return this.inputField;
        }
    });

    Ext.Button.prototype.onRender = Ext.Button.prototype.onRender.createSequence(function(el) {
        if (this.enableToggle || !Ext.isEmpty(this.toggleGroup)) {
            this.getPressedField().render(this.el.parent() || this.el);
        }
    });

    Ext.Button.override({
        getPressedField: function() {
            if (!this.pressedField) {
                this.pressedField = new Ext.form.Hidden({ id: this.id + "_Pressed", name: this.id + "_Pressed" });
            }
            return this.pressedField;
        }
    });

    Ext.menu.CheckItem.prototype.onRender = Ext.menu.CheckItem.prototype.onRender.createSequence(function(el) {
        this.getCheckedField().render(this.el.parent() || this.el);
    });

    Ext.menu.CheckItem.override({
        getCheckedField: function() {
            if (!this.checkedField) {
                this.checkedField = new Ext.form.Hidden({ id: this.id + "_Checked", name: this.id + "_Checked" });
            }
            return this.checkedField;
        }
    });

    Ext.ColorPalette.prototype.onRender = Ext.ColorPalette.prototype.onRender.createSequence(function(el) {
        this.getColorField().render(this.el.parent() || this.el);
    });

    Ext.ColorPalette.override({
        getColorField: function() {
            if (!this.colorField) {
                this.colorField = new Ext.form.Hidden({ id: this.id + "_Color", name: this.id + "_Color" });
            }
            return this.colorField;
        }
    });

    Ext.Slider.prototype.onRender = Ext.Slider.prototype.onRender.createSequence(function(el) {
        this.getValueField().render(this.el.parent() || this.el);
    });

    Ext.Slider.override({
        getValueField: function() {
            if (!this.valueField) {
                this.valueField = new Ext.form.Hidden({ id: this.id + "_Value", name: this.id + "_Value" });
            }
            return this.valueField;
        }
    });

    Ext.History.init = Ext.History.init.createInterceptor(function(onReady, scope) {
        if (this.listeners) {
            this.on(this.listeners);
            delete this.listeners;
        }
    });

    Ext.apply(Ext.form.VTypes, {
        daterange: function (val, field) {
            var date = field.parseDate(val);

            var dispUpd = function (picker) {
                var ad = picker.activeDate;
                if (ad) {
                    picker.activeDate = null;
                    picker.update(ad);
                }
            };

            if (field.startDateField) {
                var sd = Ext.getCmp(field.startDateField);
                sd.maxValue = date;
                if (sd.menu && sd.menu.picker) {
                    sd.menu.picker.maxDate = date;
                    dispUpd(sd.menu.picker);
                }
            }
            else if (field.endDateField) {
                var ed = Ext.getCmp(field.endDateField);
                ed.minValue = date;
                if (ed.menu && ed.menu.picker) {
                    ed.menu.picker.minDate = date;
                    dispUpd(ed.menu.picker);
                }
            }
            return true;
        }
    });

    if (!Ext.isIE6) {
        if (Ext.isIE) {
            Ext.util.CSS.createStyleSheet(".x-btn button{width:100%;}");
        }
        Ext.util.CSS.createStyleSheet(".x-form-radio-group .x-panel-body,.x-form-check-group .x-panel-body{background-color:transparent;}.x-form-cb-label-nowrap{white-space:nowrap;} .x-label-icon{width:16px;height:16px; margin-left:3px; margin-right:3px; vertical-align:middle;border:0px !important;} .x-label-value{vertical-align:middle;}");
    }
    
    Coolite.Ext.setTheme = function (url) {
        Ext.util.CSS.swapStyleSheet("ext-theme", url);
    };

    Coolite.Ext.getEl = function (el) {
        if (el.getEl) {
            return el.getEl();
        }

        var cmp = Ext.getCmp(el);
        if (!Ext.isEmpty(cmp)) {
            return cmp.getEl();
        }

        return Ext.get(el);
    };

    if ("function" !== typeof RegExp.escape) {
        RegExp.escape = function (s) {
            if ("string" !== typeof s) {
                return s;
            }
            return s.replace(/([.*+?^=!:${}()|[\]\/\\])/g, "\\$1");
        };
    }

if(typeof Sys!=="undefined"){Sys.Application.notifyScriptLoaded();}