﻿Client =
{
    InsertForm: function(config)
    {
        var form = new Ext.FormPanel({
            id: config.id,
            labelWidth: config.labelWidth ? config.labelWidth : 220,
            url: config.url,
            title: config.title,
            fileUpload: config.fileUpload,
            returnUrl: config.returnUrl ? config.returnUrl : "",
            frame: config.frame != undefined ? config.frame : true,
            border: config.border != undefined ? config.border : true,
            autoWidth: config.width ? config.width : false,
            defaults: { anchor: '100%' },
            defaultType: "textfield",
            focusControl: config.focusControl,
            renderTo: config.renderTo,
            locked: config.locked,
            tbar: config.tbar,
            validateForm: config.validateForm != undefined ? config.validateForm : true,
            beforeSave: config.beforeSave,
            onSave: config.onSave,
            onCancel: config.onCancel,
            params: config.params,
            onSaveComplete: config.onSaveComplete,

            SubmitForm: function(message)
            {
                var form = Ext.getCmp(config.id);
                var basicForm = form.getForm();

                if (form.validateForm)
                {
                    if (!form.getForm().isValid())
                    {
                        var invalidFields = form.getForm().getInvalidFields();
                        var itemList = Client.ToHtmlList(invalidFields);

                        Ext.Msg.show({
                            title: "Form Validation Failed",
                            msg: "The following fields are either incomplete or invalid: <br /><br />" + itemList,
                            buttons: Ext.Msg.OK,
                            icon: Ext.MessageBox.WARNING
                        });

                        return;
                    }
                }

                if (form.beforeSave)
                {
                    form.beforeSave.call(this);
                }

                if (form.onSave == undefined)
                {
                    Client.SubmitForm(basicForm, config.renderTo, form.params, form.onSaveComplete, message);
                }
                else
                {
                    form.onSave.call(this, form.onSaveComplete);
                }
            },

            focusFocusControl: function()
            {
                if (config.focusControl != undefined)
                {
                    try
                    {
                        Ext.getCmp(config.focusControl).focus(false, 200);
                    }
                    catch (e)
                    {
                    }
                }
            },

            keys: [{ key: [83, 115, 10, 13], fn: function(keyCode, event)
            {
                var form = Ext.getCmp(config.id);

                switch (keyCode)
                {
                    case 83:
                    case 115:
                        if (event.ctrlKey)
                        {
                            if (form.onKeySubmit)
                            {
                                form.onKeySubmit.call(this);
                            }
                            else
                            {
                                form.SubmitForm.call(this);
                            }
                        }
                        break;

                    default:
                        if (event.target.nodeName != "TEXTAREA")
                        {
                            if (form.onKeySubmit)
                            {
                                form.onKeySubmit.call(this);
                            }
                            else
                            {
                                form.SubmitForm.call(this);
                            }
                        }
                        break;
                }
            } }],

                items: config.items,

                bbar: new Ext.Toolbar({
                    id: config.id + "-bbar",
                    style: "border: none",
                    hidden: config.showButtons ? false : true,
                    items: ["->", config.buttons ? config.buttons : [{
                        text: "Save",
                        id: "saveButton",
                        iconCls: "saveIcon",
                        handler: function()
                        {
                            var form = Ext.getCmp(config.id);
                            form.SubmitForm.call(this);
                        }
                    }, {
                        text: "Cancel Changes",
                        iconCls: "cancelIcon",
                        handler: function()
                        {
                            Ext.Msg.show({
                                title: "Cancel Changes?",
                                msg: "Are you sure you wish to cancel your changes",
                                buttons: Ext.Msg.YESNO,
                                icon: Ext.MessageBox.QUESTION,
                                fn: function(btn)
                                {
                                    if (btn == "yes")
                                    {
                                        var form = Ext.getCmp(config.id);

                                        if (form.onCancel == undefined)
                                        {
                                            var grid = form.boundGrid;

                                            if (grid)
                                            {
                                                //Reload data
                                                if (grid.dataUrl)
                                                {
                                                    grid.loadData();
                                                }
                                            }

                                            // Hide toolbar
                                            form.showToolbar(false);

                                            // Display message to user
                                            Ext.MessageBubble.show('Changes Cancelled', 'Your changes have been cancelled', function()
                                            {
                                                var basicForm = form.getForm();
                                                basicForm.reset();
                                                basicForm.lock();

                                                if (grid)
                                                {
                                                    grid.getSelectionModel().selectFirstRow();
                                                }
                                            });
                                        }
                                        else
                                        {
                                            form.onCancel.call(this);
                                            form.showToolbar(false);
                                        }
                                    }
                                }
                            });
                        }
}]]
                    }),

                    showToolbar: function(value)
                    {
                        var form = Ext.getCmp(config.id);
                        if (form.getForm().ignoreChanges)
                        {
                            return;
                        }

                        var toolbar = Ext.getCmp(config.id + "-bbar");
                        toolbar.setVisible(value);
                    },

                    setBoundGrid: function(grid)
                    {
                        var form = Ext.getCmp(config.id);
                        form.boundGrid = grid;
                        form.getForm().boundGrid = grid;

                        if (form.boundGrid.getSelectedId() == null)
                        {
                            form.getForm().lock();
                        }
                    },

                    listeners:
                {
                    afterrender: function()
                    {
                        var form = Ext.getCmp(config.id);
                        var basicForm = form.getForm();

                        form.focusFocusControl();

                        // Capture control change events / form updates
                        for (i = 0; i < basicForm.items.length; i++)
                        {
                            var control = basicForm.items.itemAt(i);
                            var event = [];

                            switch (control.getXType())
                            {
                                case "checkbox":
                                    event = ["check"];
                                    break;

                                case "combo":
                                    event = ["select", "change"];
                                    break;

                                default:
                                    event = ["change"];
                                    break;
                            }

                            for (iEvent = 0; iEvent < event.length; iEvent++)
                            {
                                var eventName = event[iEvent];
                                control.addListener(eventName, function(control)
                                {
                                    var form = Ext.getCmp(config.id);
                                    var basicForm = form.getForm();

                                    if (form.getForm().ignoreChanges)
                                    {
                                        return;
                                    }

                                    if (control.readOnly)
                                    {
                                        return;
                                    }

                                    if (basicForm.record)
                                    {
                                        // If combobox, update displayfield of record too (so the value displays in the grid)
                                        if (control.getXType() == "combo")
                                        {
                                            if (control.boundDisplayField)
                                            {
                                                basicForm.record.set(control.boundDisplayField, control.lastSelectionText);
                                            }

                                            if (control.boundValueField)
                                            {
                                                basicForm.record.set(control.boundValueField, control.getValue());
                                            }
                                        }

                                        // Update record and reflect changes in the boundGrid
                                        basicForm.updateRecord(basicForm.record);

                                        // If the record is not dirty, exit. That means the change event should not have fired (which sometimes happens in Safari)
                                        if (!basicForm.record.dirty)
                                        {
                                            return;
                                        }
                                    }

                                    // Data changed - show Save / Cancel buttons
                                    form.showToolbar(true);

                                    if (form.boundGrid)
                                    {
                                        // Check if multiEdit is enabled, if not then lock the grid until the edit has finished
                                        if (!config.multiEdit)
                                        {
                                            form.boundGrid.lock();
                                        }
                                    }
                                });

                                control.onClear = function()
                                {
                                    var form = Ext.getCmp(config.id);

                                    // Data changed - show Save / Cancel buttons
                                    form.showToolbar(true);
                                }
                            }
                        }
                    }
                }
                });

                return form;
            },

            InsertPanel: function(config)
            {
                var panel = new Ext.Panel({
                    id: config.id,
                    labelWidth: config.labelWidth ? config.labelWidth : 220,
                    layout: config.layout,
                    title: config.title ? config.title : "",
                    frame: config.frame != undefined ? config.frame : true,
                    border: config.border != undefined ? config.border : true,
                    autoWidth: config.width ? config.width : false,
                    autoHeight: config.autoHeight ? config.autoHeight : false,
                    html: config.html,
                    defaults: { anchor: '100%' },
                    renderTo: config.renderTo,
                    tbar: config.tbar,
                    width: config.width,
                    height: config.height,
                    focusControl: config.focusControl,
                    style: config.style,

                    focusFocusControl: function()
                    {
                        if (config.focusControl != undefined)
                        {
                            try
                            {
                                Ext.getCmp(config.focusControl).focus(false, 200);
                            }
                            catch (e)
                            {
                            }
                        }
                    },

                    items: config.items,
                    buttons: config.buttons ? config.buttons : "",
                    listeners:
                    {
                        afterrender: function()
                        {
                            var panel = Ext.getCmp(config.id);
                            panel.focusFocusControl();
                        }
                    }
                });

                return panel;
            },

            SubmitForm: function(form, maskId, params, fn, message)
            {
                var json = Client.JsonEncodeForm(form);

                if (params)
                {
                    params.json = json;
                }
                else
                {
                    params = { json: json };
                }

                Ext.get(maskId).mask(message ? message : "Saving...");

                form.submit({
                    params: params,
                    success: function(form, action)
                    {
                        // Get result
                        var result = action.result;

                        if (form.record)
                        {
                            // Persist data into record set
                            form.updateRecord(form.record);
                        }

                        // Redirect to returnUrl if present
                        if (form.returnUrl)
                        {
                            document.location = form.returnUrl;
                            return;
                        }

                        // Select initial focus cell
                        form.focusFocusControl();

                        // Hide toolbar
                        form.showToolbar(false);

                        // Unmask
                        Ext.get(maskId).unmask();

                        // Show message bubble
                        Ext.MessageBubble.show('Success', result == null ? "" : (result.msg == null ? "" : "The record was saved"));

                        // Refresh grid data and enable
                        if (form.boundGrid)
                        {
                            if (form.boundGrid.dataUrl)
                            {
                                form.boundGrid.loadData.call(this, result.returnObject);
                            }
                        }

                        // if callback exists, then call it
                        if (fn)
                        {
                            fn.call(this);
                        }
                    },
                    failure: function(form, action)
                    {
                        Ext.get(maskId).unmask();

                        Client.DisplayFormFailureMessage(form, action);
                    }
                });
            },

            DisplayPopup: function(title, url, el)
            {
                // Panel for the west
                var panel = new Ext.Panel({
                    url: url,
                    anchor: '100%',
                    margins: '3 0 3 3',
                    cmargins: '3 3 3 3'
                });

                var win = new Ext.Window({
                    title: title,
                    closable: true,
                    width: 400,
                    height: 350,
                    border: false,
                    plain: true,
                    layout: 'fit',
                    items: panel
                });

                win.show(el);
            },

            FieldSet: function(config)
            {
                var fieldSet = {
                    id: config.id ? config.id : "",
                    xtype: 'fieldset',
                    forceLayout: true,
                    focusControl: config.focusControl,
                    title: config.title ? config.title : "",
                    collapsible: config.collapsible ? config.collapsible : false,
                    collapsed: config.collapsed ? config.collapsed : false,
                    height: config.height,
                    width: config.width,
                    autoHeight: config.height ? config.height : true,
                    autoWidth: config.width ? config.width : true,
                    defaults: { anchor: '100%' },
                    defaultType: 'textfield',
                    boundForm: config.boundForm,
                    bodyStyle: config.bodyStyle,
                    hidden: config.hidden,
                    layoutConfig: config.layoutConfig,
                    items: config.items,

                    focusFocusControl: function()
                    {
                        if (config.focusControl != undefined)
                        {
                            try
                            {
                                Ext.getCmp(config.focusControl).focus(false, 200);
                            }
                            catch (e)
                            {
                            }
                        }
                    }
                };

                if (config.defaults)
                {
                    fieldSet.defaults = config.defaults;
                }

                if (config.layout)
                {
                    fieldSet.layout = config.layout;
                }

                return fieldSet;
            },

            SearchTextField: function(config)
            {
                return new Ext.form.TextField({
                    fieldLabel: config.fieldLabel ? config.fieldLabel : "",
                    id: config.id,
                    width: 200,
                    renderTo: config.renderTo,
                    enableKeyEvents: true,
                    cls: "search",
                    style: "background-repeat:no-repeat; background-position: right;",

                    listeners: {
                        keyup: function(textField, e)
                        {
                            // Use timer so that the keyup event only fires after a 500 millisecond pause in typing
                            if (textField.timerId)
                            {
                                clearTimeout(textField.timerId);
                                textField.timerId = null;
                            }

                            textField.timerId = setTimeout("Ext.getCmp('" + config.id + "').fireSearchEvent('" + textField.getValue() + "')", 500);
                        }
                    },

                    fireSearchEvent: function(search)
                    {
                        if (config.searchEvent)
                        {
                            config.searchEvent.call(this, search);
                        }
                    }
                })
            },

            ComboBox: function(config)
            {
                return new Ext.form.ComboBox({
                    fieldLabel: config.fieldLabel,
                    name: config.name,
                    id: config.id,
                    width: config.width,
                    store: config.store,
                    disabled: config.disabled,
                    value: config.value,
                    enableKeyEvents: true,
                    valueField: config.valueField,
                    displayField: config.displayField,
                    boundValueField: config.boundValueField != null ? config.boundValueField : config.valueField,
                    boundDisplayField: config.boundDisplayField != null ? config.boundDisplayField : config.displayField,
                    fieldType: config.fieldType ? config.fieldType : "",
                    allowBlank: config.allowBlank ? config.allowBlank : true,
                    forceSelection: config.forceSelection != undefined ? config.forceSelection : true,
                    editable: config.editable != undefined ? config.editable : true,
                    tpl: config.tpl,
                    typeAhead: true,
                    mode: 'local',
                    triggerAction: 'all',
                    emptyText: 'Select an item...',
                    selectOnFocus: true,

                    validator: function(value)
                    {
                        if (!this.forceSelection)
                        {
                            return true;
                        }

                        if (this.disabled)
                        {
                            return true;
                        }

                        if (this.hidden)
                        {
                            return true;
                        }

                        if (this.fieldset)
                        {
                            if (this.fieldset.hidden)
                            {
                                return true;
                            }
                        }

                        if (this.getStore().find(this.displayField, value) < 0)
                        {
                            return false;
                        }
                        else
                        {
                            return true;
                        }
                    },

                    listeners: {
                        select: function(combo, record, index)
                        {
                            if (config.onSelectionChange)
                            {
                                config.onSelectionChange.call(this, combo, record, index);
                            }
                        },

                        change: function(combo, newvalue, oldvalue)
                        {
                            if (config.onChange)
                            {
                                config.onChange.call(this, combo, newvalue, oldvalue);
                            }
                        },

                        afterrender: function(combo)
                        {
                            if (config.initialValue)
                            {
                                combo.selectByValue(config.initialValue);
                            }
                        }
                    }
                });
            },

            DatePicker: function(config)
            {
                return new Ext.form.DateField({
                    fieldLabel: config.fieldLabel,
                    name: config.name,
                    format: "M d, Y",
                    id: config.id,
                    allowBlank: config.allowBlank ? config.allowBlank : false,
                    fieldType: config.fieldType ? config.fieldType : '',
                    value: config.value ? Date.parseDate(config.value, "Y-m-d H:i:s") : null
                });
            },

            DataGrid: function(config)
            {
                var grid = null;
                var gridColumnModel = config.columnModel;

                // Display row icon if rowIcon or function specified
                if (config.rowIcon)
                {
                    var iconColumn = Client.IconColumn(config.rowIcon);
                    gridColumnModel.splice(0, 0, iconColumn);
                }
                else if (config.rowIconFn)
                {
                    var iconColumn = Client.IconColumn("", config.rowIconFn);
                    gridColumnModel.splice(0, 0, iconColumn);
                }

                var gridConfig = {
                    id: config.id,
                    columns: gridColumnModel,
                    anchor: '100%',
                    margins: config.margins,
                    clicksToEdit: 1,
                    enableDragDrop: config.enableDragDrop || config.enableDrag ? true : false,
                    ddGroup: config.enableDrag || config.enableDragDrop ? config.ddGroup : "",
                    height: config.height,
                    autoHeight: config.height ? false : config.autoHeight,
                    autoWidth: config.width ? false : true,
                    style: "margin-bottom: 10px;",
                    store: config.store,
                    title: config.title ? config.title : "",
                    dataUrl: config.dataUrl,
                    params: config.params,
                    enableRowDrag: config.enableRowDrag ? config.enableRowDrag : false,
                    sortOnDrop: config.sortOnDrop ? config.sortOnDrop : false,
                    defaultSortColumn: config.defaultSortColumn ? config.defaultSortColumn : "Name",
                    defaultSortDir: config.defaultSortDir ? config.defaultSortDir : "ASC",
                    stripeRows: config.stripeRows,
                    rowIcon: config.rowIcon,
                    onDataLoaded: config.onDataLoaded,
                    selectedId: config.selectedId,
                    boundForm: config.boundForm,
                    boundFieldSet: config.boundFieldSet,
                    autoFitColumns: config.autoFitColumns,
                    locked: config.locked,
                    autoFitColumnHeaders: config.autoFitColumnHeaders,
                    forceFit: config.forceFit ? config.forceFit : (config.autoFitColumns || config.autoFitColumnHeaders ? false : true),

                    viewConfig:
                    {
                        forceFit: config.forceFit ? config.forceFit : (config.autoFitColumns || config.autoFitColumnHeaders ? false : true)
                    },

                    tbar: config.tbar ? config.tbar : new Ext.Toolbar({
                        hidden: config.allowAddDelete || config.enablePrint ? false : true,
                        items:
                        [
                    {
                        text: 'Add',
                        hidden: !config.allowAddDelete,
                        iconCls: 'addButton',
                        alwaysEnable: true,
                        handler: function(btn, ev)
                        {
                            var grid = Ext.getCmp(config.id);
                            var store = grid.getStore();
                            var newRec = new store.recordType();
                            var pos = grid.store.getCount();

                            store.insert(pos, newRec);

                            grid.getSelectionModel().selectLastRow();

                            if (grid.boundForm)
                            {
                                var form = Ext.getCmp(grid.boundForm);
                                form.focusFocusControl();
                            }

                            if (grid.boundFieldSet)
                            {
                                var fieldSet = Ext.getCmp(grid.boundFieldSet);
                                fieldSet.focusFocusControl();
                            }
                        }
                    },
                    {
                        text: 'Delete',
                        iconCls: 'deleteButton',
                        hidden: !config.allowAddDelete,
                        handler: function()
                        {
                            var grid = Ext.getCmp(config.id);
                            var rec = grid.getSelectionModel().getSelected();
                            if (!rec)
                            {
                                return false;
                            }

                            if (!rec.get("Id"))
                            {
                                grid.store.remove(rec);
                                return false;
                            }

                            var id = rec.get("Id");

                            if (config.deleteUrl)
                            {
                                Ext.Msg.show({
                                    title: "Delete selected item?",
                                    msg: "Are you sure you wish to delete the selected item",
                                    buttons: Ext.Msg.YESNO,
                                    icon: Ext.MessageBox.QUESTION,
                                    fn: function(btn)
                                    {
                                        if (btn == "yes")
                                        {
                                            Ext.Ajax.request({
                                                url: config.deleteUrl,
                                                success: function(response, options)
                                                {
                                                    if (!Client.ProcessResponse(response))
                                                    {
                                                        Ext.getCmp(config.id).el.unmask();
                                                        return;
                                                    }

                                                    var grid = Ext.getCmp(config.id);
                                                    if (grid.dataUrl)
                                                    {
                                                        grid.loadData.call(this);
                                                    }
                                                },
                                                failure: function(response, options)
                                                {
                                                    Client.DisplayAjaxFailureMessage(response, options);
                                                    Ext.getCmp(config.id).el.unmask();
                                                },
                                                params: { id: id }
                                            });
                                        }
                                    }
                                });

                                return;
                            }

                            grid.store.remove(rec);

                            var showToolbar = function()
                            {
                                if (grid.boundForm)
                                {
                                    var form = Ext.getCmp(config.boundForm);
                                    form.showToolbar(true);
                                }
                            }

                            showToolbar.defer(100);
                        }
                    },
                    config.extraButtons ? config.extraButtons : [],
                    {
                        text: 'Print',
                        iconCls: 'printIcon',
                        hidden: !config.enablePrint,
                        handler: function(btn, ev)
                        {
                            var grid = Ext.getCmp(config.id);
                            grid.print(grid);
                        }
                    },
                    '->',
                    {
                        id: config.id + '-gridPadlock',
                        cls: 'lockIcon',
                        xtype: 'panel',
                        style: 'padding-left: 20px;',
                        html: '&nbsp',
                        hidden: true
                    }
                ]
                    }),

                    bbar: config.bbar == undefined ? null : config.bbar,

                    selModel: new Ext.grid.RowSelectionModel({
                        singleSelect: true,
                        listeners:
                        {
                            selectionchange: function(selModel, rowIndex, record)
                            {
                                var grid = Ext.getCmp(config.id);
                                var record = grid.getSelectedRecord();

                                if (grid.boundForm != undefined)
                                {
                                    var form = Ext.getCmp(grid.boundForm);
                                    var basicForm = form.getForm();

                                    if (record)
                                    {
                                        basicForm.unlock();
                                        basicForm.loadRecord(record);
                                    }
                                    else
                                    {
                                        basicForm.reset();
                                        basicForm.lock();
                                    }
                                }

                                if (grid.boundFieldSet != undefined)
                                {
                                    var fieldSet = Ext.getCmp(grid.boundFieldSet);

                                    if (record)
                                    {
                                        fieldSet.unlock();
                                        fieldSet.loadRecord(record);
                                    }
                                    else
                                    {
                                        fieldSet.ignoreChanges = true;
                                        fieldSet.clear();
                                        fieldSet.lock();
                                        fieldSet.ignoreChanges = false;
                                    }
                                }

                                grid.updateToolBar();

                                if (config.onSelectionChange)
                                {
                                    config.onSelectionChange.call(this, record);
                                }
                            }
                        }
                    }),

                    print: function(grid, title)
                    {
                        GridPrinter.print(grid, title);
                    },

                    loadData: function(id)
                    {
                        if (!grid.dataUrl)
                        {
                            Ext.Msg.show({
                                title: "Oops",
                                msg: "The grid's dataUrl has not been configured",
                                buttons: Ext.Msg.OK,
                                icon: Ext.MessageBox.WARNING
                            });
                            return;
                        }

                        grid.el.mask("Loading...");

                        Ext.Ajax.request({
                            url: grid.dataUrl,
                            success: function(response, options)
                            {
                                if (!Client.ProcessResponse(response))
                                {
                                    Ext.getCmp(config.id).el.unmask();
                                    return;
                                }

                                var grid = Ext.getCmp(config.id);
                                var selectedId = grid.selectedId ? grid.selectedId : grid.getSelectedId();
                                var store = Ext.decode(response.responseText);

                                // if selectedId is 0, it must be a new record, retrieve this from the result        
                                if (selectedId == 0)
                                {
                                    selectedId = id;
                                }

                                // Load new data
                                grid.loadStore(store);

                                grid.unlock();

                                try
                                {
                                    grid.selectById(selectedId);
                                }
                                catch (e)
                                {
                                }

                                grid.el.unmask();

                                if (grid.onDataLoaded)
                                {
                                    grid.onDataLoaded.call(this, grid, store);
                                }
                            },
                            failure: function(response, options)
                            {
                                Client.DisplayAjaxFailureMessage(response, options);
                                Ext.getCmp(config.id).el.unmask();
                            },
                            params: grid.params
                        })
                    },

                    listeners:
                {
                    render: function(grid)
                    {
                        if (!config.deferLoad)
                        {
                            if (grid.dataUrl)
                            {
                                grid.loadData();
                            }
                        }

                        if (config.onRender)
                        {
                            config.onRender.call(this, grid);
                        }
                    },

                    afterrender: function(grid)
                    {
                        grid.getSelectionModel().selectRow(0);

                        grid.updateToolBar();

                        // Drag Drop
                        if (config.enableDragDrop)
                        {
                            var grid = Ext.getCmp(config.id);

                            grid.dropTargetEl = grid.getView().scroller.dom;
                            grid.firstGridDropTarget = new Ext.dd.DropTarget(grid.dropTargetEl, {
                                ddGroup: config.dropGroup,
                                notifyDrop: function(ddSource, e, data)
                                {
                                    var records = ddSource.dragData.selections;
                                    var grid = Ext.getCmp(config.id);
                                    var sm = grid.getSelectionModel();

                                    // If you are dropping to the same grid, then reorder the rows
                                    if (grid.id == ddSource.grid.id)
                                    {
                                        if (!grid.enableRowDrag)
                                        {
                                            return;
                                        }
                                        if (records.length > 0)
                                        {
                                            if (ddSource.getDragData(e))
                                            {
                                                var cindex = ddSource.getDragData(e).rowIndex;
                                                if (typeof (cindex) != "undefined")
                                                {
                                                    for (i = 0; i < records.length; i++)
                                                    {
                                                        grid.store.remove(grid.store.getById(records[i].id));
                                                    }
                                                    grid.store.insert(cindex, data.selections);
                                                    sm.clearSelections();
                                                }
                                            }
                                            else
                                            {
                                                for (i = 0; i < records.length; i++)
                                                {
                                                    grid.store.remove(grid.store.getById(records[i].id));
                                                }
                                                grid.store.add(data.selections);
                                                sm.clearSelections();
                                            }
                                        }
                                    }
                                    else
                                    {
                                        // Move row to the other grid
                                        var cindex;

                                        try
                                        {
                                            var t = Ext.lib.Event.getTarget(e);
                                            cindex = ddSource.grid.getView().findRowIndex(t);
                                        }
                                        catch (e)
                                        {
                                        }

                                        if (typeof (cindex) == "undefined" || cindex == false)
                                        {
                                            Ext.each(records, ddSource.grid.store.remove, ddSource.grid.store);
                                            grid.store.add(records);
                                            sm.clearSelections();
                                        }
                                        else
                                        {
                                            Ext.each(records, ddSource.grid.store.remove, ddSource.grid.store);
                                            grid.store.insert(cindex, records);
                                            sm.clearSelections();
                                        }

                                        if (grid.sortOnDrop)
                                        {
                                            grid.store.sort(grid.defaultSortColumn, grid.defaultSortDir);
                                        }
                                    }

                                    return true
                                },
                                notifyOver: function(ddSource, e, data)
                                {
                                    var grid = Ext.getCmp(config.id);

                                    ddSource.ddel.innerHTML = data.selections[0].data.Name;

                                    // If you are dropping to the same grid, then show the display Index (instead of green tick)
                                    if (grid.id == ddSource.grid.id)
                                    {
                                        if (!grid.enableRowDrag)
                                        {
                                            return false;
                                        }

                                        return "x-dd-drop-changeRowPosition";
                                    }
                                    else
                                    {
                                        return "x-dd-drop-transfer";
                                    }
                                }
                            });
                        }

                        // If it is a bound form, bind to grid, for updates
                        if (grid.boundForm)
                        {
                            var form = Ext.getCmp(grid.boundForm);
                            form.setBoundGrid(grid);
                        }

                        // If it is a bound fieldset, bind to grid, for updates
                        if (grid.boundFieldSet)
                        {
                            var fieldSet = Ext.getCmp(grid.boundFieldSet);
                            fieldSet.setBoundGrid(grid);
                        }

                        // capture grid store changes
                        var store = grid.getStore()
                        store.addListener("update", function(store, record, operation)
                        {
                            if (config.boundForm)
                            {
                                var form = Ext.getCmp(config.boundForm);
                                form.showToolbar(true);
                            }

                            if (config.onUpdate)
                            {
                                config.onUpdate.call(this, store, record, operation);
                            }
                        });

                    }, delay: 100, // Allow time for rows to be rendered

                    cellclick: function(grid, rowIndex, columnIndex, e)
                    {
                        if (config.cellclick)
                        {
                            config.cellclick.call(this, grid, rowIndex, columnIndex, e);
                        }
                        else
                        {
                            // Check for delete column
                            if (columnIndex == grid.getColumnModel().getIndexById('deleter'))
                            {
                                var record = grid.getStore().getAt(rowIndex);

                                try
                                {
                                    grid.getStore().remove(record);
                                }
                                catch (e)
                                {
                                }

                                grid.getView().refresh();

                                return;
                            }
                        }

                        if (grid.clicksToEdit > 1)
                        {
                            return;
                        }

                        grid.updateBooleanField(grid, rowIndex, columnIndex);
                    },

                    celldblclick: function(grid, rowIndex, columnIndex, e)
                    {
                        if (grid.clicksToEdit == 1)
                        {
                            return;
                        }

                        grid.updateBooleanField(grid, rowIndex, columnIndex);
                    },

                    rowdblclick: function(grid, rowIndex, e)
                    {
                        if (config.rowdblclick)
                        {
                            config.rowdblclick.call(this, grid, rowIndex, e);
                        }
                    },

                    reconfigure: function(grid)
                    {
                        var store = grid.getStore();
                        store.addListener("update", function(store, record, operation)
                        {
                            if (config.boundForm)
                            {
                                var form = Ext.getCmp(config.boundForm);
                                form.showToolbar(true);
                            }

                            if (config.boundFieldSet)
                            {
                                Ext.getCmp(config.boundFieldSet).onUpdate();
                            }

                            if (config.onUpdate)
                            {
                                config.onUpdate.call(this, store, record, operation);
                            }

                            if (config.onDataChanged)
                            {
                                config.onDataChanged.call(this, store);
                            }
                        });

                        store.addListener("add", function(store, records, row)
                        {
                            if (config.boundForm)
                            {
                                var form = Ext.getCmp(config.boundForm);
                                form.showToolbar(true);
                            }

                            if (config.boundFieldSet)
                            {
                                Ext.getCmp(config.boundFieldSet).onUpdate();
                            }

                            if (config.onAdd)
                            {
                                var fn = function()
                                {
                                    config.onAdd.call(this, store, records, row);
                                }

                                fn.defer(200);
                            }

                            if (config.onDataChanged)
                            {
                                config.onDataChanged.call(this, store);
                            }
                        });

                        store.addListener("remove", function(store, records, row)
                        {
                            if (config.boundForm)
                            {
                                var form = Ext.getCmp(config.boundForm);
                                form.showToolbar(true);
                            }

                            if (config.boundFieldSet)
                            {
                                Ext.getCmp(config.boundFieldSet).onUpdate();
                            }

                            if (config.onRemove)
                            {
                                config.onRemove.call(this, store, records, row);
                            }

                            if (config.onDataChange)
                            {
                                config.onUpdate.call(this, store);
                            }
                        });
                    }
                },

                    updateBooleanField: function(grid, rowIndex, columnIndex)
                    {
                        var colModel = grid.getColumnModel();
                        var col = colModel.getColumnId(columnIndex);
                        var store = grid.getStore();
                        var record = store.getAt(rowIndex);

                        if (!record)
                        {
                            return;
                        }

                        if (!record.fields.get(col))
                        {
                            return;
                        }

                        if (record.fields.get(col).type == "bool")
                        {
                            if (colModel.isCellEditable(columnIndex, rowIndex))
                            {
                                record.set(col, !record.get(col));
                            }
                        }
                    },

                    getSelectedRecord: function()
                    {
                        return Ext.getCmp(config.id).getSelectionModel().getSelected();
                    },

                    getSelectedId: function()
                    {
                        var selectedRecord = Ext.getCmp(config.id).getSelectionModel().getSelected();

                        if (selectedRecord)
                        {
                            return selectedRecord.get("Id");
                        }
                        else
                        {
                            return null;
                        }
                    },

                    selectById: function(id)
                    {
                        var grid = Ext.getCmp(config.id);
                        var store = grid.getStore();

                        for (i = 0; i < store.getCount(); i++)
                        {
                            var record = store.getAt(i);
                            if (record.get("Id") == id)
                            {
                                grid.getSelectionModel().selectRow(i);
                                return;
                            }
                        }
                    },

                    loadStore: function(store)
                    {
                        var grid = Ext.getCmp(config.id);
                        var pager = grid.getBottomToolbar();

                        if (pager)
                        {
                            pager.bind(store);

                            // Only show the pager if the number of records is greater than the page size                            
                            pager.setVisible(store.totalLength > pager.pageSize);
                        }

                        grid.reconfigure(store, grid.getColumnModel());
                        grid.getView().refresh();

                        // Autosize columns
                        if (!grid.forceFit)
                        {
                            if (grid.autoFitColumns || grid.autoFitColumnHeaders)
                            {
                                grid.autoSizeColumns(grid.autoFitColumnHeaders);
                            }
                        }

                        // Select first row
                        var selModel = grid.getSelectionModel();
                        if (selModel)
                        {
                            selModel.selectFirstRow();
                        }

                        grid.updateToolBar();
                    }
                };

                if (!config.frame)
                {
                    gridConfig.bodyCfg =
                {
                    style: 'border-left: solid 1px #D0D0D0; border-right: solid 1px #D0D0D0'
                };
                }

                // Paging
                if (!config.disablePaging)
                {
                    gridConfig.bbar = new Ext.PagingToolbar
                    ({
                        pageSize: config.pageSize ? config.pageSize : 20,
                        store: config.store,
                        displayInfo: true,
                        hidden: true
                    });
                }

                // Editor grid or normal grid
                if (config.editable)
                {
                    grid = new Ext.grid.EditorGridPanel(gridConfig);
                }
                else
                {
                    grid = new Ext.grid.GridPanel(gridConfig);
                }

                function getVisibleColumn(column)
                {
                    if (config.visibleColumns == undefined)
                    {
                        return;
                    }

                    function getColName(col)
                    {
                        if (col.indexOf(":") >= 0)
                        {
                            return col.split(":")[0];
                        }
                        else
                        {
                            return col;
                        }
                    }

                    function getColLabel(col)
                    {
                        if (col.indexOf(":") >= 0)
                        {
                            return col.split(":")[1];
                        }
                        else
                        {
                            return "";
                        }
                    }

                    function getColCustomWidth(col)
                    {
                        if (col.indexOf(":") >= 0)
                        {
                            var customWidth = col.split(":")[2];

                            if (customWidth)
                            {
                                return parseInt(customWidth);
                            }
                        }
                        else
                        {
                            return "";
                        }
                    }

                    for (x = 0; x < config.visibleColumns.length; x++)
                    {
                        var col = config.visibleColumns[x];
                        var colName = getColName(col);
                        var label = getColLabel(col);
                        var width = getColCustomWidth(col);

                        if (colName == column)
                        {
                            return { column: colName, label: label, width: width, displayIndex: x };
                        }
                    }

                    return null;
                }

                // Hide unused columns if visible columns is used
                if (config.visibleColumns != undefined)
                {
                    var colModel = Ext.getCmp(config.id).getColumnModel();

                    if (config.id == "filterGrid")
                    {
                        debugger
                    }

                    for (i = 0; i < colModel.getColumnCount(); i++)
                    {
                        var columnName = colModel.getColumnId(i);
                        var column = colModel.getColumnById(columnName);
                        var visibleColumn = getVisibleColumn(columnName);

                        if (columnName == "deleter")
                        {
                            continue;
                        }

                        if (visibleColumn == null)
                        {
                            colModel.setHidden(i, true);
                        }
                        else
                        {
                            // Move column according to displayIndex
                            colModel.moveColumn(i, visibleColumn.displayIndex);

                            // Check for custom label
                            if (visibleColumn.label != '')
                            {
                                column.header = visibleColumn.label;
                            }
                            // Check if custom width                        
                            if (visibleColumn.width)
                            {
                                column.width = visibleColumn.width;
                            }
                        }
                    }
                }

                if (config.renderTo != undefined)
                {
                    grid.render(config.renderTo);
                }

                return grid;
            },


            JsonEncodeForm: function(form)
            {
                var fields = [];

                for (i = 0; i < form.items.length; i++)
                {
                    var item = form.items.itemAt(i);
                    if (item.name != undefined)
                    {
                        var value = "";

                        switch (item.getXType())
                        {
                            case "datefield":
                                value = item.getValue();

                                if (value)
                                {
                                    value = value.format("Y-m-d H:i:s");
                                }

                                break;

                            default:
                                value = item.getValue();
                                break;
                        }

                        fields[i] = { Name: item.name, Value: value, FieldType: item.fieldType ? item.fieldType : "" };
                    }
                }

                return Ext.encode(fields);
            },

            JsonEncodeRecord: function(record)
            {
                var fields = [];

                // cols
                for (j = 0; j < record.fields.length; j++)
                {
                    var value;
                    var field = record.fields.itemAt(j);

                    switch (field.type)
                    {
                        case "datefield":
                            value = record.get(field.name);

                            if (value)
                            {
                                value = value.format("Y-m-d H:i:s");
                            }
                            break;

                        default:
                            value = record.get(field.name);
                            break;
                    }

                    fields[j] = { Name: field.name, Value: value ? value : "", FieldType: field.fieldType ? field.fieldType : "" };
                }

                return fields;
            },

            JsonEncodeStore: function(store, modifiedOnly)
            {
                var rows = [];
                var recordsCount;
                var modifiedRecords = store.getModifiedRecords();

                if (modifiedOnly)
                {
                    recordsCount = modifiedRecords.length;
                }
                else
                {
                    recordsCount = store.getCount();
                }

                // rows
                for (i = 0; i < recordsCount; i++)
                {
                    var record;
                    if (modifiedOnly)
                    {
                        record = modifiedRecords[i];
                    }
                    else
                    {
                        record = store.getAt(i);
                    }

                    rows[i] = Client.JsonEncodeRecord(record);
                }

                return Ext.encode(rows);
            },

            CreateQueryStringFromForm: function(form)
            {
                var url = "";

                for (i = 0; i < form.items.length; i++)
                {
                    var item = form.items.itemAt(i);
                    if (item.name != undefined)
                    {
                        var value = "";

                        switch (item.getXType())
                        {
                            case "datefield":
                                value = item.getValue().format("Y-m-d H:i:s");
                                break;

                            default:
                                value = item.getValue();
                                break;
                        }

                        if (i > 0)
                        {
                            url += "&";
                        }

                        url += item.name + "=" + value;
                    }
                }

                return url;
            },

            ToProperCase: function(value)
            {
                return value.charAt(0).toUpperCase() + value.substring(1, value.length).toLowerCase();
            },

            DisplayFormFailureMessage: function(form, action, fn)
            {
                var result;
                var msg;

                try
                {
                    // See if there is a result object
                    result = Ext.decode(action.response.responseText);

                    if (!result.success)
                    {
                        msg = result.msg;
                    }
                }
                catch (e)
                {
                }

                if (!msg)
                {
                    var statusText = "";
                    var responseText = "";

                    try
                    {
                        statusText = action.response.statusText;
                    }
                    catch (e)
                    {
                        statusText = "Unknown Error";
                    }

                    try
                    {
                        responseText = action.response.responseText;
                    }
                    catch (e)
                    {
                    }

                    msg = "Url: " + form.url + "<br /><br />" +
                      "Status:" + statusText + "<br /><br />" +
                      responseText;
                }

                Ext.Msg.show({
                    title: "Oops",
                    msg: msg,
                    buttons: Ext.Msg.OK,
                    icon: Ext.MessageBox.WARNING,
                    fn: fn
                });
            },

            DisplayAjaxFailureMessage: function(response, options, fn)
            {
                var result;
                var msg;

                try
                {
                    // See if there is a result object
                    result = Ext.decode(response.responseText);

                    if (!result.success)
                    {
                        msg = result.msg;
                    }
                }
                catch (e)
                {
                }

                if (!msg)
                {
                    var msg = "Url: " + options.url + "<br /><br />" +
                      "Status:" + response.status + ' - ' + response.statusText + "<br /><br />" +
                      response.responseText;
                }

                Ext.Msg.show({
                    title: "Ajax Error",
                    msg: msg,
                    buttons: Ext.Msg.OK,
                    icon: Ext.MessageBox.WARNING,
                    fn: fn
                });
            },

            ProcessResponse: function(response)
            {
                var result;

                try
                {
                    result = Ext.decode(response.responseText);

                    if (result.success == undefined)
                    {
                        // It is not a result object
                        return true;
                    }

                    if (!result.success)
                    {
                        Ext.Msg.show({
                            title: "Oops",
                            msg: result.msg,
                            buttons: Ext.Msg.OK,
                            icon: Ext.MessageBox.WARNING
                        });
                        return false;
                    }
                }
                catch (e)
                {
                }

                return true;
            },

            IconColumn: function(className, fn, col)
            {
                if (!col)
                {
                    col = "Icon";
                }
                var iconColumn =
                {
                    header: "",
                    dataIndex: col,
                    name: col,
                    id: col,
                    width: 24,

                    renderer: function(v, p, record, rowIndex)
                    {
                        if (fn)
                        {
                            className = fn(record);
                        }

                        return '<div class="' + className + '" style="width: 20px; background-position: left; height: 16px;"></div>';
                    }
                };

                return iconColumn;
            },

            Menu: function(config)
            {
                var menu = new Ext.menu.Menu({
                    id: config.id,
                    floating: false,
                    autoWidth: true
                });

                var panel = new Ext.Panel({
                    id: config.id + "-panel",
                    title: config.title ? config.title : "",
                    frame: config.frame != undefined ? config.frame : true,
                    border: config.border != undefined ? config.border : true,
                    autoWidth: true,
                    defaults: { anchor: '100%' },
                    renderTo: config.renderTo,

                    items: menu
                });

                return menu;
            },

            ToHtml: function(element)
            {
                var div = document.createElement("div");
                div.appendChild(element);

                return div.innerHTML;
            },

            InputBox: function(name, fn)
            {
                var form = Client.InsertForm({
                    id: "inputForm",
                    title: "Enter " + name,
                    labelWidth: 40,
                    keys: [{ key: [10, 13], fn: submitForm}],
                    items: new Ext.form.TextField({
                        fieldLabel: "Value",
                        name: "inputValue",
                        id: "inputValue"
                    }),
                    buttons: []
                })

                function submitForm()
                {
                    var value = Ext.getCmp("inputValue").getValue();
                    fn.call(this, value);
                }

                var inputWindow = new Ext.Window({
                    id: "inputWindow",
                    layout: 'fit',
                    width: 340,
                    height: 170,
                    closeAction: 'close',
                    plain: true,

                    items: form,

                    closeWindow: function()
                    {
                        var closeFormDelegate = function()
                        {
                            Ext.getCmp("inputWindow").close();
                        }

                        closeFormDelegate.defer(100);
                    },

                    buttons:
                [{
                    text: 'OK',
                    handler: submitForm
                },
                {
                    text: 'Cancel',
                    handler: function()
                    {
                        Ext.getCmp("inputWindow").close();
                    }
}]
                });

                inputWindow.show(this);

                Ext.getCmp("inputValue").focus(false, 200);

                return inputWindow;
            },

            InputComboBox: function(name, store, valueField, displayField, fn)
            {
                var form = Client.InsertForm({
                    id: "inputForm",
                    title: "Enter " + name,
                    labelWidth: 40,
                    keys: [{ key: [10, 13], fn: submitForm}],
                    items: Client.ComboBox({
                        fieldLabel: "Value",
                        name: "inputValue",
                        id: "inputValue",
                        store: store,
                        valueField: valueField,
                        displayField: displayField,
                        allowBlank: false
                    }),
                    buttons: []
                })

                function submitForm()
                {
                    var value = Ext.getCmp("inputValue").getValue();
                    fn.call(this, value);
                }

                var inputWindow = new Ext.Window({
                    id: "inputWindow",
                    layout: 'fit',
                    width: 340,
                    height: 170,
                    closeAction: 'close',
                    plain: true,

                    items: form,

                    closeWindow: function()
                    {
                        var closeFormDelegate = function()
                        {
                            Ext.getCmp("inputWindow").close();
                        }

                        closeFormDelegate.defer(100);
                    },

                    buttons:
            [{
                text: 'OK',
                handler: submitForm
            },
             {
                 text: 'Cancel',
                 handler: function()
                 {
                     Ext.getCmp("inputWindow").close();
                 }
}]
                });

                inputWindow.show(this);

                Ext.getCmp("inputValue").focus(false, 200);

                return inputWindow;
            },

            MessageBubble: function(title, message)
            {
                Ext.MessageBubble.show(title, message);
            },


            TextArea: function(config)
            {
                return new Ext.form.TextArea({
                    id: config.id,
                    width: 400
                });
            },

            DateFormat: function()
            {
                return "M d, Y";
            },

            DateTimeFormat: function()
            {
                return "M d, Y - H:i";
            },

            ServerDateFormat: function()
            {
                return "Y-m-d";
            },

            //Charts
            Chart: function(config)
            {
                var xAxis;
                var yAxis;

                if (config.report.Type == "Bar")
                {
                    xAxis: new Ext.chart.CategoryAxis
                    ({
                        title: config.report.XLabel
                    });

                    yAxis: new Ext.chart.NumericAxis
                    ({
                        title: config.report.YLabel
                    });
                }
                else
                {
                    xAxis: new Ext.chart.NumericAxis
                    ({
                        title: config.report.XLabel
                    });

                    yAxis: new Ext.chart.CategoryAxis
                    ({
                        title: config.report.YLabel
                    });
                };

                var chartConfig =
                {
                    store: config.store,
                    url: getAppRoot() + '/Scripts/ext/resources/charts.swf',
                    xField: config.report.XField,
                    yField: config.report.YField,
                    xAxis: xAxis,
                    yAxis: yAxis,

                    extraStyle:
                    {
                        animationEnabled: true,
                        xAxis:
                        {
                            labelRotation: config.report.XAxisLabelRotation
                        },
                        yAxis:
                        {
                            labelRotation: config.report.YAxisLabelRotation
                        }
                    }
                };

                var chart;
                switch (config.report.Type)
                {
                    case "Column":
                        chart = new Ext.chart.ColumnChart(chartConfig);
                        break;

                    case "Line":
                        chart = new Ext.chart.LineChart(chartConfig);
                        break;

                    default:
                        chart = new Ext.chart.BarChart(chartConfig);
                        break;
                }

                return chart;
            },

            PieChart: function(config)
            {
                var chart = new Ext.chart.PieChart
                ({
                    store: config.store,
                    url: getAppRoot() + '/Scripts/ext/resources/charts.swf',
                    dataField: config.report.DataField,
                    categoryField: config.report.CategoryField,

                    extraStyle:
                    {
                        animationEnabled: true,
                        legend:
                        {
                            display: 'bottom',
                            padding: 5
                        }
                    }
                })

                return chart;
            },

            StackedBarChart: function(config)
            {
                var seriesFields;
                if (config.report.SeriesFields)
                {
                    seriesFields = Ext.decode(config.report.SeriesFields);
                }

                var chart = new Ext.chart.StackedBarChart
                ({
                    store: config.store,
                    url: getAppRoot() + '/Scripts/ext/resources/charts.swf',
                    yField: config.report.YField,

                    xAxis: new Ext.chart.NumericAxis
                    ({
                        stackingEnabled: true
                    }),

                    series: seriesFields
                })

                return chart;
            },

            StackedColumnChart: function(config)
            {
                var seriesFields;
                if (config.report.SeriesFields)
                {
                    seriesFields = Ext.decode(config.report.SeriesFields);
                }

                var chart = new Ext.chart.StackedColumnChart
                ({
                    store: config.store,
                    url: getAppRoot() + '/Scripts/ext/resources/charts.swf',
                    yField: config.report.YField,

                    xAxis: new Ext.chart.NumericAxis
                    ({
                        stackingEnabled: true
                    }),

                    series: seriesFields
                })

                return chart;
            },

            GetDefaultLabel: function(fieldName)
            {
                var label = "";
                var ch = "";
                var lastCh = "";

                if (!fieldName)
                {
                    return "";
                }

                for (i = 0; i < fieldName.length; i++)
                {
                    ch = fieldName.substring(i, i + 1);

                    if (i == 0)
                    {
                        label += ch.toUpperCase();
                    }
                    else
                    {
                        // If two contiguous numbers, then don't put a space between them
                        if (parseInt(ch) == ch && parseInt(lastCh) == lastCh)
                        {
                            label += ch;
                        }
                        else
                        {
                            label += ch == ch.toUpperCase() ? " " + ch : ch;
                        }
                    }

                    lastCh = ch;
                }

                return label.replace(/  /g, "");
            },

            InsertTabPanel: function(config)
            {
                var panel = new Ext.TabPanel({
                    id: config.id,
                    activeTab: config.activeTab ? config.activeTab : 0,
                    defaults: { autoScroll: true },
                    padding: "10 10 0 10",
                    labelWidth: config.labelWidth ? config.labelWidth : 220,
                    deferredRender: false,
                    forceLayout: true,
                    frame: config.frame != undefined ? config.frame : true,
                    border: config.border != undefined ? config.border : true,
                    autoHeight: config.height ? config.height : true,
                    html: config.html,
                    defaults: { anchor: '100%' },
                    renderTo: config.renderTo,
                    width: config.width,
                    height: config.height,
                    style: config.style,
                    bodyStyle: "background: none; padding: 10px; padding-bottom: 0px",
                    layout: config.layout,
                    defaults: config.defaults,
                    title: config.title,
                    hidden: config.hidden,
                    items: config.items
                });

                return panel;
            },

            FieldSetLabel: function(text)
            {
                return {
                    xtype: "panel",
                    width: "auto",
                    margin: "0",
                    padding: "4 0 0 0",
                    html: text + ":"
                };
            },

            TweenColor: function(element, startColor, endColor)
            {
                colorTween = new ColorTween(element.style, 'backgroundColor', Tween.bounceEaseIn, startColor, endColor, 3);
                colorTween.start();
            },

            ToHtmlList: function(items)
            {
                var html = "";

                for (elIndex = 0; elIndex < items.length; elIndex++)
                {
                    var element = items[elIndex];
                    html += element + "<br />";
                }

                return html;
            },

            FileUpload: function(config)
            {
                return new Ext.ux.form.FileUploadField(config);
            },

            AddToBasket: function(productId, maskId)
            {
                Ext.Ajax.request({
                    url: getAppRoot() + "/ShoppingCart/AddItem",
                    success: function(response, options)
                    {
                        if (!Client.ProcessResponse(response))
                        {
                            Ext.get(maskId).unmask();
                            return;
                        }

                        result = Ext.decode(response.responseText);

                        // update Shopping Cart
                        Client.UpdateBasketItems();

                        Client.MessageBubble("Success", "1 Item Added to Basket");

                        Ext.get(maskId).unmask();
                    },
                    failure: function(response, options)
                    {
                        Client.DisplayFormFailureMessage(response, options);
                        Ext.get(maskId).unmask();
                    },
                    params: { productId: productId }
                });
            },

            RemoveFromBasket: function(id, maskId)
            {
                Ext.Ajax.request({
                    url: getAppRoot() + "/ShoppingCart/RemoveItem",
                    success: function(response, options)
                    {
                        if (!Client.ProcessResponse(response))
                        {
                            Ext.get(maskId).unmask();
                            return;
                        }

                        result = Ext.decode(response.responseText);

                        // update Shopping Cart
                        Client.UpdateBasketItems();

                        Client.MessageBubble("Success", "1 Item Removed from Basket");

                        Ext.get(maskId).unmask();
                    },
                    failure: function(response, options)
                    {
                        Client.DisplayFormFailureMessage(response, options);
                        Ext.get(maskId).unmask();
                    },
                    params: { id: id }
                });
            },

            UpdateBasketItems: function()
            {
                var basketMenu = Ext.get("myBasketMenu");
                if (basketMenu)
                {
                    Ext.Ajax.request
                    ({
                        url: getAppRoot() + "/ShoppingCart/GetItemCount",
                        success: function(response, options)
                        {
                            if (!Client.ProcessResponse(response))
                            {
                                return;
                            }
                            var itemCount = parseInt(response.responseText);
                            basketMenu.dom.innerHTML = "Basket (" + itemCount + ")";
                        },
                        failure: function(response, options)
                        {
                            Client.DisplayAjaxFailureMessage(response, options);
                        }
                    });
                }
            }
        }
