﻿/// <reference name="MicrosoftAjax.debug.js" />
/// <reference name="AjaxControlToolkit.ExtenderBase.BaseScripts.js" assembly="AjaxControlToolkit" />
/// <reference name="AjaxControlToolkit.Common.Common.js" assembly="AjaxControlToolkit" />
/// <reference name="AjaxControlToolkit.DropDown.DropDownBehavior.js" assembly="AjaxControlToolkit"/>
/// <reference name="AjaxControlToolkit.ModalPopup.ModalPopupBehavior.js" assembly="AjaxControlToolkit"/>
/// <reference name="AjaxControlToolkit.AlwaysVisibleControl.AlwaysVisibleControlBehavior.js" assembly="AjaxControlToolkit"/>
/// <reference name="AjaxControlToolkit.PopupControl.PopupControlBehavior.js" assembly="AjaxControlToolkit"/>
/// <reference name="AjaxControlToolkit.Calendar.CalendarBehavior.js" assembly="AjaxControlToolkit"/>
/// <reference path="Web.DataViewResources.js"/>
Type.registerNamespace("Web");

Web.DataViewMode = { View: 'View', Lookup: 'Lookup' };

Web.DataViewSelectionMode = { Single: 'Single', Multiple: 'Multiple' };
Web.DynamicExpressionScope = { Field: 0, ViewRowStyle: 1, CategoryVisibility: 2, DataFieldVisibility: 3, DefaultValues: 4 };
Web.DynamicExpressionType = { RegularExpression: 0, ClientScript: 1, ServerExpression: 2, CSharp: 3, VisualBasic: 4, Any: 4 };

Sys.StringBuilder.prototype.appendFormat = function(fmt, args) {
    this.append(String._toFormattedString(false, arguments));
}

String.isNullOrEmpty = function(s) {
    return s == null || s.length == 0;
}

String.isBlank = function(s) {
    return s == null || s.toString().match(/^\s*$/) != null;
}

Web.DataView = function(element) {
    Web.DataView.initializeBase(this, [element]);
    this._controller = null;
    this._viewId = null;
    this._servicePath = null;
    this._showActionBar = true;
    this._baseUrl = null;
    this._pageIndex = -1;
    this._pageSize = Web.DataViewResources.Pager.PageSizes[0];
    this._sortExpression = null;
    this._filter = [];
    this._externalFilter = [];
    this._categories = null;
    this._fields = null;
    this._allFields = null;
    this._rows = null;
    this._totalRowCount = 0;
    this._firstPageButtonIndex = 0;
    this._pageCount = 0;
    this._views = [];
    this._actionGroups = [];
    this._selectedKey = [];
    this._selectedKeyFilter = []
    this._lastCommandName = null;
    this._lastViewId = null;
    this._lookupField = null;
    this._tabIndex = 0;
    this._filterFields = null;
    this._filterSource = null;
    this._mode = Web.DataViewMode.View;
    this._lookupPostBackExpression = null;
    this._domFilterSource = null;
    this._selectedKeyList = [];
}

Web.DataView.htmlEncode = function(s) { return s ? s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;') : s; }

Web.DataView.htmlAttributeEncode = function(s) { return s ? s.replace(/\x27/g, '&#39;').replace(/\x22/g, '&quot;') : s; }

Web.DataView.isIE6 = this._ie6 = Sys.Browser.agent == Sys.Browser.InternetExplorer && Sys.Browser.version < 7;

Web.DataView.prototype = {
    get_controller: function() {
        return this._controller;
    },
    set_controller: function(value) {
        this._controller = value;
    },
    get_viewId: function() {
        if (!this._viewId && this._views.length > 0)
            this._viewId = this._views[0].Id;
        return this._viewId;
    },
    set_viewId: function(value) {
        this._viewId = value;
    },
    get_newViewId: function() {
        return this._newViewId;
    },
    set_newViewId: function(value) {
        this._newViewId = value;
    },
    get_servicePath: function() {
        return this._servicePath;
    },
    set_servicePath: function set_servicePath(value) {
        this._servicePath = this.resolveClientUrl(value);
        if (!Web.DataView._servicePath) Web.DataView._servicePath = value;
    },
    get_baseUrl: function() {
        return this._baseUrl;
    },
    set_baseUrl: function(value) {
        if (value == '~') value = '/';
        this._baseUrl = value;
        if (!Web.DataView._baseUrl) Web.DataView._baseUrl = value;
    },
    get_siteUrl: function() {
        var servicePath = this.get_servicePath();
        var m = servicePath.match(/(^.+?\/)\w+\/\w+\.asmx/);
        return m ? m[1] : '';
    },
    resolveClientUrl: function(url) {
        return url ? url.replace(/~\x2f/g, this.get_baseUrl()) : null;
    },
    get_hideExternalFilterFields: function() {
        return this._hideExternalFilterFields != false;
    },
    set_hideExternalFilterFields: function(value) {
        this._hideExternalFilterFields = value;
    },
    get_backOnCancel: function() {
        return this._backOnCancel == true;
    },
    set_backOnCancel: function(value) {
        this._backOnCancel = value;
    },
    get_startCommandName: function() {
        return this._startCommandName;
    },
    set_startCommandName: function(value) {
        this._startCommandName = value;
    },
    get_startCommandArgument: function() {
        return this._startCommandArgument;
    },
    set_startCommandArgument: function(value) {
        this._startCommandArgument = value;
    },
    get_exitModalStateCommands: function() {
        return this._exitModalStateCommands;
    },
    set_exitModalStateCommands: function(value) {
        this._exitModalStateCommands = value;
    },
    get_showActionBar: function() {
        return this._showActionBar;
    },
    set_showActionBar: function(value) {
        this._showActionBar = value;
    },
    get_selectionMode: function() {
        return this._selectionMode;
    },
    set_selectionMode: function(value) {
        this._selectionMode = value;
    },
    get_cookie: function() {
        return this._cookie;
    },
    set_cookie: function(value) {
        this._cookie = value;
    },
    get_pageIndex: function() {
        return this._pageIndex;
    },
    set_pageIndex: function(value) {
        this._pageIndex = value;
        if (value >= 0) {
            if (value >= this._firstPageButtonIndex + Web.DataViewResources.Pager.PageButtonCount)
                this._firstPageButtonIndex = value;
            else if (value < this._firstPageButtonIndex) {
                this._firstPageButtonIndex -= Web.DataViewResources.Pager.PageButtonCount;
                if (value < this._firstPageButtonIndex)
                    this._firstPageButtonIndex = value;
            }
            if (this._firstPageButtonIndex < 0)
                this._firstPageButtonIndex = 0;
            if (this.get_pageCount() - this._firstPageButtonIndex < Web.DataViewResources.Pager.PageButtonCount)
                this._firstPageButtonIndex = this.get_pageCount() - Web.DataViewResources.Pager.PageButtonCount;
            if (this._firstPageButtonIndex < 0)
                this._firstPageButtonIndex = 0;
        }
    },
    get_enabled: function() {
        return this._enabled == null ? true : this._enabled;
    },
    set_enabled: function(value) {
        this._enabled = value;
    },
    get_tabIndex: function() {
        return this._tabIndex;
    },
    set_tabIndex: function(value) {
        this._tabIndex = value;
    },
    get_pageSize: function() {
        return this._pageSize;
    },
    set_pageSize: function(value) {
        this._pageSize = value;
        if (this._fields != null) {
            this.set_pageIndex(-2);
            this._loadPage();
        }
    },
    get_sortExpression: function() {
        return this._sortExpression;
    },
    set_sortExpression: function(value) {
        if (!value || value.length == 0)
            this._sortExpression = null;
        else {
            var expression = value.match(/^(\w+)\s*((asc|desc)|$)/)
            if (expression[2].length == 0)
                if (this._sortExpression == null || this._sortExpression.match(/^(\w+)\s/)[1] != expression[1])
                this._sortExpression = value + ' asc';
            else if (this._sortExpression.endsWith(' asc'))
                this._sortExpression = value + ' desc';
            else
                this._sortExpression = value + ' asc';

            else
                this._sortExpression = value;
        }
    },
    get_filterSource: function() {
        return this._filterSource;
    },
    set_filterSource: function(value) {
        this._filterSource = value;
    },
    get_filterFields: function() {
        return this._filterFields;
    },
    set_filterFields: function(value) {
        this._filterFields = value;
    },
    get_allowQuickFind: function() {
        return this._allowQuickFind != false;
    },
    get_quickFindText: function() {
        return String.isNullOrEmpty(this._quickFindText) ? Web.DataViewResources.Grid.QuickFindText : this._quickFindText;
    },
    set_quickFindText: function(value) {
        this._quickFindText = value;
    },
    get_quickFindElement: function() {
        return $get(this.get_id() + '_QuickFind');
    },
    set_allowQuickFind: function(value) {
        this._allowQuickFind = value;
    },
    get_filter: function() {
        if (this.get_lookupField() == null && (this.get_pageIndex() == -1 && !this._allFields || this._externalFilter.length > 0 && this._filter.length == 0)) {
            if (this.get_domFilterSource()) {
                this._externalFilter = [];
                Array.add(this._externalFilter, { Name: this.get_filterFields(), Value: this.get_domFilterSource().value });
            }
            else {
                var params = document.location.href.match(/\?([\s\S]+)/);
                if (params && (this.get_filterSource() != 'None' && this.get_filterSource() == null)) {
                    this._externalFilter = [];
                    var iterator = /(\w+)=([\S\s]+?)(&|$)/g;
                    var match = iterator.exec(params[1]);
                    while (match) {
                        if (match[1] != 'ReturnUrl') Array.add(this._externalFilter, { Name: match[1], Value: decodeURIComponent(match[2]) });
                        match = iterator.exec(params[1]);
                    }
                }
            }
            this.applyExternalFilter();
        }
        else if (this.get_filterSource() == 'Context' && this._externalFilter.length > 0)
            this.applyExternalFilter(true);
        return this._filter;
    },
    set_filter: function(value) {
        this._filter = value;
    },
    get_externalFilter: function() {
        return this._externalFilter;
    },
    set_externalFilter: function(value) {
        this._externalFilter = value;
    },
    get_modalAnchor: function() {
        return this._modalAnchor;
    },
    set_modalAnchor: function(value) {
        this._modalAnchor = value;
    },
    get_isModal: function() {
        return this._modalPopup != null;
    },
    get_categories: function() {
        return this._categories;
    },
    get_fields: function() {
        return this._fields;
    },
    get_rows: function() {
        return this._rows;
    },
    get_selectedRow: function() {
        return this._rows[this._selectedRowIndex != null ? this._selectedRowIndex : 0];
    },
    get_pageCount: function() {
        return this._pageCount;
    },
    get_aggregates: function() {
        return this._aggregates;
    },
    get_views: function() {
        return this._views;
    },
    get_actionGroups: function(scope, all) {
        var groups = [];
        for (var i = 0; i < this._actionGroups.length; i++)
            if (this._actionGroups[i].Scope == scope) {
            var group = this._actionGroups[i];
            var current = all ? group : null;
            if (!all)
                for (var j = 0; j < group.Actions.length; j++)
                if (this._isActionAvailable(group.Actions[j])) {
                current = this._actionGroups[i]
                break;
            }
            if (current) Array.add(groups, current);
        }
        return groups;
    },
    get_actions: function(scope) {
        for (var i = 0; i < this._actionGroups.length; i++)
            if (this._actionGroups[i].Scope == scope)
            return this._actionGroups[i].Actions;
        return [];
    },
    get_selectedKey: function() {
        return this._selectedKey;
    },
    get_selectedKeyFilter: function() {
        return this._selectedKeyFilter;
    },
    _get_selectedValueElement: function() {
        return $get(String.format('{0}_{1}_SelectedValue', this.get_id(), this.get_controller()));
    },
    get_selectedValue: function() {
        var sv = this._get_selectedValueElement();
        return sv ? sv.value : '';
    },
    set_selectedValue: function(value) {
        var selectedValue = this._get_selectedValueElement();
        if (selectedValue)
            selectedValue.value = value;
    },
    _createRowKey: function(index) {
        var r = this._rows[index];
        var v = '';
        for (var i = 0; i < this._keyFields.length; i++) {
            var f = this._keyFields[i];
            if (v.length > 0) v += ',';
            v += r[f.Index].toString()
        }
        return v;
    },
    toggleSelectedRow: function(index) {
        var startIndex = index != null ? index : 0;
        var endIndex = index != null ? index : this._rows.length - 1;
        for (var i = startIndex; i <= endIndex; i++) {
            var key = this._createRowKey(i);
            var j = Array.indexOf(this._selectedKeyList, key);
            if (j == -1)
                Array.add(this._selectedKeyList, key);
            else
                Array.removeAt(this._selectedKeyList, j);
            if (!index) {
                var cb = $get(this.get_id() + '_CheckBox' + i);
                if (cb) cb.checked = j == -1;
            }
        }
        this.set_selectedValue(this._selectedKeyList.join(';'));
    },
    get_view: function() {
        if (!this._view || this._view.Id != this.get_viewId())
            for (var i = 0; i < this._views.length; i++)
            if (this._views[i].Id == this.get_viewId()) {
            if (!this._view && this._views[i].Type == 'Form') {
                this._lastCommandName = 'Select';
                if (this._rows.length > 0) this._selectKeyByRowIndex(this._selectedRowIndex = 0);
            }
            this._view = this._views[i];
            break;
        }
        return this._view;
    },
    get_lastCommandName: function() {
        return this._lastCommandName;
    },
    set_lastCommandName: function(value) {
        this._lastCommandName = value;
        this._lastCommandArgument = null;
    },
    get_lastCommandArgument: function() {
        return this._lastCommandArgument;
    },
    set_lastCommandArgument: function(value) {
        this._lastCommandArgument = value;
    },
    get_isEditing: function() {
        return this._lastCommandName == 'New' || this._lastCommandName == 'Edit';
    },
    get_isInserting: function() {
        return this.get_lastCommandName() == 'New';
    },
    get_lookupField: function() {
        return this.get_mode() == Web.DataViewMode.View ? this._lookupField : this._fields[0];
    },
    set_lookupField: function(value) {
        this._lookupField = value;
    },
    get_lookupContext: function() {
        var f = this.get_lookupField();
        return f ? { 'FieldName': f.Name, 'Controller': f._dataView.get_controller(), 'View': f._dataView.get_viewId()} : null;
    },
    get_mode: function() {
        return this._mode;
    },
    set_mode: function(value) {
        this._mode = value;
    },
    get_lookupValue: function() {
        return this._lookupValue;
    },
    set_lookupValue: function(value) {
        this._lookupValue = value;
    },
    get_lookupText: function() {
        return this._lookupText;
    },
    set_lookupText: function(value) {
        this._lookupText = value;
    },
    get_lookupPostBackExpression: function() {
        return this._lookupPostBackExpression;
    },
    set_lookupPostBackExpression: function(value) {
        this._lookupPostBackExpression = value;
    },
    get_domFilterSource: function() {
        return this._domFilterSource;
    },
    set_domFilterSource: function(value) {
        this._domFilterSource = value;
    },
    initialize: function() {
        Web.DataView.callBaseMethod(this, 'initialize');
        this._headerDropDownOnShowingHandler = Function.createDelegate(this, this._headerDropDownOnShowing);
        this._actionBarGroupOnShowingHandler = Function.createDelegate(this, this._actionBarGroupOnShowing);
        this._viewSelectorOnShownHandler = Function.createDelegate(this, this._viewSelectorOnShown);
        this._bodyKeydownHandler = Function.createDelegate(this, this._bodyKeydown);
        this._filterSourceSelectedHandler = Function.createDelegate(this, this._filterSourceSelected);
        this._quickFindHandlers = {
            'focus': this._quickFind_focus,
            'blur': this._quickFind_blur,
            'keydown': this._quickFind_keydown
        }
    },
    dispose: function() {
        if (!Sys.Application._disposing) this._detachBehaviors();
        this._stopValueChangedTimer();
        this._lookupField = null;
        this._headerDropDownOnShowingHandler = null;
        this._actionBarGroupOnShowingHandler = null;
        this._bodyKeydownHandler = null;
        this._filterSourceSelectedHandler = null;
        delete this._container;
        Web.DataView.callBaseMethod(this, 'dispose');
    },
    updated: function() {
        Web.DataView.callBaseMethod(this, 'updated');
        if (this.get_servicePath().startsWith('http'))
            this.set_baseUrl(this.get_siteUrl());
        var selectedValue = this.get_selectedValue();
        if (selectedValue.length > 0) {
            if (this.get_selectionMode() == Web.DataViewSelectionMode.Multiple)
                this._selectedKeyList = selectedValue.split(';');
            else {
                this._selectedKey = selectedValue.split(',');
                this._pendingSelectedEvent = true;
            }
        }
        if (this._container == null) {
            this.get_element().innerHTML = '';
            this._container = document.createElement('div');
            this.get_element().appendChild(this._container);
            Sys.UI.DomElement.addCssClass(this._container, 'DataViewContainer');
        }
        if (this.get_filterSource() && this.get_filterSource() != 'Context') {
            var source = Web.DataView.find(this.get_filterSource());
            if (source) {
                source.add_selected(this._filterSourceSelectedHandler);
                if (source._pendingSelectedEvent) {
                    this._source = source;
                    this._afterUpdateTimerId = window.setInterval(String.format('$find("{0}")._afterUpdate()', this.get_id()), 250);
                }
            }
            else {
                source = $get(this.get_filterSource());
                if (source) $addHandler(source, 'change', this._filterSourceSelectedHandler);
                this.set_domFilterSource(source);
            }
            this._createExternalFilter();
            if (!this._source) this.applyExternalFilter();
        }
        if (this.get_modalAnchor() && !this.get_isModal())
            this._initializeModalPopup();
        this.loadPage();
    },
    _afterUpdate: function() {
        if (this._delayedLoading || this._source._isBusy) return;
        window.clearInterval(this._afterUpdateTimerId);
        var source = this._source;
        this._source = null;
        this._filterSourceSelected(source, Sys.EventArgs.Empty, true);
    },
    loadPage: function(showWait) {
        this._showWait(!this.get_isDisplayed());
        if (this.get_mode() != Web.DataViewMode.View || (this.get_lookupField() || !(this._delayedLoading = !this.get_isDisplayed()))) {
            if (!this._source) this._loadPage();
        }
        else if (!Array.contains(Web.DataView._delayedLoadingViews, this))
            Array.add(Web.DataView._delayedLoadingViews, this);
    },
    get_isDisplayed: function() {
        var node = this.get_element().parentNode;
        while (node != null) {
            if (node.style && node.style.display == 'none')
                return false;
            node = node.parentNode;
        }
        return true;
    },
    goToPage: function(pageIndex) {
        this.set_pageIndex(pageIndex);
        this._loadPage();
    },
    sort: function(sortExpression) {
        this.set_sortExpression(sortExpression);
        this.set_pageIndex(0);
        this._loadPage();
    },
    applyFilterByIndex: function(fieldIndex, valueIndex) {
        var filterField = this._allFields[fieldIndex];
        var field = this.findFieldUnderAlias(filterField);
        this.applyFilter(filterField, valueIndex >= 0 ? '=' : null, valueIndex >= 0 ? field._listOfValues[valueIndex] : null);
    },
    findFieldUnderAlias: function(aliasField) {
        if (aliasField.Hidden)
            for (var i = 0; i < this._allFields.length; i++)
            if (this._allFields[i].AliasIndex == aliasField.Index) return this._allFields[i];
        return aliasField;
    },
    removeFromFilter: function(field) {
        for (var i = 0; i < this._filter.length; i++) {
            if (this._filter[i].match(/^(\w+):/)[1] == field.Name) {
                Array.removeAt(this._filter, i);
                break;
            }
        }
    },
    applyFilter: function(field, operator, value) {
        this.removeFromFilter(field);
        if (operator) Array.add(this._filter, field.Name + ':' + operator + this.convertFieldValueToString(field, value));
        var keepFieldValues = (this._filter.length == 1 && this._filter[0].match(/(\w+):/)[1] == field.Name);
        field = this.findFieldUnderAlias(field);
        for (i = 0; i < this._allFields.length; i++)
            if (!keepFieldValues || this._allFields[i].Name != field.Name) this._allFields[i]._listOfValues = null;
        this.set_pageIndex(-2);
        this._loadPage();
    },
    applyExternalFilter: function(preserveFilter) {
        if (!preserveFilter) this._filter = [];
        this._selectedRowIndex = null;
        for (var i = 0; i < this._externalFilter.length; i++) {
            var filterItem = this._externalFilter[i];
            if (preserveFilter) {
                for (var j = 0; j < this._filter.length; j++) {
                    if (this._filter[j].startsWith(filterItem.Name + ':=')) {
                        Array.removeAt(this._filter, j);
                        break;
                    }
                }
            }
            Array.add(this._filter, filterItem.Name + ':=' + filterItem.Value);
        }
    },
    showCustomFilter: function(fieldIndex) {
        var field = this._allFields[fieldIndex];
        var customFilter = null;
        for (var i = 0; i < this._filter.length; i++) {
            var m = this._filter[i].match(/(\w+):([\s\S]*)/);
            if (m[1] == field.Name) {
                customFilter = m[2];
                break;
            }
        }
        if (customFilter && customFilter.indexOf('\0') == -1) customFilter += '\0';
        var panel = this._customFilterPanel = document.createElement('div');
        this.get_element().appendChild(panel);
        panel.className = 'CustomFilterDialog';
        panel.id = this.get_id() + '_CustomFilterPanel';
        var sb = new Sys.StringBuilder();
        sb.appendFormat('<div>{0}</div>', String.format(Web.DataViewResources.HeaderFilter.CustomFilterPrompt, this.get_view().Label, field.Label));
        sb.append('<table cellpadding="0" cellspacing="0">');
        sb.appendFormat('<tr><td colspan="2"><input type="text" id="{0}_Query" size="70" value="{1}"></input></td></tr>', this.get_id(), customFilter ? Web.DataView.htmlAttributeEncode(customFilter.replace(/\0/g, ', ').replace(/\*|[^<>]=|^=|, $/g, '')) : '');
        sb.appendFormat('<tr><td></td><td align="right"><button id="{0}Ok">OK</button> <button id="{0}Cancel">Cancel</button></td></tr>', this.get_id());
        sb.append('</table>');
        panel.innerHTML = sb.toString();
        sb.clear();
        this._customFilterField = field;
        this._customFilterModalPopupBehavior = $create(AjaxControlToolkit.ModalPopupBehavior, {
            OkControlID: this.get_id() + 'Ok', CancelControlID: this.get_id() + 'Cancel', OnOkScript: String.format('$find("{0}").applyCustomFilter()', this.get_id()), OnCancelScript: String.format('$find("{0}").closeCustomFilter()', this.get_id()),
            PopupControlID: panel.id, DropShadow: true, BackgroundCssClass: 'ModalBackground'
        }, null, null, $get(this.get_id() + '_CustomFilterOption' + fieldIndex));
        this._customFilterModalPopupBehavior.show();
        $addHandler(document.body, 'keydown', this._bodyKeydownHandler);
        $get(this.get_id() + '_Query').focus();
    },
    applyCustomFilter: function() {
        this.removeFromFilter(this._customFilterField);
        var iterator = /\s*(=|<={0,1}|>={0,1}|)\s*([\S\s]+?)\s*(,|$)/g;
        var filter = this._customFilterField.Name + ':';
        var s = $get(this.get_id() + '_Query').value;
        var match = iterator.exec(s);
        while (match) {
            filter += (match[1] ? match[1] : (this._customFilterField.Type == 'String' ? '*' : '=')) + match[2] + '\0';
            match = iterator.exec(s);
        }
        if (filter.indexOf('\0') > 0) Array.add(this._filter, filter);
        this.set_pageIndex(-2);
        this._loadPage();
        this.closeCustomFilter();
    },
    closeCustomFilter: function() {
        if (this._customFilterModalPopupBehavior) {
            this._customFilterModalPopupBehavior.dispose();
            this._customFilterModalPopupBehavior = null;
            this._customFilterField = null;
        }
        if (this._customFilterPanel) {
            this.get_element().removeChild(this._customFilterPanel);
            delete this._customFilterPanel;
        }
        $removeHandler(document.body, 'keydown', this._bodyKeydownHandler);
    },
    convertFieldValueToString: function(field, value) {
        return field.Type == 'DateTime' && field.DataFormatString && field.DataFormatString.length > 0 ? (value == null ? 'null' : String.localeFormat(field.DataFormatString, value)) : value;
    },
    goToView: function(viewId) {
        if (viewId == 'form')
            for (var i = 0; i < this.get_views().length; i++)
            if (this.get_views()[i].Type == 'Form') {
            viewId = this.get_views()[i].Id;
            break;
        }
        Web.DataView.hideMessage();
        this._detachBehaviors();
        if (this.get_view().Type != 'Form') {
            this._lastViewId = this.get_viewId();
            this._selectedRowIndex = 0;
        }
        this.set_viewId(viewId);
        if (this.get_view().Type != 'Form') this._lastViewId = viewId;
        this.set_pageIndex(-1);
        this.set_filter(this.get_view().Type == 'Form' ? this.get_selectedKeyFilter() : []);
        this.set_sortExpression(null);
        this._loadPage();
        this.raiseSelected();
    },
    filterOf: function(field) {
        var header = (field.AliasName && field.AliasName.length > 0 ? field.AliasName : field.Name) + ':';
        for (var i = 0; i < this._filter.length; i++)
            if (this._filter[i].startsWith(header))
            return this._filter[i].substr(header.length);
        return null;
    },
    findField: function(query) {
        for (var i = 0; i < this._allFields.length; i++) {
            var field = this._allFields[i];
            if (field.Name == query) return field;
        }
        return null;
    },
    findCategory: function(query) {
        for (var i = 0; i < this._categories.length; i++) {
            var c = this._categories[i];
            if (c.HeaderText == query) return c;
        }
        return null;
    },
    _isInInstantDetailsMode: function() {
        return window.location.href.match(/(\?|&)l=.+(&|$)/);
    },
    _closeInstantDetails: function() {
        if (this._isInInstantDetailsMode()) {
            if (Web.DataViewResources.Lookup.ShowDetailsInPopup) {
                window.close();
                return true;
            }
        }
        return false;
    },
    executeAction: function(scope, actionIndex, rowIndex, groupIndex) {
        if (this._isBusy) return;
        Web.DataView.hideMessage();
        var actions = this.get_lookupField() ? null : (scope == 'ActionBar' ? this.get_actionGroups(scope)[groupIndex].Actions : this.get_actions(scope));
        if (actionIndex < 0 && actions) {
            for (var i = 0; i < actions.length; i++)
                if (this._isActionAvailable(actions[i], rowIndex)) {
                actionIndex = i;
                break;
            }
            if (actionIndex < 0) return;
        }
        var action = actions ? actions[actionIndex] : null;
        if (action && action.Confirmation && action.Confirmation.length > 0 && !confirm(action.Confirmation)) return;
        var command = action ? action.CommandName : 'Select';
        var argument = action ? action.CommandArgument : null;
        var causesValidation = action ? action.CausesValidation : true;
        this.executeRowCommand(rowIndex, command, argument, causesValidation);
    },
    executeRowCommand: function(rowIndex, command, argument, causesValidation) {
        if (rowIndex != null && rowIndex >= 0) {
            this._selectedRowIndex = rowIndex;
            this._selectKeyByRowIndex(rowIndex);
        }
        this.executeCommand({ commandName: command, commandArgument: argument ? argument : '', causesValidation: causesValidation ? true : false });
        if (command == 'Select' && argument == null && this.get_view().Type != 'Grid') this._render();
    },
    _get_dataRequestForm: function() {
        var f = $get('_dataRequest_form');
        if (!f) {
            f = document.createElement('form');
            f.id = '_dataRequest_form';
            f.method = 'post';
            f.innerHTML = '<input type="hidden" name="q" id="q"/><input type="hidden" name="c" id="c"/><input type="hidden" name="a" id="a"/>';
            document.body.appendChild(f);
        }
        return f;
    },
    executeReport: function(args) {
        var f = this._get_dataRequestForm();
        f.action = this.resolveClientUrl('~/Report.ashx');
        $get('c', f).value = args.commandName;
        $get('a', f).value = args.commandArgument;
        var q = this._createParams();
        q.Controller = this.get_controller();
        q.View = this.get_viewId();
        $get('q', f).value = Sys.Serialization.JavaScriptSerializer.serialize(q);
        f.submit();
    },
    executeExport: function(args) {
        var f = this._get_dataRequestForm();
        f.target = args.commandName == 'ExportRss' ? '_blank' : '';
        f.action = this.resolveClientUrl('~/Export.ashx');
        var q = this._createParams();
        args.Controller = this.get_controller();
        args.View = this.get_viewId();
        args.Filter = q.Filter;
        args.SortExpression = q.SortExpression;
        $get('c', f).value = args.commandName;
        $get('a', f).value = args.commandArgument;
        $get('q', f).value = Sys.Serialization.JavaScriptSerializer.serialize(args);
        f.submit();
    },
    executeCommand: function(args) {
        this._hidePopups();
        if (this._isBusy) return;
        switch (args.commandName) {
            case 'Select':
                this.set_lastCommandName(args.commandName);
                this.set_lastCommandArgument(args.commandArgument);
                if (this.get_lookupField() && args.commandArgument == '') {
                    var values = [];
                    var labels = [];
                    var dataValueField = this.findField(this.get_lookupField().ItemsDataValueField);
                    var dataTextField = this.findField(this.get_lookupField().ItemsDataTextField);
                    if (dataValueField != null) Array.add(values, this.get_selectedRow()[dataValueField.Index]);
                    if (dataTextField != null) Array.add(labels, this.get_selectedRow()[dataTextField.Index]);
                    if (!dataValueField) {
                        for (var i = 0; i < this._allFields.length; i++) {
                            if (this._allFields[i].IsPrimaryKey)
                                Array.add(values, this.get_selectedRow()[this._allFields[i].Index]);
                        }
                    }
                    if (!dataTextField) {
                        for (i = 0; i < values.length; i++) {
                            if (i < this.get_fields().length)
                                Array.add(labels, this.get_selectedRow()[this.get_fields()[i].AliasIndex]);
                        }
                    }
                    this.get_lookupField()._dataView.changeLookupValue(this.get_lookupField().Index, values.length == 1 ? values[0] : values, labels.join(';'));
                }
                else {
                    for (i = 0; i < this.get_rows().length; i++) {
                        var row = $get(this.get_id() + '_Row' + i);
                        if (row)
                            if (i == this._selectedRowIndex)
                            Sys.UI.DomElement.addCssClass(row, 'Selected');
                        else
                            Sys.UI.DomElement.removeCssClass(row, 'Selected');
                    }
                    if (args.commandArgument.length > 0)
                        this.goToView(args.commandArgument);
                }
                break;
            case 'Edit':
            case 'New':
                this.set_lastCommandName(args.commandName);
                this.set_lastCommandArgument(args.commandArgument);
                if (args.commandArgument.length > 0)
                    this.goToView(args.commandArgument);
                else
                    this._render();
                if (args.commandName == 'New') {
                    Array.clear(this._selectedKey);
                    this.raiseSelected();
                }
                break;
            case 'Navigate':
                this.navigate(args.commandArgument);
                break;
            case 'Cancel':
                if (this._closeInstantDetails()) { }
                else if (this.endModalState('Cancel')) return;
                else if (this.get_backOnCancel())
                    history.go(-1);
                else {
                    this.set_lastCommandName(null);
                    if (this.get_view().Type == 'Form')
                        this.goToView(this._lastViewId);
                    else
                        this._render();
                }
                break;
            case 'Back':
                history.go(!String.isNullOrEmpty(args.commandArgument) ? parseInt(args.commandArgument) : -1);
                break;
            case 'Report':
            case 'ReportAsPdf':
            case 'ReportAsImage':
            case 'ReportAsExcel':
                this.executeReport(args);
                break;
            case 'ExportCsv':
            case 'ExportRowset':
            case 'ExportRss':
                this.executeExport(args);
                break;
            case '_ViewDetails':
                var f = this.findField(args.commandArgument);
                if (f) {
                    var keyFieldName = f.Name;
                    if (f.ItemsDataController == this.get_controller())
                        for (i = 0; i < this._allFields.length; i++) {
                        if (this._allFields[i].IsPrimaryKey) {
                            keyFieldName = this._allFields[i].Name;
                            break;
                        }
                    }
                    var link = String.format('{0}&{1}={2}', f.ItemsDataController, f.ItemsDataValueField && f.ItemsDataValueField.length > 0 ? f.ItemsDataValueField : keyFieldName, this.get_selectedRow()[f.Index]);
                    if (Web.DataViewResources.Lookup.ShowDetailsInPopup)
                        window.open(this.resolveClientUrl(String.format('~/{0}?l={1}', Web.DataView.DetailsHandler, encodeURIComponent(link))), '_blank', 'scrollbars=yes,height=100,resizable=yes');
                    else
                        window.location.href = this.resolveClientUrl(String.format('~/{0}?l={1}', Web.DataView.DetailsHandler, encodeURIComponent(link)));
                }
                break;
            default:
                values = this._collectFieldValues();
                if (this._validateFieldValues(values, args.causesValidation == null || args.causesValidation))
                    this._execute({ CommandName: args.commandName, CommandArgument: args.commandArgument, LastCommandName: this.get_lastCommandName(), Values: values, ContextKey: this.get_id(), Cookie: this.get_cookie(), Controller: this.get_controller(), View: this.get_viewId() });
                break;

        }
    },
    navigate: function(location, values) {
        if (location) location = this.resolveClientUrl(location);
        if (location) {
            var iterator = /([\s\S]*?)\{(\w+)?\}/g;
            var formattedLocation = '';
            var lastIndex = -1;
            var match = iterator.exec(location);
            while (match) {
                formattedLocation += match[1];
                if (values && this._lastArgs) {
                    for (var i = 0; i < values.length; i++) {
                        var v = values[i];
                        if (v.Name == match[2]) {
                            formattedLocation += this._lastArgs.CommandName.match(/Insert/i) ? v.NewValue : v.OldValue;
                            break;
                        }
                    }
                }
                else {
                    var field = match[2].match(/^\d+$/) ? this.get_fields()[parseInt(match[2])] : this.findField(match[2]);
                    formattedLocation += field ? encodeURIComponent(this.get_selectedRow()[field.Index]) : '';
                }
                lastIndex = iterator.lastIndex;
                match = iterator.exec(location);
            }
            if (lastIndex != -1) location = formattedLocation + (lastIndex < location.length ? location.substr(lastIndex) : '');
        }
        var targetView = null;
        for (i = 0; i < this.get_views().length; i++)
            if (this.get_views()[i].Id == location) {
            targetView = this.get_views()[i];
            break;
        }
        if (targetView)
            this.goToView(location);
        else {
            Web.DataView._navigated = true;
            window.location.href = location;
        }
    },
    showLookup: function(fieldIndex) {
        if (!this.get_enabled()) return;
        var field = this._allFields[fieldIndex];
        if (!field._lookupModalBehavior) {
            var showLink = $get(this.get_id() + '_Item' + field.Index + '_ShowLookupLink');
            if (showLink) {
                var panel = field._lookupModalPanel = document.createElement('div');
                this.get_element().appendChild(panel);
                panel.className = 'ModalPanel';
                panel.id = this.get_id() + '_ItemLookupPanel' + field.Index;
                panel.innerHTML = String.format('<table style="width:100%;height:100%"><tr><td valign="middle" align="center"><table cellpadding="0" cellspacing="0"><tr><td class="ModalTop"><div style="height:1px;font-size:1px"></div></td><td><div style="height:1px;font-size:1px"></div></td></tr><tr><td align="left" valign="top" id="{0}_ItemLookupPlaceholder{1}"  class="ModalPlaceholder"></td><td class="RightSideShadow"></td></tr><tr><td colspan="2"><div class="BottomShadow"></div></td></tr></table></td></tr></table>', this.get_id(), field.Index);
                field._lookupModalBehavior = $create(AjaxControlToolkit.ModalPopupBehavior, { id: this.get_id() + "_ItemLookup" + field.Index, PopupControlID: panel.id, BackgroundCssClass: 'ModalBackground' }, null, null, showLink);
            }
        }
        else
            field._lookupDataControllerBehavior._render();
        var contextFilter = [];
        if (field.ContextFields && field.ContextFields.length > 0) {
            var contextValues = this._collectFieldValues();
            var iterator = /(\w+)(=(\w+)){0,1}(,|$)/g;
            var m = iterator.exec(field.ContextFields);
            while (m) {
                var f = this.findField(m[3] && m[3].length > 0 ? m[3] : m[1]);
                if (f) {
                    for (var j = 0; j < contextValues.length; j++) {
                        if (contextValues[j].Name == f.Name) {
                            var v = contextValues[j];
                            var fieldValue = v.Modified ? v.NewValue : v.OldValue;
                            Array.add(contextFilter, { 'Name': m[1], 'Value': fieldValue });
                            break;
                        }
                    }
                }
                m = iterator.exec(field.ContextFields);
            }
        }
        if (!field._lookupDataControllerBehavior)
            field._lookupDataControllerBehavior = $create(Web.DataView, { id: this.get_id() + '_LookupView' + fieldIndex, baseUrl: this.get_baseUrl(), pageSize: Web.DataViewResources.Pager.PageSizes[0], servicePath: this.get_servicePath(), controller: field.ItemsDataController, showActionBar: Web.DataViewResources.Lookup.ShowActionBar, lookupField: field, externalFilter: contextFilter, filterSource: contextFilter.length > 0 ? 'Context' : null }, null, null, $get(this.get_id() + '_ItemLookupPlaceholder' + field.Index));
        else if (contextFilter.length > 0) {
            field._lookupDataControllerBehavior.set_externalFilter(contextFilter);
            field._lookupDataControllerBehavior.goToPage(-1);
        }
        this._saveTabIndexes();
        field._lookupModalBehavior.show();
        $addHandler(document.body, 'keydown', field._lookupDataControllerBehavior._bodyKeydownHandler);
        field._lookupDataControllerBehavior._adjustLookupSize();
    },
    changeLookupValue: function(fieldIndex, value, text) {
        var field = this._allFields[fieldIndex];
        this._closeLookup(field);
        this._restoreTabIndexes();
        var itemId = this.get_id() + '_Item' + fieldIndex;
        Sys.UI.DomElement.setVisible($get(itemId + '_ClearLookupLink'), true);
        $get(itemId + '_ShowLookupLink').innerHTML = this.htmlEncode(field, text);
        $get(itemId + '_ShowLookupLink').focus();
        $get(itemId).value = value;
        this._updateLookupInfo(value, text);
    },
    clearLookupValue: function(fieldIndex) {
        var itemId = this.get_id() + '_Item' + fieldIndex;
        Sys.UI.DomElement.setVisible($get(itemId + '_ClearLookupLink'), false);
        $get(itemId + '_ShowLookupLink').innerHTML = Web.DataViewResources.Lookup.SelectLink;
        $get(itemId + '_ShowLookupLink').focus();
        $get(itemId).value = '';
        this._updateLookupInfo('', Web.DataViewResources.Lookup.SelectLink);
    },
    _updateLookupInfo: function(value, text) {
        var lookupText = $get(this.get_id() + '_Text0');
        if (lookupText) {
            lookupText.value = text;
            lookupText.name = lookupText.id;
            var lookupValue = $get(this.get_id() + '_Item0');
            lookupValue.value = value;
            lookupValue.name = lookupValue.id;
            if (this.get_lookupPostBackExpression()) {
                var prm = Sys.WebForms.PageRequestManager.getInstance();
                if (prm)
                    eval("Sys.WebForms.PageRequestManager.getInstance()._doPostBack" + this.get_lookupPostBackExpression().match(/\w+(.+)/)[1]);
                else
                    eval(this.get_lookupPostBackExpression());
            }
        }
        else
            this._valueChanged();
    },
    createNewLookupValue: function(fieldIndex) {
        var field = this._newLookupValueField = this._allFields[fieldIndex];
        this._createNewView = Web.DataView.showModal($get(String.format('{0}_Item{1}_CreateNewLookupLink', this.get_id(), field.Index)), field.ItemsDataController, field.ItemsNewDataView, 'New', field.ItemsNewDataView, this.get_baseUrl(), this.get_servicePath());
        this._createNewView.add_executed(Function.createDelegate(this, this._saveNewLookupValueCompleted));
    },
    _saveNewLookupValueCompleted: function(sender, args) {
        if (args.result.Errors.length > 0) return;
        args.handled = true;
        Web.DataView.hideMessage();
        var v = null;
        if (args.result.Values.length == 0) args.result.Values = sender._lastArgs.Values;
        for (var j = 0; j < args.result.Values.length; j++)
            if (args.result.Values[j].Name == sender._keyFields[0].Name) {
            v = args.result.Values[j].NewValue;
            break;
        }
        var t = null;
        for (i = 0; i < sender._lastArgs.Values.length; i++) {
            if (sender._lastArgs.Values[i].Name == sender._fields[0].Name) {
                t = sender._lastArgs.Values[i].NewValue;
                break;
            }
        }
        if (this._newLookupValueField._lookupDataControllerBehavior) this._newLookupValueField._lookupDataControllerBehavior.goToPage(-1);
        this._createNewView.endModalState('Cancel');
        this.changeLookupValue(this._newLookupValueField.Index, v, t);
    },
    hideLookup: function(fieldIndex) {
        var field = fieldIndex ? this._allFields[fieldIndex] : this.get_lookupField();
        this._closeLookup(field);
        this.get_lookupField()._dataView._restoreTabIndexes();
        $get(this.get_lookupField()._dataView.get_id() + '_Item' + field.Index + '_ShowLookupLink').focus();
    },
    closeLookupAndCreateNew: function() {
        this.hideLookup();
        var field = this.get_lookupField();
        field._dataView.createNewLookupValue(field.Index);
    },
    htmlEncode: function(field, s) { return this._allFields[field.AliasIndex].Type == 'String' ? Web.DataView.htmlEncode(s) : s; },
    filterIsExternal: function() {
        if (this._externalFilter.length == 0) return false;
        for (var i = 0; i < this._filter.length; i++) {
            var name = this._filter[i].match(/(\w+):/)[1];
            var found = false;
            for (var j = 0; j < this._externalFilter.length; j++)
                if (this._externalFilter[j].Name == name) {
                found = true;
                break;
            }
            if (!found) return false;
        }
        return true;
    },
    add_selected: function(handler) {
        this.get_events().addHandler('selected', handler);
    },
    remove_selected: function(handler) {
        this.get_events().removeHandler('selected', handler);
    },
    raiseSelected: function(eventArgs) {
        var handler = this.get_events().getHandler('selected');
        if (handler) handler(this, Sys.EventArgs.Empty);
        if (this.get_selectionMode() != Web.DataViewSelectionMode.Multiple)
            this.set_selectedValue(this.get_selectedKey());
    },
    add_executed: function(handler) {
        this.get_events().addHandler('executed', handler);
    },
    remove_executed: function(handler) {
        this.get_events().removeHandler('executed', handler);
    },
    raiseExecuted: function(eventArgs) {
        var handler = this.get_events().getHandler('executed');
        if (handler) handler(this, eventArgs);
    },
    _closeLookup: function(field) {
        if (field && field._lookupModalBehavior) {
            field._lookupModalBehavior.hide();
            $removeHandler(document.body, 'keydown', field._lookupDataControllerBehavior._bodyKeydownHandler);
        }
    },
    _collectFieldValues: function() {
        var values = new Array();
        var selectedRow = this.get_selectedRow();
        if (!selectedRow && !this.get_isInserting()) return values;
        for (var i = 0; i < this._allFields.length; i++) {
            var field = this._allFields[i];
            var element = $get(this.get_id() + '_Item' + i);
            if (field.Items.length > 0) {
                if (field.ItemsStyle == 'RadioButtonList') {
                    for (var j = 0; j < field.Items.length; j++) {
                        var option = $get(this.get_id() + '_Item' + i + '_' + j);
                        if (option && option.checked) {
                            element = option;
                            break;
                        }
                    }
                }
                else if (field.ItemsStyle == 'CheckBoxList' && element) {
                    element.value = '';
                    for (j = 0; j < field.Items.length; j++) {
                        option = $get(this.get_id() + '_Item' + i + '_' + j);
                        if (option && option.checked) {
                            if (element.value.length > 0) element.value += ',';
                            element.value += option.value;
                        }
                    }
                }
            }
            if (element || field.IsPrimaryKey || !field.ReadOnly)
                Array.add(values, { Name: field.Name, OldValue: this.get_isInserting() ? (this._newRow ? this._newRow[field.Index] : null) : selectedRow[field.Index], NewValue: element && element.value ? (field.Type == 'Boolean' ? element.value == 'true' : element.value) : null, Modified: element != null });
        }
        for (i = 0; i < this._externalFilter.length; i++) {
            var filterItem = this._externalFilter[i];
            for (j = 0; j < values.length; j++)
                if (values[j].Name.toLowerCase() == filterItem.Name.toLowerCase() && values[j].NewValue == null) {
                values[j].NewValue = filterItem.Value;
                values[j].Modified = true;
                break;
            }
        }
        return values;
    },
    _enumerateExpressions: function(type, scope, target) {
        var l = [];
        if (this._expressions) {
            for (var i = 0; i < this._expressions.length; i++) {
                var e = this._expressions[i];
                if (e.Scope == scope && (type == Web.DynamicExpressionType.Any || e.Type == Web.DynamicExpressionType.RegularExpression) && e.Target == target)
                    Array.add(l, e);
            }
        }
        return l;
    },
    _prepareJavaScriptExpression: function(expression) {
        if (!expression._variables) {
            var vars = [];
            var re = /\[(\w+)\]/g;
            var m = re.exec(expression.Test);
            while (m) {
                var found = false;
                for (var i = 0; i < vars.length; i++) {
                    if (vars[i].name == m[1]) {
                        found = true;
                        break;
                    }
                }
                if (!found) Array.add(vars, { 'name': m[1], 'regex': new RegExp('\\[' + m[1] + '\\]', 'g') });
                m = re.exec(expression.Test);
            }
            expression._variables = vars;
        }
    },
    _evaluateJavaScriptExpressions: function(expressions, row, concatenateResult) {
        var result = concatenateResult ? '' : null;
        for (var i = 0; i < expressions.length; i++) {
            var exp = expressions[i];
            if (exp.Type == Web.DynamicExpressionType.ClientScript) {
                this._prepareJavaScriptExpression(exp);
                var script = exp.Test;
                for (var j = 0; j < exp._variables.length; j++) {
                    var v = exp._variables[j];
                    var f = this.findField(v.name);
                    if (f) {
                        var o = row[f.Index];
                        if (String.isInstanceOfType(o))
                            o = '\'' + o.toString().replace('\'', '\\\'') + '\'';
                        else if (Date.isInstanceOfType(o))
                            o = 'parseDate(\'' + o + '\')';
                        script = script.replace(v.regex, o);
                    }
                    else {
                        script = null;
                        break;
                    }
                }
                if (script) {
                    try {
                        var r = eval(script);
                        if (concatenateResult) {
                            if (r) {
                                if (result == null) result = exp.Result;
                                else result += ' ' + exp.Result;
                            }
                        }
                        else
                            return exp.Result == null ? r : exp.Result;
                    }
                    catch (er) {
                    }
                }
            }
        }
        return result;
    },
    _validateFieldValues: function(values, displayErrors) {
        var valid = true;
        var sb = new Sys.StringBuilder();
        for (var i = 0; i < values.length; i++) {
            var v = values[i];
            var field = this.findField(v.Name);
            if (field.Type == 'DateTime' && v.OldValue != null) v.OldValue = new Date(v.OldValue - v.OldValue.getTimezoneOffset() * 60 * 1000);
            var error = null;
            if (v.Modified) {
                // see if the field is blank
                if (!field.AllowNulls && (!field.HasDefaultValue || Web.DataViewResources.Validator.EnforceRequiredFieldsWithDefaultValue))
                    if (!v.NewValue || v.NewValue.toString().match(/^\s*$/))
                    error = Web.DataViewResources.Validator.RequiredField;
                // convert blank values to "null"
                if (!error && v.NewValue && v.NewValue.toString().match(/^\s*$/))
                    v.NewValue = null;
                // convert to the "typed" value
                if (!error && v.NewValue != null) {
                    switch (field.Type) {
                        case 'SByte':
                        case 'Byte':
                        case 'Int16':
                        case 'Int32':
                        case 'UInt32':
                        case 'Int64':
                        case 'Single':
                        case 'Double':
                        case 'Decimal':
                            var newValue = v.NewValue && typeof (v.NewValue) == 'string' ? Number.parseLocale(v.NewValue.replace(Sys.CultureInfo.CurrentCulture.numberFormat.CurrencySymbol, '')) : v.NewValue;
                            if (String.format('{0}', newValue) == 'NaN')
                                error = Web.DataViewResources.Validator.NumberIsExpected;
                            else
                                v.NewValue = newValue;
                            break;
                        case 'Boolean':
                            try {
                                v.NewValue = String.isInstanceOfType(v.NewValue) ? Boolean.parse(v.NewValue) : v.NewValue;
                            }
                            catch (e) {
                                error = Web.DataViewResources.Validator.BooleanIsExpected;
                            }
                            break;
                        case 'DateTime':
                            newValue = field.DataFormatString && field.DataFormatString.length ? Date.parseLocale(v.NewValue, field.DataFormatString.match(/\{0:([\s\S]*?)\}/)[1]) : Date.parse(v.NewValue);
                            if (!newValue)
                                error = Web.DataViewResources.Validator.DateIsExpected;
                            else
                                v.NewValue = newValue;
                            if (!error && v.NewValue != null) v.NewValue = new Date(v.NewValue - v.NewValue.getTimezoneOffset() * 60 * 1000);
                            break;
                    }
                }
                if (!error) {
                    var expressions = this._enumerateExpressions(Web.DynamicExpressionType.RegularExpression, Web.DynamicExpressionScope.Field, v.Name);
                    for (var j = 0; j < expressions.length; j++) {
                        var exp = expressions[j];
                        var s = v.NewValue ? v.NewValue : '';
                        try {
                            var re = new RegExp(exp.Test);
                            var m = re.exec(s);
                            if (exp.Result.match(/\$(\d|\'\`)/)) {
                                if (m) v.NewValue = s.replace(re, exp.Result);
                            }
                            else {
                                if (!m) error = error ? error += exp.Result : exp.Result;
                            }
                        }
                        catch (ex) {
                        }
                    }
                }
                // see if the value has been modified
                v.Modified = field.Type == 'DateTime' ? ((v.NewValue == null ? null : v.NewValue.toString()) != (v.OldValue == null ? null : v.OldValue.toString())) : v.NewValue != v.OldValue;
            }
            // display/hide the error as needed
            var errorElement = $get(this.get_id() + '_Item' + field.Index + '_Error');
            if (errorElement && displayErrors) {
                Sys.UI.DomElement.setVisible(errorElement, error != null);
                errorElement.innerHTML = error;
            }
            if (error) {
                if (valid) {
                    var element = $get(this.get_id() + '_Item' + field.Index);
                    if (element) try { element.focus(); } catch (ex) { }
                }
                valid = false;
                if (!errorElement) sb.append(Web.DataView.formatMessage('Attention', field.Label + ": " + error));
            }
        }
        if (!displayErrors) valid = true;
        if (!valid) Web.DataView.showMessage(sb.toString());
        sb.clear();
        return valid;
    },
    _fieldIsInExternalFilter: function(field) {
        return this._findExternalFilterItem(field) != null;
    },
    _findExternalFilterItem: function(field) {
        for (var i = 0; i < this._externalFilter.length; i++) {
            var filterItem = this._externalFilter[i];
            if (field.Name.toLowerCase() == filterItem.Name.toLowerCase())
                return filterItem;
        }
        return null;
    },
    _focus: function(fieldName, message) {
        if (message) {
            for (var i = 0; i < this.get_fields().length; i++) {
                var field = this.get_fields()[i];
                var error = $get(this.get_id() + '_Item' + field.Index + '_Error');
                if (error) Sys.UI.DomElement.setVisible(error, false);
            }
        }
        for (i = 0; i < this.get_fields().length; i++) {
            field = this.get_fields()[i];
            if (!field.ReadOnly && (fieldName == null || field.Name == fieldName)) {
                var element = $get(this.get_id() + '_Item' + field.Index);
                var c = $get(String.format('{0}_ItemContainer{1}', this.get_id(), field.Index));
                if (element && (!c || Sys.UI.DomElement.getVisible(c))) {
                    try {
                        if (message) {
                            error = $get(this.get_id() + '_Item' + field.Index + '_Error');
                            if (error) {
                                error.innerHTML = message;
                                Sys.UI.DomElement.setVisible(error, true);
                            }
                        }
                        element.select();
                        element.focus();
                    } catch (ex) { }
                }
                break;
            }
        }
    },
    _saveTabIndexes: function() {
        this._lastSavedTabIndexes = this._savedTabIndexes;
        this._savedTabIndexes = [];
        for (var i = 0; i < Web.DataView._tagsWithIndexes.length; i++) {
            var tags = document.getElementsByTagName(Web.DataView._tagsWithIndexes[i]);
            for (var j = 0; j < tags.length; j++) {
                var elem = tags[j];
                if (elem)
                    Array.add(this._savedTabIndexes, { element: elem, tabIndex: elem.tabIndex });
            }
            delete tags;
        }
    },
    _restoreTabIndexes: function() {
        if (this._savedTabIndexes) {
            for (var i = 0; i < this._savedTabIndexes.length; i++) {
                this._savedTabIndexes[i].element.tabIndex = this._savedTabIndexes[i].tabIndex;
                delete this._savedTabIndexes[i].element;
            }
            Array.clear(this._savedTabIndexes);
        }
        this._savedTabIndexes = this._lastSavedTabIndexes;
        this._lastSavedTabIndexes = null;
    },
    _selectKeyByRowIndex: function(rowIndex) {
        var oldKey = this._selectedKey;
        this._selectedKey = [];
        this._selectedKeyFilter = []
        for (var i = 0; i < this._keyFields.length; i++) {
            var field = this._keyFields[i];
            Array.add(this._selectedKey, this._rows[rowIndex][field.Index]);
            Array.add(this._selectedKeyFilter, field.Name + ':=' + this.convertFieldValueToString(field, this._rows[rowIndex][field.Index]));
            if (oldKey && (oldKey.length < i || (oldKey[i] != this._selectedKey[i]))) oldKey = null;
        }
        if (!oldKey) this.raiseSelected();
    },
    _showWait: function(force) {
        if (this.get_fields() == null || force)
            this._container.innerHTML = Web.DataViewResources.Common.WaitHtml;
        else {
            var wait = $get(this.get_id() + '_Wait');
            if (wait) {
                this._oldWaitHTML = wait.innerHTML;
                wait.innerHTML = Web.DataViewResources.Common.WaitHtml;
            }
        }
    },
    _hideWait: function() {
        if (this._oldWaitHTML) {
            var waitElement = $get(this.get_id() + '_Wait');
            if (waitElement) waitElement.innerHTML = this._oldWaitHTML;
        }
    },
    _get_colSpan: function() {
        return this.get_view().Type == 'Form' ? 2 : this.get_fields().length + (this._selectionMode == Web.DataViewSelectionMode.Multiple ? 1 : 0);
    },
    _renderCreateNewBegin: function(sb, field) { if (!String.isNullOrEmpty(field.ItemsNewDataView)) sb.append('<table cellpadding="0" cellspacing="0"><tr><td>'); },
    _renderCreateNewEnd: function(sb, field) {
        if (!String.isNullOrEmpty(field.ItemsNewDataView)) {
            sb.append('</td><td>');
            if (this.get_enabled())
                sb.appendFormat('<a href="#" class="CreateNew" onclick="$find(\'{0}\').createNewLookupValue({1});return false" id="{0}_Item{1}_CreateNewLookupLink" title="{2}"{3}>&nbsp;</a>',
                    this.get_id(), field.Index, String.format(Web.DataViewResources.Lookup.NewToolTip, field.Label), this._tabIndex > 0 ? String.format(' tabindex="{0}"', this._tabIndex++) : '');
            sb.append('</td></tr></table>');
        }
    },
    _render: function() {
        var sb = new Sys.StringBuilder();
        if (this.get_mode() == Web.DataViewMode.Lookup) {
            var field = this._fields[0];
            var v = this.get_lookupText();
            if (v == null) v = Web.DataViewResources.Lookup.SelectLink;
            var s = field.DataFormatString && field.DataFormatString.length > 0 ? String.localeFormat(field.DataFormatString, v) : v.toString();
            this._renderCreateNewBegin(sb, field);
            sb.appendFormat('<table cellpadding="0" cellspacing="0" class="DataViewLookup"><tr><td><a href="#" onclick="$find(\'{0}\').showLookup({1});return false" id="{0}_Item{1}_ShowLookupLink" title="{3}" tabindex="{7}"{8}>{2}</a><a href="#" class="Clear" onclick="$find(\'{0}\').clearLookupValue({1});return false" id="{0}_Item{1}_ClearLookupLink" title="{5}" tabindex="{7}">&nbsp;</a></td></tr></table><input type="hidden" id="{0}_Item{1}" value="{4}"/><input type="hidden" id="{0}_Text{1}" value="{6}"/>',
                this.get_id(), field.Index, this.htmlEncode(field, s), String.format(Web.DataViewResources.Lookup.SelectToolTip, field.Label), this.get_lookupValue(), String.format(Web.DataViewResources.Lookup.ClearToolTip, field.Label), Web.DataView.htmlAttributeEncode(s), this._tabIndex, this.get_enabled() ? '' : ' disabled="true" class="Disabled"');
            this._renderCreateNewEnd(sb, field);
            this.get_element().appendChild(this._container);
            this._container.innerHTML = sb.toString();
            if (this.get_lookupValue() == '' || !this.get_enabled()) $get(this.get_id() + '_Item0_ClearLookupLink').style.display = 'none';
        }
        else {
            sb.appendFormat('<table class="DataView {1}_{2}" cellpadding="0" cellspacing="0"{0}>', this.get_isModal() ? String.format(' style="width:{0}px"', this._container.offsetWidth - 20) : '', this.get_controller(), this.get_viewId());
            if (this.get_view().Type == 'Form')
                this._renderFormView(sb);
            else
                this._renderGridView(sb);
            sb.append('</table>');
            this._container.innerHTML = sb.toString();
            this._attachBehaviors();
            this._updateVisibility();
            if (this.get_isEditing()) this._focus();
        }
        sb.clear();
    },
    _renderFormView: function(sb) {
        this._renderViewDescription(sb);
        if (Web.DataViewResources.Form.ShowActionBar) this._renderActionBar(sb);
        var row = this.get_isInserting() ? (this._newRow ? this._newRow : []) : this.get_selectedRow();
        if (this.get_isInserting() && this._expressions) {
            for (i = 0; i < this._expressions.length; i++) {
                var exp = this._expressions[i];
                if (exp.Scope == Web.DynamicExpressionScope.DefaultValues && exp.Type == Web.DynamicExpressionType.ClientScript) {
                    var f = this.findField(exp.Target);
                    if (f) {
                        if (String.isNullOrEmpty(exp.Test))
                            row[f.Index] = exp.Result;
                        else {
                            var r = eval(exp.Test);
                            if (r)
                                row[f.Index] = String.isNullOrEmpty(exp.Result) ? r : exp.Result;
                        }
                    }
                }
            }
        }
        this._tabIndex = 1;

        var fieldCount = 0;
        for (var i = 0; i < this._allFields.length; i++)
            if (!this._allFields[i].Hidden) fieldCount++;
        if (fieldCount > Web.DataViewResources.Form.SingleButtonRowFieldLimit && row)
            this._renderActionButtons(sb, 'Top');
        if (!row) this._renderNoRecordsWhenNeeded(sb);
        else {
            var t = this._get_template();
            if (t) {
                sb.append('<tr class="CategoryRow"><td valign="top" class="Fields" colspan="2">');
                this._renderTemplate(t, sb, row, true, false);
                sb.append('</td></tr>');
            }
            else {
                for (i = 0; i < this.get_categories().length; i++) {
                    var category = this.get_categories()[i];
                    sb.appendFormat('<tr class="CategoryRow" id="{2}_Category{3}"><td valign="top" class="Category"><table class="Category" cellpadding="0" cellspacing="0"><tr><td class="HeaderText">{0}</td></tr><tr><td class="Description">{1}</td></tr></table></td><td valign="top" class="Fields">', category.HeaderText, category.Description, this.get_id(), i);
                    for (j = 0; j < this.get_fields().length; j++) {
                        var field = this.get_fields()[j];
                        if (!field.Hidden && field.CategoryIndex == category.Index)
                            this._renderItem(sb, field, row, true);
                    }
                    sb.append('</td></tr>');
                }
            }
        }
        if (row) this._renderActionButtons(sb, 'Bottom');
    },
    _renderItem: function(sb, field, row, isSelected, isInlineForm, isFirstRow) {
        var isForm = this.get_view().Type == 'Form' || isInlineForm;
        var v = row[field.Index];
        if (v != null) v = v.toString();
        var checkBox = null;
        var isEditing = this.get_isEditing();
        if (isEditing && field.ItemsStyle == 'CheckBox' && field.Items.length == 2) {
            if (v == null) v = 'false';
            checkBox = String.format('<input type="checkbox" id="{0}_Item{1}"{2} tabindex="{3}" value="{4}" onclick="this.value=this.checked;$find(&quot;{0}&quot;)._valueChanged();"/>', this.get_id(), field.Index, field.Items[1][0] && v == 'true' ? ' checked' : '', this._tabIndex++, v);
        }
        if (isForm) {
            sb.appendFormat('<div class="Item {2}" id="{0}_ItemContainer{1}"><div class="Error" id="{0}_Item{1}_Error" style="display:none"></div>', this.get_id(), field.Index, field.Name);
            var headerText = this._allFields[field.AliasIndex].HeaderText;
            if (headerText.length > 0)
                sb.appendFormat('<div class="Header">{3}<label for="{0}_Item{1}">{2}{4}</label></div>', this.get_id(), field.Index, headerText, checkBox, isEditing && !field.AllowNulls && Web.DataViewResources.Form.RequiredFieldMarker ? Web.DataViewResources.Form.RequiredFieldMarker : '');
            if (checkBox == null)
                sb.append('<div class="Value">');
        }
        var needObjectRef = !isEditing && field.ItemsDataController && field.ItemsDataController.length > 0 && field.ItemsStyle != 'CheckBoxList' && !isFirstRow && v;
        if (needObjectRef && !isForm) sb.append('<table width="100%" cellpadding="0" cellspacing="0" class="ObjectRef"><tr><td>');
        if (isEditing && isSelected && !field.ReadOnly) {
            if (!isForm && checkBox) sb.append(checkBox);
            if (checkBox == null)
                if (field.Items.length > 0) {
                if (field.ItemsStyle == 'RadioButtonList') {
                    sb.append('<table cellpadding="0" cellspacing="0" class="RadioButtonList">');
                    var columns = field.Columns == 0 ? 1 : field.Columns;
                    var rows = Math.floor(field.Items.length / columns) + (field.Items.length % columns > 0 ? 1 : 0);
                    for (var r = 0; r < rows; r++) {
                        sb.append('<tr>');
                        for (var c = 0; c < columns; c++) {
                            var itemIndex = c * rows + r; //r * columns + c;
                            if (itemIndex < field.Items.length) {
                                var item = field.Items[itemIndex];
                                var itemValue = item[0] == null ? '' : item[0].toString();
                                if (v == null) v = '';
                                sb.appendFormat(
                                        '<td class="Button"><input type="radio" id="{0}_Item{1}_{2}" name="{0}_Item{1}" value="{3}"{4} tabindex="{6}" onclick="$find(&quot;{0}&quot;)._valueChanged()"/></td><td class="Option"><label for="{0}_Item{1}_{2}">{5}<label></td>',
                                        this.get_id(), field.Index, itemIndex, itemValue, itemValue == v ? " checked" : "", this.htmlEncode(field, item[1]), this._tabIndex++);
                            }
                            else
                                sb.append('<td class="Button">&nbsp;</td><td class="Option"></td>');
                        }
                        sb.append('</tr>');
                    }
                    sb.append('</table>');
                }
                else if (field.ItemsStyle == 'CheckBoxList') {
                    var lov = v ? v.split(',') : [];
                    sb.appendFormat('<input type="hidden" id="{0}_Item{1}" name="{0}_Item{1}" value=""/>', this.get_id(), field.Index);
                    sb.append('<table cellpadding="0" cellspacing="0" class="RadioButtonList">');
                    columns = field.Columns == 0 ? 1 : field.Columns;
                    rows = Math.floor(field.Items.length / columns) + (field.Items.length % columns > 0 ? 1 : 0);
                    for (r = 0; r < rows; r++) {
                        sb.append('<tr>');
                        for (c = 0; c < columns; c++) {
                            itemIndex = c * rows + r; //r * columns + c;
                            if (itemIndex < field.Items.length) {
                                item = field.Items[itemIndex];
                                itemValue = item[0] == null ? '' : item[0].toString();
                                if (v == null) v = '';
                                sb.appendFormat(
                                        '<td class="Button"><input type="checkbox" id="{0}_Item{1}_{2}" name="{0}_Item{1}" value="{3}"{4} tabindex="{6}"  onclick="$find(&quot;{0}&quot;)._valueChanged()"/></td><td class="Option"><label for="{0}_Item{1}_{2}">{5}<label></td>',
                                        this.get_id(), field.Index, itemIndex, itemValue, Array.indexOf(lov, itemValue) != -1 ? " checked" : "", this.htmlEncode(field, item[1]), this._tabIndex++);
                            }
                            else
                                sb.append('<td class="Button">&nbsp;</td><td class="Option"></td>');
                        }
                        sb.append('</tr>');
                    }
                    sb.append('</table>');
                }
                else {
                    sb.appendFormat('<select id="{0}_Item{1}" size="{2}" tabindex="{3}" onchange="$find(&quot;{0}&quot;)._valueChanged();">', this.get_id(), field.Index, field.ItemsStyle == 'ListBox' ? (field.Rows == 0 ? 5 : field.Rows) : '1', this._tabIndex++);
                    if (v == null) v = '';
                    v = v.toString();
                    for (var i = 0; i < field.Items.length; i++) {
                        item = field.Items[i];
                        itemValue = item[0];
                        if (itemValue == null) itemValue = '';
                        itemValue = itemValue.toString();
                        sb.appendFormat('<option value="{0}"{1}>{2}</option>', itemValue, itemValue == v ? ' selected' : '', this.htmlEncode(field, item[1]));
                    }
                    sb.append('</select>');
                }
            }
            else if (field.ItemsDataController && field.ItemsDataController.length > 0) {
                v = row[field.AliasIndex];
                if (v == null) v = Web.DataViewResources.Lookup.SelectLink;
                var s = field.DataFormatString && field.DataFormatString.length > 0 ? String.localeFormat(field.DataFormatString, v) : v.toString();
                this._renderCreateNewBegin(sb, field);
                sb.appendFormat('<table cellpadding="0" cellspacing="0" class="Lookup"><tr><td><a href="#" onclick="$find(\'{0}\').showLookup({1});return false" id="{0}_Item{1}_ShowLookupLink" title="{3}" tabindex="{5}">{2}</a><a href="#" class="Clear" onclick="$find(\'{0}\').clearLookupValue({1});return false" id="{0}_Item{1}_ClearLookupLink" title="{7}" tabindex="{6}" style="display:{8}">&nbsp;</a></td></tr></table><input type="hidden" id="{0}_Item{1}" value="{4}"/>',
                    this.get_id(), field.Index, this.htmlEncode(field, s), String.format(Web.DataViewResources.Lookup.SelectToolTip, field.Label), row[field.Index], this._tabIndex++, this._tabIndex++, String.format(Web.DataViewResources.Lookup.ClearToolTip, field.Label), row[field.Index] != null ? 'display' : 'none');
                this._renderCreateNewEnd(sb, field);
            }
            else if (field.OnDemand) this._renderOnDemandItem(sb, field, row, isSelected, isForm);
            else if (field.Rows > 1) {
                if (!isInlineForm) this._renderLiquidFrameHeader(sb);
                sb.appendFormat('<textarea id="{0}_Item{1}" tabindex="{2}"  onchange="$find(&quot;{0}&quot;)._valueChanged()"', this.get_id(), field.Index, this._tabIndex++);
                if (!isForm)
                    sb.append(' style="width:95%"');
                else
                    sb.appendFormat(' cols="{0}"', field.Columns > 0 ? field.Columns : 50);
                sb.appendFormat(' rows="{0}"', field.Rows);
                sb.append('>');
                sb.append(this.htmlEncode(field, v));
                sb.append('</textarea>');
                if (!isInlineForm) this._renderLiquidFrameFooter(sb);
            }
            else {
                if (!isInlineForm) this._renderLiquidFrameHeader(sb);
                sb.appendFormat('<input type="{3}" id="{0}_Item{1}" tabindex="{2}" onchange="$find(&quot;{0}&quot;)._valueChanged()"', this.get_id(), field.Index, this._tabIndex++, field.TextMode == 0 ? 'text' : 'password');
                if (!isForm)
                    sb.append(' style="width:100%"');
                else
                    sb.appendFormat(' size="{0}"', field.Columns > 0 ? field.Columns : 50);
                v = row[field.Index];
                if (v == null)
                    s = '';
                else
                    s = field.DataFormatString && field.DataFormatString.length > 0 ? String.localeFormat(field.DataFormatString, v) : v.toString();
                sb.appendFormat(' value="{0}"', Web.DataView.htmlAttributeEncode(s));
                sb.append('/>');
                if (field.Type == 'DateTime' && isForm && Web.DataViewResources.Form.ShowCalendarButton)
                    sb.appendFormat('<a id="{0}_Item{1}_Button" href="#" onclick="return false" class="Calendar" tabindex="{2}">&nbsp;</a>', this.get_id(), field.Index, this._tabIndex++);
                if (!isInlineForm) this._renderLiquidFrameFooter(sb);
            }
        }
        else {
            if (field.OnDemand) this._renderOnDemandItem(sb, field, row, isSelected, isForm);
            else {
                v = this.htmlEncode(field, row[field.AliasIndex]);
                if (field.Items.length == 0) {
                    if (field.Type == 'String' && v != null && v.length > Web.DataViewResources.Data.MaxReadOnlyStringLen)
                        v = v.substring(0, Web.DataViewResources.Data.MaxReadOnlyStringLen) + '...';
                    s = v == null || field.Type == "String" && v.trim().length == 0 ? (isForm ? Web.DataViewResources.Data.NullValueInForms : Web.DataViewResources.Data.NullValue) : (field.DataFormatString && field.DataFormatString.length > 0 ? String.localeFormat(field.DataFormatString, v) : v.toString());
                }
                else if (field.ItemsStyle == 'CheckBoxList') {
                    lov = v ? v.split(',') : [];
                    for (i = 0; i < lov.length; i++) {
                        if (i > 0) sb.append(', ');
                        item = this._findItemByValue(field, lov[i]);
                        if (item) sb.append(Web.DataView.htmlEncode(item[1]));
                    }
                    s = lov.length == 0 ? Web.DataViewResources.Data.NullValueInForms : '';
                }
                else {
                    item = this._findItemByValue(field, v);
                    s = item[1];
                }
                sb.append(s);
            }
        }
        if (needObjectRef) {
            if (!isForm) sb.append('</td><td align="right">');
            sb.appendFormat('<span class="ObjectRef" title="{0}" onclick="$find(&quot;{1}&quot;).executeCommand({{commandName: &quot;_ViewDetails&quot;, commandArgument: &quot;{2}&quot;}})">&nbsp;</span>',
                String.format(Web.DataViewResources.Lookup.DetailsToolTip, Web.DataView.htmlAttributeEncode(this._allFields[field.AliasIndex].HeaderText)), this.get_id(), field.Name);
            if (!isForm) sb.append('</td></tr></table>');
        }
        if (isForm) {
            if (checkBox == null)
                sb.append('</div>');
            if (field.FooterText && field.FooterText.length > 0)
                sb.appendFormat('<div class="Footer">{0}</div>', field.FooterText);
            sb.append('</div>');
        }
    },
    _renderOnDemandItem: function(sb, field, row, isSelected, isForm) {
        var v = row[field.Index];
        var m = v ? v.match(/^null\|(.+)$/) : null;
        var isNull = m != null;
        if (m) v = m[1];
        if (isNull && !isSelected && field.OnDemandStyle == 1)
            sb.append(isForm ? Web.DataViewResources.Data.NullValueInForms : Web.DataViewResources.Data.NullValue);
        else {
            var blobHref = this.resolveClientUrl(Web.DataViewResources.Data.BlobHandler);
            if (isSelected && !isNull) sb.appendFormat('<a href="{0}?{1}=o|{2}" target="_blank" title="{3}">', blobHref, field.OnDemandHandler, v, Web.DataViewResources.Data.BlobDownloadHint);
            if (field.OnDemandStyle == 1)
                if (isNull)
                sb.append(isForm ? Web.DataViewResources.Data.NullValueInForms : Web.DataViewResources.Data.NullValue);
            else
                sb.append(isSelected ? Web.DataViewResources.Data.BlobDownloadLink : Web.DataViewResources.Data.BlobDownloadLinkReadOnly);
            else
                sb.appendFormat('<img src="{0}?{1}=t|{2}" class="Thumbnail"/>', blobHref, field.OnDemandHandler, v);
            if (isSelected && !isNull) sb.append('</a>');
            if (!field.ReadOnly && (this.get_isEditing() && isSelected || isForm))
                sb.appendFormat('<iframe src="{0}?{1}=u|{2}" frameborder="0" scrolling="no"></iframe>', blobHref, field.OnDemandHandler, v);
        }
    },
    _renderLiquidFrameHeader: function(sb) {
        if (this.get_view().Type == 'Grid') sb.append('<table class="Liquid" cellpadding="0" cellspacing="0"><tr><td class="Liquid">');
    },
    _renderLiquidFrameFooter: function(sb) {
        if (this.get_view().Type == 'Grid') sb.append('</td></tr></table>');
    },
    _renderActionButtons: function(sb, location) {
        var actions = this.get_actions('Form');
        sb.appendFormat('<tr class="ActionButtonsRow {0}ButtonsRow"><td colspan="{1}" class="ActionButtons">', location, this._get_colSpan());
        sb.appendFormat('<table style="width:100%" cellpadding="0" cellspacing="0" class="ActionButtons"><tr><td id="{0}_Wait" align="left">{1}&nbsp;</td><td align="right">&nbsp;', location == 'Bottom' ? this.get_id() : '', this.get_isEditing() && Web.DataViewResources.Form.RequiredFieldMarker ? Web.DataViewResources.Form.RequiredFiledMarkerFootnote : '');
        for (var i = 0; i < actions.length; i++) {
            var action = actions[i];
            if (this._isActionAvailable(action)) {
                var className = action.CssClass && action.CssClass.length > 0 ? action.CssClass : '';
                if (action.HeaderText && action.HeaderText.length > 10) {
                    if (className.length > 0) className += ' ';
                    className += 'AutoWidth';
                }
                sb.appendFormat('<button onclick="$find(\'{0}\').executeAction(\'Form\', {1},-1);return false;" tabindex="{3}"{4}>{2}</button>', this.get_id(), i, action.HeaderText, this._tabIndex++, className.length > 0 ? String.format(' class="{0}"', className) : '');
            }
        }
        sb.append('</tr></tr></table></td></tr>');
    },
    _isActionAvailable: function(action, rowIndex) {
        var lastCommand = action.WhenLastCommandName ? action.WhenLastCommandName : '';
        var lastArgument = action.WhenLastCommandArgument ? action.WhenLastCommandArgument : '';
        var available = lastCommand.length == 0 || (lastCommand == this.get_lastCommandName() && (lastArgument.length == 0 || lastArgument == this.get_lastCommandArgument()));
        if (available && this.get_isEditing()) {
            var isSelected = this._rowIsSelected(rowIndex == null ? this._selectedRowIndex : rowIndex);
            if (isSelected)
                return lastCommand == 'New' || lastCommand == 'Edit';
            else if (!isSelected && rowIndex == null && lastCommand == 'New')
                return true;
            else
                return lastCommand.length == 0 && rowIndex != null;
        }
        return available;
    },
    _rowIsSelected: function(rowIndex) {
        var row = this._rows[rowIndex];
        if (row && this._keyFields.length == this._selectedKey.length) {
            for (var j = 0; j < this._keyFields.length; j++) {
                var field = this._keyFields[j];
                var v1 = this._selectedKey[j];
                var v2 = row[field.Index];
                if (field.Type == 'DateTime') {
                    if (!(v1 || v2)) return false;
                    v1 = v1.toString();
                    v2 = v2.toString();
                }
                if (v1 != v2) return false;
            }
            return true;
        }
        else
            return false;
    },
    _get_template: function() {
        return $get(this.get_controller() + '_' + this.get_viewId());
    },
    _renderTemplate: function(template, sb, row, isSelected, isInlineForm) {
        var s = template.innerHTML;
        var iterator = /([\s\S]*?)\{([\w\d]+)(\:([\S\s]+?)){0,1}\}/g;
        var lastIndex = 0;
        var match = iterator.exec(s);
        while (match) {
            lastIndex = match.index + match[0].length;
            sb.append(match[1]);
            var field = this.findField(match[2]);
            if (field)
                if (match[4] && match[4].length > 0)
                sb.appendFormat('{0:' + match[4] + '}', row[field.Index]);
            else
                this._renderItem(sb, field, row, isSelected, isInlineForm);
            match = iterator.exec(s);
        }
        if (lastIndex < s.length) sb.append(s.substring(lastIndex));
    },
    _renderGridView: function(sb) {
        this._renderViewDescription(sb);
        this._renderActionBar(sb);
        this._renderInfoBar(sb);
        var expressions = this._enumerateExpressions(Web.DynamicExpressionType.Any, Web.DynamicExpressionScope.ViewRowStyle, this.get_viewId());
        sb.append('<tr class="HeaderRow">');
        var multipleSelection = this._selectionMode == Web.DataViewSelectionMode.Multiple;
        if (multipleSelection)
            sb.appendFormat('<th class="Toggle"><input type="checkbox" onclick="$find(&quot;{0}&quot;).toggleSelectedRow()"/></th>', this.get_id());
        for (var i = 0; i < this.get_fields().length; i++) {
            var field = this.get_fields()[i];
            sb.appendFormat('<th class="{3}"><div id="{0}_Header{1}" style="padding:3px;cursor:pointer;{2}" class="HeaderSelector">', this.get_id(), i, Web.DataView.isIE6 ? 'display:inline-block;' : '', field.Name);
            this._renderFieldHeaderText(sb, field)
            sb.append('</div></th>');
        }
        sb.append('</tr>');
        var isEditing = this.get_isEditing();
        var t = isEditing ? this._get_template() : null;
        for (i = 0; i < this.get_rows().length; i++) {
            var row = this.get_rows()[i];
            var customCssClasses = ' ' + this._evaluateJavaScriptExpressions(expressions, row, true);
            var isSelectedRow = this._rowIsSelected(i);
            var checkBoxCell = null;
            if (multipleSelection) {
                var selected = Array.indexOf(this._selectedKeyList, this._createRowKey(i)) != -1;
                checkBoxCell = String.format('<td class="Cell"><input type="checkbox" id="{0}_CheckBox{1}" onclick="$find(&quot;{0}&quot;).toggleSelectedRow({1})"{2}"/></td>', this.get_id(), i, selected ? ' checked="checked"' : null);
            }
            if (isSelectedRow && isEditing && t) {
                sb.appendFormat('<tr id="{0}_Row{1}" class="{2}Row{3}">{5}<td class="Cell" colspan="{4}">', this.get_id(), i, i % 2 == 0 ? '' : 'Alternating', ' InlineFormRow', this.get_fields().length, checkBoxCell);
                this._renderTemplate(t, sb, row, true, true);
                sb.append('</td>');
            }
            else {
                sb.appendFormat('<tr id="{0}_Row{1}" class="{2}Row{3}" onmouseover="Sys.UI.DomElement.addCssClass(this,\'Highlight\');" onmouseout="Sys.UI.DomElement.removeCssClass(this,\'Highlight\');">', this.get_id(), i, i % 2 == 0 ? '' : 'Alternating', isSelectedRow ? ' Selected' + customCssClasses : customCssClasses);
                if (checkBoxCell) sb.append(checkBoxCell);
                for (j = 0; j < this.get_fields().length; j++) {
                    field = this.get_fields()[j];
                    if (j == 0 && this.get_lookupField() == null || isSelectedRow && isEditing) sb.appendFormat('<td class="Cell {0}">', field.Name); else sb.appendFormat('<td class="Cell {2}" style="cursor:default;" onclick="$find(&quot;{0}&quot;).executeRowCommand({1},&quot;Select&quot;)">', this.get_id(), i, field.Name);
                    if (isSelectedRow && isEditing && !field.ReadOnly) sb.appendFormat('<div class="Error" id="{0}_Item{1}_Error" style="display:none"></div>', this.get_id(), field.Index);
                    if (j == 0) {
                        sb.appendFormat('<div id="{0}_RowSelector{1}" style="padding:3px;margin:-1;cursor:pointer;{2}" class="RowSelector">', this.get_id(), i, Web.DataView.isIE6 ? 'display:inline-block;' : '');
                        if (!(isSelectedRow && isEditing))
                            if (!this.get_lookupField()) sb.appendFormat('<a href="#" onclick="$find(\'{0}\').executeAction(\'Grid\',-1,{1});return false">', this.get_id(), i); else sb.append('<a href="#" onclick="return false">');
                    }
                    this._renderItem(sb, field, row, isSelectedRow, null, j == 0);
                    if (j == 0 && !isEditing) {
                        if (!(isSelectedRow && isEditing)) sb.append('</a>');
                        sb.append('</div>');
                    }
                    sb.append('</td>');
                }
            }
            sb.append('</tr>');
        }
        this._renderAggregates(sb);
        this._renderNoRecordsWhenNeeded(sb);
        this._renderViewPager(sb);
    },
    _renderAggregates: function(sb) {
        if (this._totalRowCount == 0 || this.get_aggregates() == null) return;
        sb.append('<tr class="AggregateRow">');
        var aggregateTypes = ['None', 'Sum', 'Count', 'Average', 'Maximum', 'Minimum'];
        for (var i = 0; i < this.get_fields().length; i++) {
            var field = this.get_fields()[i];
            if (field.Aggregate == 0) sb.append('<td class="None">&nbsp;</td>');
            else {
                var v = this.get_aggregates()[field.Index];
                if (v == null) v = Web.DataViewResources.Data.NullValue;
                else v = (field.DataFormatString && field.DataFormatString.length > 0 ? String.localeFormat(field.DataFormatString, v) : v.toString());
                sb.appendFormat('<td class="Aggregate {3}" title="{1} of {2}">{0}</td>', v, aggregateTypes[field.Aggregate], field.Label, field.Name);
            }
        }
        sb.append('</tr>');
    },
    _renderNoRecordsWhenNeeded: function(sb) {
        if (this._totalRowCount == 0)
            sb.appendFormat('<tr class="Row NoRecords"><td colspan="{0}" class="Cell">{1}</td></tr>', this._get_colSpan(), Web.DataViewResources.Data.NoRecords);
    },
    _attachBehaviors: function() {
        this._detachBehaviors();
        this._attachActionBarBehaviors();
        if (this.get_view().Type == 'Grid') {
            this._attachRowContextBehaviors();
            this._attachHeaderDropDownBehaviors();
        }
        this._attachFieldBehaviors();
        var e = this.get_quickFindElement();
        if (e) $addHandlers(e, this._quickFindHandlers, this);
    },
    _attachActionBarBehaviors: function() {
        var offsetX = -4;
        var offsetY = 4;
        if (Sys.Browser.agent === Sys.Browser.Opera) {
            offsetX = 0;
            offsetY = 0;
        }
        else if (Sys.Browser.agent === Sys.Browser.Firefox && Sys.Browser.version >= 3) {
            offsetX = 0;
            offsetY = 1;
        }
        else if (Sys.Browser.agent !== Sys.Browser.InternetExplorer) {
            offsetX = 0;
            offsetY = 22;
        }
        var groups = this.get_actionGroups('ActionBar');
        for (var i = 0; i < groups.length; i++) {
            var group = groups[i];
            var target = $get(this.get_id() + '_ActionBarGroup' + i.toString());
            if (target) {
                var panel = group._panel = document.createElement('div');
                panel.id = this.get_id() + '_ActionBarGroupPanel' + i.toString()
                Sys.UI.DomElement.setVisible(panel, false);
                this.get_element().appendChild(panel);
                panel.className = 'ContextMenuPanel ActionBarContextMenuPanel';
                var sb = new Sys.StringBuilder();
                if (Web.DataView.isIE6) sb.append('<table cellpadding="0" cellspacing="0"><tr><td style="padding:0px">');
                for (var j = 0; j < group.Actions.length; j++) {
                    var action = group.Actions[j];
                    if (this._isActionAvailable(action))
                        if (action.CommandName == null || action.CommandName.length == 0)
                        sb.append('<div class="ContextMenuBreak"></div>');
                    else
                        sb.appendFormat('<a href="#" onclick="$find(\'{0}\').executeAction(\'ActionBar\',{1},null,{2});return false" class="ContextMenuItem {4}"><div class="Title">{3}</div><div class="Description">{5}</div></a>',
                                this.get_id(), j, i, action.HeaderText, action.CssClass && action.CssClass.length > 0 ? action.CssClass : action.CommandName + "LargeIcon", action.Description);
                }
                if (Web.DataView.isIE6) sb.append('</td></tr></table>');
                panel.innerHTML = sb.toString();
                sb.clear();
                var popup = group._popupBehavior = $create(AjaxControlToolkit.PopupControlBehavior, { id: this.get_id() + "_ActionBarGroupPopup" + i.toString(), PopupControlID: panel.id, Position: AjaxControlToolkit.PopupControlPopupPosition.Bottom, OffsetY: offsetY, OffsetX: offsetX }, null, null, target);
                popup.hidePopup();
                popup._popupBehavior.add_showing(this._actionBarGroupOnShowingHandler);
            }
        }
        var selector = $get(this.get_id() + '_ViewSelector');
        if (selector) {
            selector.innerHTML = String.format('<table style="width:100%;" cellpadding="0" cellspacing="0"><tr><td nowrap style="width:100%;padding:1px 16px 1px 4px"><span>{0}</span></td ><td class="ajax__dropdown_arrow_image" style="padding:0px 14px 0px 0px">&nbsp;</td></table>', this.get_view().Label);
            panel = this._viewSelectorPanel = document.createElement('div');
            Sys.UI.DomElement.setVisible(panel, false);
            this.get_element().appendChild(panel);
            panel.className = 'ContextMenuPanel';
            sb = new Sys.StringBuilder();
            for (i = 0; i < this.get_views().length; i++) {
                var view = this.get_views()[i];
                if (view.Type != 'Form' || view.Id == this.get_viewId())
                    sb.appendFormat('<a href="#" onclick="$find(\'{0}\').executeCommand({{commandName:\'Select\',commandArgument:\'{1}\'}});return false" class="ContextMenuItem {2}">{3}</a>',
                        this.get_id(), view.Id, view.Id == this.get_viewId() ? 'Checked' : '', view.Label);
            }
            panel.innerHTML = sb.toString();
            panel.id = this.get_id() + '_ViewSelectorMenu';
            target = $get(this.get_id() + '_ViewSelector');
            this._viewSelectorPopupBehavior = $create(AjaxControlToolkit.PopupControlBehavior, { id: this.get_id() + "_ViewSelectorPopup", PopupControlID: panel.id, Position: AjaxControlToolkit.PopupControlPopupPosition.Bottom, OffsetY: offsetY, OffsetX: offsetX }, null, null, target);
            this._viewSelectorPopupBehavior.add_shown(this._viewSelectorOnShownHandler);
            this._viewSelectorPopupBehavior.add_showing(this._actionBarGroupOnShowingHandler);
            sb.clear();
        }
    },
    _getStyle: function(el, styleProp) {
        if (el.currentStyle)
            return el.currentStyle[styleProp];
        else
            if (window.getComputedStyle) return document.defaultView.getComputedStyle(el, null).getPropertyValue(styleProp.replace(/([A-Z])/, '-$1').toLowerCase());
        return '';
    },
    _attachRowContextBehaviors: function() {
        this._rowSelectors = [];
        var actions = this.get_actions('Grid');
        var t = this._get_template();
        if (actions && actions.length > 0 && this.get_lookupField() == null) {
            for (i = 0; i < this._rows.length; i++) {
                if (!this._rowIsSelected(i) || (!this.get_isEditing() || Web.DataViewResources.Grid.InPlaceEditContextMenuEnabled && t == null)) {
                    sb = new Sys.StringBuilder();
                    if (Web.DataView.isIE6) sb.append('<table cellpadding="0" cellspacing="0"><tr><td style="padding:0px">');
                    for (var j = 0; j < actions.length; j++) {
                        var action = actions[j];
                        if (this._isActionAvailable(action, i))
                            if (action.CommandName == null || action.CommandName.length == 0)
                            sb.append('<div class="ContextMenuBreak"></div>');
                        else
                            sb.appendFormat('<a href="#" onclick="$find(\'{0}\').executeAction(\'Grid\', {1},{2});return false" class="ContextMenuItem {4}">{3}</a>',
                            this.get_id(), j, i, action.HeaderText, action.CssClass && action.CssClass.length > 0 ? action.CssClass : action.CommandName + 'Icon');
                    }
                    var panel = document.createElement('div');
                    Sys.UI.DomElement.setVisible(panel, false);
                    panel.className = 'ContextMenuPanel';
                    if (Web.DataView.isIE6) sb.append('</td></tr></table>');
                    panel.innerHTML = sb.toString();
                    sb.clear();
                    sb = null;
                    this.get_element().appendChild(panel);
                    dropDown = $create(AjaxControlToolkit.DropDownBehavior, { dropDownControl: panel, id: this.get_id() + '_RowDropDown' + i.toString() }, null, null, $get(this.get_id() + '_RowSelector' + i.toString()));
                    dropDown._dropFrame.className = 'DropDown_RowSelector';
                    color = Web.DataView._rowHighlightBackgroundColor;
                    if (!color) {
                        var color = this._getStyle(dropDown._dropFrame, 'backgroundColor');
                        Web.DataView._rowHighlightBackgroundColor = color;
                    }
                    dropDown.set_highlightBackgroundColor(color);
                    Array.add(this._rowSelectors, { _panel: panel, _dropDownBehavior: dropDown });
                }
            }
        }
    },
    _attachHeaderDropDownBehaviors: function() {
        for (i = 0; i < this.get_fields().length; i++) {
            var field = this.get_fields()[i];
            var headerDiv = $get(this.get_id() + '_Header' + i.toString());
            if (field.AllowSorting || field.AllowQBE) {
                if (!field._dropDownPanel) {
                    panel = field._dropDownPanel = document.createElement('div');
                    Sys.UI.DomElement.setVisible(panel, false);
                    panel.className = 'ContextMenuPanel';
                    panel.id = this.get_id() + '_DropDownPanel' + i.toString();
                    this.get_element().appendChild(panel);
                }
                dropDown = field._headerDropDownBehavior = $create(AjaxControlToolkit.DropDownBehavior, { dropDownControl: field._dropDownPanel, id: this.get_id() + '_HeaderDropDown' + i.toString() }, null, null, headerDiv);
                dropDown._dropFrame.className = 'DropDown_Header';
                var color = Web.DataView._headerHighlightBackgroundColor;
                if (!color) {
                    color = this._getStyle(dropDown._dropFrame, 'backgroundColor');
                    Web.DataView._headerHighlightBackgroundColor = color;
                }
                dropDown.set_highlightBackgroundColor(color);
                dropDown.add_showing(this._headerDropDownOnShowingHandler);
            }
            else
                headerDiv.style.cursor = '';
        }
    },
    _attachFieldBehaviors: function() {
        if (this.get_isEditing()) {
            for (var i = 0; i < this.get_fields().length; i++) {
                var field = this.get_fields()[i];
                var element = $get(this.get_id() + '_Item' + field.Index);
                if (element) {
                    if (field.Mask && field.Mask.length > 0) {
                        var cc = Sys.CultureInfo.CurrentCulture;
                        var sdp = cc.dateTimeFormat.ShortDatePattern.toUpperCase().split(cc.dateTimeFormat.DateSeparator);
                        var m = $create(AjaxControlToolkit.MaskedEditBehavior, {
                            'CultureAMPMPlaceholder': cc.dateTimeFormat.AMDesignator + ';' + cc.dateTimeFormat.PMDesignator,
                            'CultureCurrencySymbolPlaceholder': cc.numberFormat.CurrencySymbol,
                            'CultureDateFormat': sdp[0].substring(0, 1) + sdp[1].substring(0, 1) + sdp[2].substring(0, 1),
                            'CultureDatePlaceholder': cc.dateTimeFormat.DateSeparator,
                            'CultureDecimalPlaceholder': cc.numberFormat.NumberDecimalSeparator,
                            'CultureName': cc.name,
                            'CultureThousandsPlaceholder': cc.numberFormat.NumberGroupSeparator,
                            'CultureTimePlaceholder': cc.dateTimeFormat.TimeSeparator,
                            'DisplayMoney': field.DataFormatString == '{0:c}',
                            'Mask': field.Mask,
                            'MaskType': field.MaskType,
                            'id': this.get_id() + '_MaskedEdit' + field.Index
                        },
                            null, null, element);
                        if (field.MaskType == 2) m.set_InputDirection(1);
                        Array.add(field.Behaviors, m);

                    }
                    if (field.Type == 'DateTime') {
                        var c = $create(AjaxControlToolkit.CalendarBehavior, { id: this.get_id() + '_Calendar' + field.Index }, null, null, element);
                        c.set_format(field.DataFormatString.match(/\{0:([\s\S]*?)\}/)[1]);
                        var button = $get(element.id + '_Button');
                        if (button) c.set_button(button);
                        Array.add(field.Behaviors, c);
                    }
                }
            }
        }
    },
    _detachBehaviors: function() {
        // detach quick find
        var e = this.get_quickFindElement();
        if (e) $clearHandlers(e);
        // detach view selector
        if (this._viewSelectorPopupBehavior) {
            this._viewSelectorPopupBehavior.remove_shown(this._viewSelectorOnShownHandler);
            this._viewSelectorPopupBehavior.remove_showing(this._actionBarGroupOnShowingHandler);
            this._viewSelectorPopupBehavior.dispose();
            delete this._viewSelectorPopupBehavior._popupElement;
            this._viewSelectorPopupBehavior = null;
        }
        if (this._viewSelectorPanel) {
            this.get_element().removeChild(this._viewSelectorPanel);
            delete this._viewSelectorPanel;
        }
        // detach action bar popups
        var groups = this.get_actionGroups('ActionBar', true);
        for (var i = 0; i < groups.length; i++) {
            var group = groups[i];
            if (group._popupBehavior) {
                group._popupBehavior._popupBehavior.remove_showing(this._actionBarGroupOnShowingHandler);
                group._popupBehavior.dispose();
                delete group._popupBehavior._popupElement;
                group._popupBehavior = null;
                this.get_element().removeChild(group._panel);
                delete group._panel;
            }
        }
        // detach row selectors
        if (this._rowSelectors) {
            for (i = 0; i < this._rowSelectors.length; i++) {
                this._rowSelectors[i]._dropDownBehavior.get_element().style.backgroundColor = '';
                this._rowSelectors[i]._dropDownBehavior.dispose();
                this._rowSelectors[i]._dropDownBehavior = null;
                this.get_element().removeChild(this._rowSelectors[i]._panel);
                delete this._rowSelectors[i]._panel;
            }
            this._rowSelectors = null;
        }
        // detach row header drop downs and field behaviors
        if (this.get_fields() != null) {
            for (i = 0; i < this.get_fields().length; i++) {
                var field = this.get_fields()[i];
                if (field._headerDropDownBehavior != null) {
                    field._headerDropDownBehavior.remove_showing(this._headerDropDownOnShowingHandler);
                    field._headerDropDownBehavior.dispose();
                    field._headerDropDownBehavior = null;
                }
                if (field._lookupModalBehavior != null) {
                    field._lookupModalBehavior.dispose();
                    this.get_element().removeChild(field._lookupModalPanel);
                    delete field._lookupModalPanel;
                    field._lookupModalBehavior = null;
                }
                if (field._lookupDataControllerBehavior != null) {
                    field._lookupDataControllerBehavior.dispose();
                    field._lookupDataControllerBehavior = null;
                }
                if (field._dropDownPanel != null) {
                    this.get_element().removeChild(field._dropDownPanel);
                    delete field._dropDownPanel;
                }
                for (var j = 0; j < field.Behaviors.length; j++)
                    field.Behaviors[j].dispose();
                Array.clear(field.Behaviors);
            }
        }
    },
    _renderFieldHeaderText: function(sb, field) {
        field = this._allFields[field.AliasIndex];
        if (field.AllowSorting) {
            sb.appendFormat('<a href="#" onclick="$find(\'{0}\').sort(\'{1}\');return false" title="{3}">{2}</a>',
                this.get_id(), field.Name, field.HeaderText, String.format(Web.DataViewResources.HeaderFilter.SortBy, field.HeaderText));
            if (this.get_sortExpression() != null && this.get_sortExpression().startsWith(field.Name + " "))
                sb.append(this.get_sortExpression().endsWith(' asc') ? '<span class="SortUp">&nbsp;</span>' : '<span class="SortDown">&nbsp;</span>');
            if (this.filterOf(field) != null)
                sb.append('<span class="Filter">&nbsp;</span>');
        }
        else
            sb.append(field.HeaderText);
    },
    _renderActionBar: function(sb) {
        if (!this.get_showActionBar()) return;
        sb.appendFormat('<tr class="ActionRow"><td colspan="{0}"  class="ActionBar">', this._get_colSpan());
        sb.append('<table style="width:100%" cellpadding="0" cellspacing="0"><tr><td style="width:100%">');
        var groups = this.get_actionGroups('ActionBar');
        sb.append('<table cellpadding="0" cellspacing="0" class="Groups"><tr>');
        if (this.get_view().Type == 'Grid' && this.get_allowQuickFind()) {
            var s = this.get_quickFindText();
            sb.appendFormat('<td class="QuickFind" title="{2}"><div class="QuickFind"><input type="text" id="{0}_QuickFind" value="{1}" class="{3}"/></div></td>', this.get_id(), Web.DataView.htmlAttributeEncode(s), Web.DataViewResources.Grid.QuickFindToolTip, s == Web.DataViewResources.Grid.QuickFindText ? 'Empty' : 'NonEmpty');
            sb.append('<td class="Divider"><div></div></td>');
            if (this.get_lookupField() && !String.isNullOrEmpty(this.get_lookupField().ItemsNewDataView)) {
                sb.appendFormat('<td class="QuickCreateNew"><a href="#" onclick="$find(&quot;{0}&quot;).closeLookupAndCreateNew()" class="CreateNew" title="{1}"><span class="Placeholder"></span></a></td>', this.get_id(), Web.DataViewResources.Lookup.GenericNewToolTip);
            }
        }
        else {
            if (groups.length == 0 || this.get_lookupField()) sb.append("<td>&nbsp;</td>");
        }
        if (!this.get_lookupField()) {
            for (var i = 0; i < groups.length; i++) {
                if (i > 0)
                    sb.append('<td class="Divider"><div></div></td>');
                var group = groups[i];
                sb.appendFormat('<td class="Group"><a href="#" id="{0}_ActionBarGroup{1}" onclick="return false"><div>{2}<span>&nbsp;</span></div></a></td>', this.get_id(), i, group.HeaderText);
            }
        }
        sb.append('</tr></table>');
        sb.append('</td><td align="right">');
        sb.appendFormat('<table id="{0}_ViewSelectorContainer" class="ViewSelector" cellpadding="0" cellspacing="0"><tr><td class="Label">{1}:</td><td class="Selector"><a id="{0}_ViewSelector" class="Name" href="#" onclick="return false" onmouseover="Sys.UI.DomElement.addCssClass($get(\'{0}_ViewSelectorContainer\'),\'ViewSelectorActive\');" onmouseout="Sys.UI.DomElement.removeCssClass($get(\'{0}_ViewSelectorContainer\'),\'ViewSelectorActive\');">Name</a></td></tr></table>', this.get_id(), Web.DataViewResources.ActionBar.View);
        sb.append('</td></tr></table>');
        sb.append('</td></tr>');
    },
    _renderViewDescription: function(sb) {
        if (this.get_view().HeaderText != null || this.get_lookupField()) {
            sb.appendFormat('<tr class="HeaderTextRow"><td colspan="{0}" class="HeaderText">', this._get_colSpan());
            if (this.get_lookupField() != null)
                sb.append('<table style="width:100%" cellpadding="0" cellspacing="0"><tr><td style="padding:0px">');
            sb.append(this.get_view().HeaderText);
            if (this.get_lookupField() != null)
                sb.appendFormat('</td><td align="right" style="padding:0px"><a href="#" class="Close" onclick="$find(\'{0}\').hideLookup();return false">{1}</a></td></tr></table>', this.get_id(), Web.DataViewResources.ModalPopup.Close);
            sb.append('</td></tr>');
        }
    },
    _renderInfoBar: function(sb) {
        var filter = this.get_filter();
        if (filter.length > 0 && !this.filterIsExternal()) {
            sb.appendFormat('<tr class="InfoRow"><td colspan="{0}" id="{2}_InfoBar">', this._get_colSpan());
            if (this.get_view().Type != "Form") this._renderFilterDetails(sb, filter);
            sb.append('</td></tr>');
        }
    },
    _renderFilterDetails: function(sb, currentFilter) {
        sb.appendFormat('<span class="Information">&nbsp;</span>{0}', Web.DataViewResources.InfoBar.FilterApplied);
        for (var i = 0; i < currentFilter.length; i++) {
            var filter = currentFilter[i].match(/(\w+):([\s\S]*)/);
            var field = this.findField(filter[1]);
            if (!field || this._fieldIsInExternalFilter(field)) continue;
            var aliasField = this._allFields[field.AliasIndex];
            sb.appendFormat(Web.DataViewResources.InfoBar.ValueIs, aliasField.HeaderText);
            var re = /(\*|\>={0,1}|\<={0,1}|=)([\s\S]*?)(\0|$)/g;
            var first = true;
            var fieldOperator = filter[2].match(">|<") ? Web.DataViewResources.InfoBar.And : Web.DataViewResources.InfoBar.Or;
            while ((info = re.exec(filter[2])) != null) {
                if (first)
                    first = false;
                else
                    sb.append(fieldOperator);
                switch (info[1]) {
                    case '=':
                        sb.append(info[2] == 'null' ? Web.DataViewResources.InfoBar.Empty : Web.DataViewResources.InfoBar.EqualTo);
                        break;
                    case '<':
                        sb.append(Web.DataViewResources.InfoBar.LessThan);
                        break;
                    case '<=':
                        sb.append(Web.DataViewResources.InfoBar.LessThanOrEqualTo);
                        break;
                    case '>':
                        sb.append(Web.DataViewResources.InfoBar.GreaterThan);
                        break;
                    case '>=':
                        sb.append(Web.DataViewResources.InfoBar.GreaterThanOrEqual);
                        break;
                    case '*':
                        sb.append(info[2].startsWith('%') ? Web.DataViewResources.InfoBar.Like : Web.DataViewResources.InfoBar.StartsWith);
                        break;
                }
                var item = this._findItemByValue(field, info[2]);
                var v = item == null ? info[2] : item[1];
                if (info[2] != 'null') sb.appendFormat('<b>{0}</b>', Web.DataView.htmlEncode(v));
            }
            sb.append('.');
        }
    },
    _renderFieldHeaderOptions: function(field, values) {
        field._adjustmentNeeded = true;
        var ascending = Web.DataViewResources.HeaderFilter.GenericSortAscending;
        var descending = Web.DataViewResources.HeaderFilter.GenericSortDescending;
        switch (field.Type) {
            case 'String':
                ascending = Web.DataViewResources.HeaderFilter.StringSortAscending;
                descending = Web.DataViewResources.HeaderFilter.StringSortDescending;
                break;
            case 'DateTime':
                ascending = Web.DataViewResources.HeaderFilter.DateSortAscending;
                descending = Web.DataViewResources.HeaderFilter.DateSortDescending;
                break;
        }
        var sb = new Sys.StringBuilder();
        if (Web.DataView.isIE6) sb.append('<table cellpadding="0" cellspacing="0"><tr><td>');
        if (field.AllowSorting)
            sb.appendFormat(
                '<a href="#" onclick="$find(\'{0}\').sort(\'{1} asc\');return false" class="ContextMenuItem SortAscending">{2}</a><a href="#" onclick="$find(\'{0}\').sort(\'{1} desc\');return false" class="ContextMenuItem SortDescending">{3}</a>',
                this.get_id(), field.Name, ascending, descending);
        if (!values)
            values = field._listOfValues;
        if (field.AllowQBE)
            if (values) {
            var aliasField = this._allFields[field.AliasIndex];
            var fieldFilter = this.filterOf(field);
            fieldFilter = fieldFilter && fieldFilter.startsWith('=') ? fieldFilter.substr(1) : (fieldFilter ? '\0' : null);
            if (field.AllowSorting) sb.append('<div class="ContextMenuBreak"></div>');
            sb.appendFormat('<div id="Options"><a href="#" id="{0}_CustomFilterOption{1}" onclick="{3}if(!this.disabled)$find(\'{0}\').applyFilterByIndex({1},-1);return false" class="ContextMenuItem FilterOff{2} {2}" {3}>{4}&nbsp;</a><a href="#" onclick="$find(\'{0}\').showCustomFilter({1});return false" class="ContextMenuItem {6}">{5}</a>',
                this.get_id(), field.AliasIndex, fieldFilter ? '' : 'Disabled', fieldFilter ? '' : 'return false;', String.format(Web.DataViewResources.HeaderFilter.ClearFilter, aliasField.HeaderText), Web.DataViewResources.HeaderFilter.CustomFilterOption, fieldFilter && fieldFilter.indexOf('\0') >= 0 ? 'Checked' : 'CustomFilter');
            if (values.length > 0) sb.append('<div class="ContextMenuBreak"></div>');
            for (var i = 0; i < values.length; i++) {
                var isSelected = false;
                var v = values[i];
                var text = v;
                if (v == null)
                    text = Web.DataViewResources.HeaderFilter.EmptyValue;
                else if (field.Items.length > 0) {
                    var item = this._findItemByValue(field, v);
                    text = item[1];
                }
                else {
                    if (field.Type == 'String' && v.length == 0)
                        text = Web.DataViewResources.HeaderFilter.BlankValue;
                    else if (!String.isNullOrEmpty(field.DataFormatString))
                        text = field.Type == 'DateTime' ? text = String.localeFormat('{0:d}', v) : String.localeFormat(field.DataFormatString, v);
                }
                v = v == null ? 'null' : this.convertFieldValueToString(field, v);
                isSelected = v == fieldFilter;
                if (text.length > Web.DataViewResources.HeaderFilter.MaxSampleTextLen) text = text.substring(0, Web.DataViewResources.HeaderFilter.MaxSampleTextLen) + '...';
                sb.appendFormat('<a href="#" onclick="$find(\'{0}\').applyFilterByIndex({1},{2});return false" class="ContextMenuItem {4}">{3}</a>',
                    this.get_id(), field.AliasIndex, i, aliasField.Type == "String" && v != "null" ? Web.DataView.htmlEncode(text) : text, isSelected ? 'Checked' : '');
            }
            sb.append('</div>');
        }
        else
            sb.appendFormat('<div class="Wait">{0}</div>', Web.DataViewResources.HeaderFilter.Loading);
        if (Web.DataView.isIE6) sb.append('</td></tr></table>');
        field._dropDownPanel.innerHTML = sb.toString();
        sb.clear();
    },
    _findItemByValue: function(field, value) {
        if (field.Items.length == 0) return null;
        value = value == null ? '' : value.toString();
        for (var i = 0; i < field.Items.length; i++) {
            var item = field.Items[i];
            var itemValue = item[0] == null ? "" : item[0].toString();
            if (itemValue == value)
                return item;
        }
        return [value, value];
    },
    _adjustFieldHeaderOptions: function(field) {
        var panel = field._dropDownPanel;
        if (field._listOfValues && field._adjustmentNeeded && field.AllowQBE) {
            var oldDisplay = panel.style.display
            panel.style.display = 'block';
            panel.style.width = '115px';
            field._adjustmentNeeded = false;
            var optionsDiv = $get('Options', panel);
            var needHeightAdjustment = optionsDiv.offsetHeight > 250
            var scrollBarWidth = needHeightAdjustment ? 20 : 0;
            optionsDiv.style.overflow = 'auto';
            var actualWidth = optionsDiv.scrollWidth;
            optionsDiv.style.overflow = '';
            if (panel.offsetWidth < actualWidth) {
                optionsDiv.style.width = (actualWidth + scrollBarWidth) + 'px';
                panel.style.width = (actualWidth + scrollBarWidth) + 'px';
            }
            var headerBounds = $common.getBounds(field._headerDropDownBehavior.get_element());
            var panelBounds = $common.getBounds(panel);
            var linkBounds = $common.getBounds(field._headerDropDownBehavior.get_element());
            var p = { x: headerBounds.x + headerBounds.width - panelBounds.width, y: linkBounds.y + linkBounds.height - 1 };
            var b = $common.getBounds(this.get_element());
            if (p.x < 0) p.x = 0;
            if (panel.offsetTop <= p.y)
                p.y = panel.offsetTop;
            $common.setLocation(panel, p);
            if (needHeightAdjustment) {
                var clientBounds = $common.getClientBounds();
                var optionsHeight = 250;
                var scrollTop = (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
                var optionsBounds = $common.getBounds(optionsDiv);
                if (optionsBounds.y + optionsHeight - scrollTop > clientBounds.height - 2)
                    optionsHeight = clientBounds.height - (optionsBounds.y - scrollTop) - 2;
                if (optionsHeight < 50) optionsHeight = 50;
                optionsDiv.style.height = optionsHeight + 'px';
                optionsDiv.style.overflow = 'auto';
            }
            panel.style.display = oldDisplay;
        }
    },
    _renderViewPager: function(sb) {
        sb.appendFormat('<tr class="FooterRow"><td colspan="{0}" class="Footer"><table cellpadding="0" cellspacing="0" style="width:100%"><tr><td align="left" class="Pager">', this._get_colSpan());
        if (this.get_pageCount() > 1) {
            var buttonIndex = this._firstPageButtonIndex;
            var buttonCount = Web.DataViewResources.Pager.PageButtonCount;
            if (this.get_pageIndex() > 0)
                sb.appendFormat('<a href="#" onclick="$find(\'{1}\').goToPage({0});return false" class="PaddedLink">{2}</a>', this.get_pageIndex() - 1, this.get_id(), Web.DataViewResources.Pager.Previous);
            else
                sb.appendFormat('<span class="Disabled">{0}</span>', Web.DataViewResources.Pager.Previous);
            sb.appendFormat(' | {0}: ', Web.DataViewResources.Pager.Page);
            if (buttonIndex > 0)
                sb.appendFormat('<a href="#" onclick="$find(\'{1}\').goToPage({0});return false" class="PaddedLink">...</a>', buttonIndex - 1, this.get_id());
            while (buttonCount > 0 && buttonIndex < this.get_pageCount()) {
                if (buttonIndex == this.get_pageIndex())
                    sb.appendFormat('<span class="Selected">{0}</span>', buttonIndex + 1);
                else
                    sb.appendFormat('<a href="#" onclick="$find(\'{1}\').goToPage({0});return false" class="PaddedLink">{2}</a>', buttonIndex, this.get_id(), buttonIndex + 1);
                buttonIndex++;
                buttonCount--;
            }
            if (buttonIndex <= this.get_pageCount() - 1)
                sb.appendFormat('<a href="#" onclick="$find(\'{1}\').goToPage({0});return false" class="PaddedLink">...</a>', this._firstPageButtonIndex + Web.DataViewResources.Pager.PageButtonCount, this.get_id());
            sb.append(' | ');
            if (this.get_pageIndex() < this.get_pageCount() - 1)
                sb.appendFormat('<a href="#" onclick="$find(\'{1}\').goToPage({0});return false" class="PaddedLink">{2}</a>', this.get_pageIndex() + 1, this.get_id(), Web.DataViewResources.Pager.Next);
            else
                sb.appendFormat('<span class="Disabled">{0}</span>', Web.DataViewResources.Pager.Next);
        }
        sb.append('</td><td align="right" class="Pager">&nbsp;');
        var pageSizes = Web.DataViewResources.Pager.PageSizes;
        if (this._totalRowCount > this.get_pageSize()) {
            sb.append(Web.DataViewResources.Pager.ItemsPerPage);
            for (i = 0; i < pageSizes.length; i++) {
                if (i > 0) sb.append(', ');
                if (this.get_pageSize() == pageSizes[i])
                    sb.appendFormat('<b>{0}</b>', this.get_pageSize());
                else
                    sb.appendFormat('<a href="#" onclick="$find(\'{0}\').set_pageSize({1});return false">{1}</a>', this.get_id(), pageSizes[i]);
            }
            sb.append(' | ');
        }
        if (this._totalRowCount > 0) {
            var lastVisibleItemIndex = (this.get_pageIndex() + 1) * this.get_pageSize();
            if (lastVisibleItemIndex > this._totalRowCount) lastVisibleItemIndex = this._totalRowCount;
            sb.appendFormat(Web.DataViewResources.Pager.ShowingItems, this.get_pageIndex() * this.get_pageSize() + 1, lastVisibleItemIndex, this._totalRowCount);
            sb.append(' | ');
        }
        sb.appendFormat('</td><td align="center" class="Pager" id="{0}_Wait" style="width:45px">', this.get_id());
        sb.appendFormat('<a href="#" onclick="$find(\'{0}\').goToPage(-1);return false" class="PaddedLink">{1}</a>', this.get_id(), Web.DataViewResources.Pager.Refresh);
        sb.append('</td></tr></table>');
        sb.append('</td></tr>');
    },
    _createParams: function() {
        var lc = this.get_lookupContext();
        return { PageIndex: this.get_pageIndex(), PageSize: this.get_pageSize(), SortExpression: this.get_sortExpression(), Filter: this.get_filter(), ContextKey: this.get_id(), Cookie: this.get_cookie(), FilterIsExternal: this._externalFilter.length > 0, LookupContextFieldName: lc ? lc.FieldName : null, LookupContextController: lc ? lc.Controller : null, LookupContextView: lc ? lc.View : null, LookupContext: lc };
    },
    _loadPage: function() {
        this._delayedLoading = false;
        if (this._source) return;
        if (this.get_mode() != Web.DataViewMode.View) {
            this._allFields = [{ Index: 0, Label: '', DataFormatString: '', AliasIndex: 0, ItemsDataController: this.get_controller(), ItemsNewDataView: this.get_newViewId(), _dataView: this}];
            this._fields = this._allFields;
            this._render();
        }
        else {
            this._busy(true);
            this._detachBehaviors();
            this._showWait();
            this._invoke('GetPage', { controller: this.get_controller(), view: this.get_viewId(), request: this._createParams() }, Function.createDelegate(this, this._onGetPageComplete));
        }
    },
    _invoke: function(methodName, params, onSuccess, userContext) {
        if (this.get_servicePath().startsWith('http')) {
            var m = this.get_servicePath().match(/(.+?)\w+\/\w+\.\w+(\?|$)/)
            var scriptParamId = String.format('__{0}_{1}_ScriptParam', this.get_id(), methodName);
            var scriptParam = $get(scriptParamId);
            var p = scriptParam ? scriptParam.value : Sys.Serialization.JavaScriptSerializer.serialize(params);
            if (scriptParam) scriptParam.value = '';
            var paramLength = p.length;
            while (p) {
                var src = String.format('{0}ScriptHost.ashx?sender={1}&method={2}&ctx={3}&args={4}&cookie={5}', m && m[1].startsWith('http') ? m[1] : '', this.get_id(), methodName, userContext, encodeURI(p), this.get_cookie());
                if (src.length <= 2048) {
                    if (scriptParam && scriptParam.value.length == 0)
                        scriptParam.parentElement.removeChild(scriptParam);
                    break;
                };
                if (!scriptParam) {
                    scriptParam = document.createElement('input');
                    scriptParam.setAttribute('type', 'hidden');
                    scriptParam.setAttribute('id', scriptParamId);
                    document.body.appendChild(scriptParam);
                }
                paramLength = Math.round(paramLength / 3 * 2);
                p = p + scriptParam.value; // reconstruct the serialized parameter
                scriptParam.value = p.substr(paramLength, p.length - paramLength);
                p = p.substr(0, paramLength)
                delete scriptParam;
            }
            var head = document.getElementsByTagName('head')[0];
            var script = document.createElement('script');
            script.setAttribute('id', String.format('__{0}_{1}_ScriptCallBack', this.get_id(), methodName));
            script.setAttribute('type', 'text/javascript');
            script.setAttribute('language', 'javascript');
            script.setAttribute('src', src + (scriptParam ? '&c=1' : ''));
            head.appendChild(script);
        }
        else
            Sys.Net.WebServiceProxy.invoke(this.get_servicePath(), methodName, false, params, onSuccess, Function.createDelegate(this, this._onMethodFailed), userContext);
    },
    _onGetPageComplete: function(result, context) {
        this._busy(false);
        if (this._pageIndex < 0) {
            if (this._pageIndex == -1) {
                this._expressions = result.Expressions;
                this._allFields = result.Fields;
                this._fields = [];
                var selectedKeyMap = [];
                if (this._keyFields && this._selectedKey.length > 0) {
                    for (var i = 0; i < this._keyFields.length; i++)
                        selectedKeyMap[i] = { 'name': this._keyFields[i].Name, 'value': this._selectedKey[i] };
                    this._selectedKey = [];
                }
                this._keyFields = [];
                for (i = 0; i < result.Fields.length; i++) result.Fields[i].Index = i;
                for (i = 0; i < result.Fields.length; i++) {
                    var field = result.Fields[i];
                    field.AliasIndex = field.AliasName && field.AliasName.length > 0 ? this.findField(field.AliasName).Index : i;
                    if (this._fieldIsInExternalFilter(field) && this.get_hideExternalFilterFields())
                        field.Hidden = true;
                    field.Behaviors = [];
                }
                for (i = 0; i < result.Fields.length; i++) {
                    field = result.Fields[i];
                    field._dataView = this;
                    if (!field.Hidden) Array.add(this._fields, field);
                    if (field.IsPrimaryKey) {
                        Array.add(this._keyFields, field);
                        for (var j = 0; j < selectedKeyMap.length; j++) {
                            if (selectedKeyMap[j].name == field.Name) {
                                Array.add(this._selectedKey, selectedKeyMap[j].value);
                                break;
                            }
                        }
                    }
                    if (String.isNullOrEmpty(field.HeaderText)) field.HeaderText = field.Label;
                    if (String.isNullOrEmpty(field.HeaderText)) field.HeaderText = field.Name;
                    if (field.DataFormatString && field.DataFormatString.indexOf('{') == -1)
                        field.DataFormatString = '{0:' + field.DataFormatString + '}';
                    if (field.DataFormatString)
                        field.DataFormatString = this.resolveClientUrl(field.DataFormatString);
                    if (field.Type == 'DateTime' && !field.DataFormatString) field.DataFormatString = '{0:d}';
                    if (field.Type == 'Boolean' && field.Items.length == 0) {
                        field.Items = field.AllowNulls ? Web.DataViewResources.Data.BooleanOptionalDefaultItems : Web.DataViewResources.Data.BooleanDefaultItems;
                        if (!field.ItemsStyle) field.ItemsStyle = Web.DataViewResources.Data.BooleanDefaultStyle;
                    }
                    if (field.Items && field.Items.length > 0 && field.AllowNulls && field.Items[0][0] != null && field.ItemsStyle != 'CheckBoxList')
                        Array.insert(field.Items, 0, [null, Web.DataViewResources.Data.NullValueInForms]);
                }
                this._views = result.Views;
                this._actionGroups = result.ActionGroups ? (result.ActionGroups.length == 0 ? Web.DataViewResources.Actions.DefaultGroups : result.ActionGroups) : [];
                for (i = 0; i < this._actionGroups.length; i++) {
                    for (j = 0; j < this._actionGroups[i].Actions.length; j++) {
                        var action = this._actionGroups[i].Actions[j];
                        if (!action.HeaderText || action.HeaderText.length == 0)
                            action.HeaderText = action.CommandName;
                    }
                }
                this._categories = result.Categories;
                for (i = 0; i < this._categories.length; i++)
                    this._categories[i].Index = i;
            }
            this._totalRowCount = result.TotalRowCount;
            this._filter = result.Filter;
            this._sortExpression = result.SortExpression;
            this._pageIndex = result.PageIndex;
            this._firstPageButtonIndex = Math.floor(result.PageIndex / Web.DataViewResources.Pager.PageButtonCount) * Web.DataViewResources.Pager.PageButtonCount; //result.PageIndex;
            this._pageSize = result.PageSize;
            this._pageCount = Math.floor(result.TotalRowCount / result.PageSize);
            if (result.TotalRowCount % result.PageSize != 0)
                this._pageCount++;
        }
        this._rows = result.Rows;
        this._newRow = result.NewRow;
        if (result.Aggregates) this._aggregates = result.Aggregates;
        if (this.get_view().Type == 'Form' && this._selectedRowIndex == null && this._totalRowCount > 0) {
            this._selectedRowIndex = 0;
            this._selectKeyByRowIndex(0);
        }
        if (this.get_startCommandName()) {
            var command = this.get_startCommandName();
            var argument = this.get_startCommandArgument();
            this.set_startCommandName(null);
            this.set_startCommandArgument(null);
            this.executeCommand({ commandName: command, commandArgument: argument ? argument : '' });
        }
        this._render();
        if (this.get_modalAnchor())
            this._adjustModalPopupSize();
        else
            this._adjustLookupSize();
        if (this._isInInstantDetailsMode()) {
            var size = $common.getClientBounds();
            var contentSize = $common.getContentSize(document.body);
            window.resizeBy(0, contentSize.height - size.height);
        }
    },
    _initializeModalPopup: function() {
        Sys.UI.DomElement.addCssClass(this.get_element(), 'ModalPlaceholder');
        var cb = $common.getClientBounds();
        var width = cb.width / 5 * 4;
        if (width > Web.DataViewResources.ModalPopup.MaxWidth) width = Web.DataViewResources.ModalPopup.MaxWidth;
        var height = cb.height / 5 * 4;
        if (this._container.style.overflowX != null) {
            this._container.style.overflowY = 'auto';
            this._container.style.overflowX = 'hidden';
        }
        else
            this._container.style.overflow = 'auto';
        this._container.style.height = height + 'px';
        this._container.style.width = width + 'px';
        this._saveTabIndexes();
        this._modalPopup = $create(AjaxControlToolkit.ModalPopupBehavior, { id: this.get_id() + 'ModalPopup' + Sys.Application.getComponents().length, PopupControlID: this.get_element().id, DropShadow: true, BackgroundCssClass: 'ModalBackground' }, null, null, this.get_modalAnchor());
        this._modalPopup.show();
    },
    _adjustModalPopupSize: function() {
        var sb = new Sys.StringBuilder();
        var rowsToDelete = [];
        var tables = this._container.getElementsByTagName('table');
        for (var i = tables.length - 1; i >= 0; i--) {
            var t = tables[i];
            if (t.className == 'ActionButtons') {
                if (sb.isEmpty()) {
                    sb.append('<table class="DataView" cellSpacing=0 cellPadding=0><tr class="ActionButtonsRow BottomButtonsRow">')
                    sb.append(t.parentNode.parentNode.innerHTML);
                    sb.append('</tr></table>');
                }
                Array.add(rowsToDelete, t.parentNode.parentNode);
            }
        }
        delete tables;
        while (rowsToDelete.length > 0) {
            rowsToDelete[0].parentNode.removeChild(rowsToDelete[0]);
            delete rowsToDelete[0];
            Array.removeAt(rowsToDelete, 0);
        }
        if (!this._buttons) {
            var b = $common.getContentSize(this._container.childNodes[0]);
            this._buttons = document.createElement('div');
            this.get_element().appendChild(this._buttons);
            this._buttons.style.width = b.width + 'px';
            Sys.UI.DomElement.addCssClass(this._buttons, 'FixedButtons');
            this._title = document.createElement('div');
            this._title.innerHTML = Web.DataView.htmlEncode(this.get_view().Label);
            Sys.UI.DomElement.addCssClass(this._title, 'FixedTitle');
            this.get_element().insertBefore(this._title, this._container);
        }
        this._buttons.innerHTML = sb.toString();
        sb.clear();
        var containerBounds = $common.getBounds(this._container);
        var contentSize = $common.getBounds(this._container.childNodes[0]);
        var clientBounds = $common.getClientBounds();
        var maxHeight = Math.ceil(clientBounds.height / 5 * 4);
        if (containerBounds.height > maxHeight)
            this._container.style.height = maxHeight + 'px';
        if (containerBounds.height > contentSize.height) {
            $common.setContentSize(this._container, contentSize);
        }
        this._container.childNodes[0].style.width = this._title.offsetWidth + 'px';
        this._buttons.style.width = this._title.offsetWidth + 'px';
        Sys.UI.DomElement.setVisible(this.get_element(), true);
        if (this._modalPopup) {
            if (Sys.Browser.agent === Sys.Browser.InternetExplorer) this._modalPopup.hide();
            this._modalPopup.show();
        }
        if (Sys.Browser.agent === Sys.Browser.InternetExplorer && this.get_isEditing()) this._focus();
    },
    endModalState: function(commandName) {
        if (this.get_isModal()) {
            var exitCommands = this.get_exitModalStateCommands();
            if (exitCommands) {
                for (var i = 0; i < exitCommands.length; i++) {
                    if (commandName == exitCommands[i]) {
                        this._modalPopup.dispose();
                        this._restoreTabIndexes();
                        var elem = this.get_element();
                        this.dispose();
                        elem.parentNode.removeChild(elem);
                        delete elem;
                        return true;
                    }
                }
            }
        }
        return false;
    },
    _adjustLookupSize: function() {
        if (this.get_lookupField() && Web.DataView.isIE6) this.get_lookupField()._lookupModalBehavior._layout(); ;
        if (this.get_lookupField() && this.get_pageSize() > 3) {
            var scrollTop = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop;
            var clientBounds = $common.getClientBounds()
            var b = $common.getBounds(this.get_element());
            if (b.height + b.y > clientBounds.height + scrollTop) this.set_pageSize(Math.ceil(this.get_pageSize() * 0.66));
        }
    },
    _onMethodFailed: function(err, response, context) {
        if (Web.DataView._navigated) return;
        this._busy(false);
        alert(String.format('Timed out: {0}\r\nException: {1}\r\nMessage: {2}\r\nStack:\r\n{3}', err.get_timedOut(), err.get_exceptionType(), err.get_message(), err.get_stackTrace()));
    },
    _loadListOfValues: function(fieldName, distinctFieldName) {
        this._busy(true);
        var lc = this.get_lookupContext();
        var filter = this.get_filter();
        this._invoke('GetListOfValues', { controller: this.get_controller(), view: this.get_viewId(), request: { FieldName: distinctFieldName, Filter: filter.length == 1 && filter[0].match(/(\w+):/)[1] == distinctFieldName ? null : filter, LookupContextFieldName: lc ? lc.FieldName : null, LookupContextController: lc ? lc.Controller : null, LookupContextView: lc ? lc.View : null} },
            Function.createDelegate(this, this._onGetListOfValuesComplete), fieldName);
    },
    _onGetListOfValuesComplete: function(result, context) {
        this._busy(false);
        var field = this.findField(context);
        field._listOfValues = result;
        if (result[result.length - 1] == null) {
            Array.insert(result, 0, result[result.length - 1]);
            Array.removeAt(result, result.length - 1);
        }
        this._renderFieldHeaderOptions(field, result);
        this._adjustFieldHeaderOptions(field);
    },
    _execute: function(args) {
        this._busy(true);
        this._showWait();
        this._lastArgs = args;
        args.Filter = this.get_filter();
        args.SortExpression = this.get_sortExpression();
        var selection = this.get_selectedValue();
        args.SelectedValues = selection.length == 0 ? [] : (this.get_selectionMode() == Web.DataViewSelectionMode.Single ? [selection] : selection.split(';'));
        args.ExternalFilter = this.get_externalFilter();
        this._invoke('Execute', { controller: this.get_controller(), view: this.get_viewId(), args: args }, Function.createDelegate(this, this._onExecuteComplete));
    },
    _onExecuteComplete: function(result, context) {
        this._busy(false);
        this._hideWait();
        var ev = { 'result': result, 'context': context, 'handled': false }
        this.raiseExecuted(ev);
        if (ev.handled) return;
        var existingRow = !this._lastArgs.CommandName.match(/Insert/i);
        if (existingRow)
            for (var i = 0; i < result.Values.length; i++) {
            var v = result.Values[i];
            var field = this.findFind(v.Name);
            if (field) this.get_selectedRow()[field.Index] = v.NewValue;
        }
        else {
            this._selectedKey = [];
            this._selectedKeyFilter = [];
            if (result.Values.length == 0) result.Values = this._lastArgs.Values;
            for (i = 0; i < this._keyFields.length; i++) {
                field = this._keyFields[i];
                v = null;
                for (var j = 0; j < result.Values.length; j++)
                    if (result.Values[j].Name == field.Name) {
                    v = result.Values[j];
                    break;
                }
                Array.add(this._selectedKey, v ? v.NewValue : null);
                Array.add(this._selectedKeyFilter, field.Name + ':=' + this.convertFieldValueToString(field, v ? v.NewValue : null));
            }
            this.raiseSelected();
        }
        if (result.Errors.length == 0) {
            if (result.ClientScript) {
                result.ClientScript = this.resolveClientUrl(result.ClientScript);
                eval(result.ClientScript);
                if (this._exportRedirect && this.get_servicePath().startsWith('http'))
                    this._exportRedirect = this.resolveClientUrl(this._exportRedirect.replace(/(.*?)(\/\w+\.\w+.*)$/, '~$2'));
            }
            else if (result.NavigateUrl) {
                result.NavigateUrl = this.resolveClientUrl(result.NavigateUrl);
                this.navigate(result.NavigateUrl, existingRow ? this._lastArgs.Values : result.Values);
            }
            else if (this._closeInstantDetails()) { }
            else if (this.endModalState(this._lastArgs.CommandName)) { }
            else if (this.get_backOnCancel()) history.go(-1)
            else {
                var actions = this.get_actions(this.get_view().Type);
                var lastCommand = this._lastArgs.CommandName;
                var lastArgument = this._lastArgs.CommandArgument;
                for (i = 0; i < actions.length; i++) {
                    var a = actions[i];
                    if (a.WhenLastCommandName == lastCommand && (a.WhenLastCommandArgument == '' || a.WhenLastCommandArgument == lastArgument)) {
                        this.executeCommand({ commandName: a.CommandName, commandArgument: a.CommandArgument, causesValidation: a.CausesValidation });
                        return;
                    }
                }
                this.set_lastCommandName(null);
                this.goToView(this._lastViewId);
            }
        }
        else {
            if (result.ClientScript) {
                result.ClientScript = this.resolveClientUrl(result.ClientScript);
                eval(result.ClientScript);
            }
            var sb = new Sys.StringBuilder();
            for (i = 0; i < result.Errors.length; i++)
                sb.append(Web.DataView.formatMessage('Attention', result.Errors[i]));
            Web.DataView.showMessage(sb.toString());
            sb.clear();
        }
    },
    _busy: function(isBusy) {
        this._isBusy = isBusy;
        this._enableButtons(!isBusy);
    },
    _enableButtons: function(enable) {
        var buttons = document.getElementsByTagName('button');
        for (var i = 0; i < buttons.length; i++) {
            var button = buttons[i];
            if (button)
                if (!enable) {
                button.WasDisabled = true;
                button.disabled = true;
            }
            else if (button.WasDisabled) {
                button.WasDisabled = false;
                button.disabled = false;
            }
        }
    },
    _headerDropDownOnShowing: function(e, args) {
        var m = e.get_id().match(/_HeaderDropDown(\d+)/);
        var field = this.get_fields()[Number.parseInvariant(m[1])];
        this._renderFieldHeaderOptions(field);
        if (!field._listOfValues && field.AllowQBE)
            this._loadListOfValues(field.Name, this._allFields[field.AliasIndex].Name);
        else
            this._adjustFieldHeaderOptions(field);
    },
    _actionBarGroupOnShowing: function(sender, args) {
        this._hidePopups();
    },
    _viewSelectorOnShown: function(sender, args) {
        var parentBounds = $common.getBounds(sender.get_parentElement().parentNode);
        var elementBounds = $common.getBounds(sender.get_element());
        elementBounds.x = parentBounds.x + parentBounds.width - elementBounds.width;
        elementBounds.y += Sys.Browser.agent == Sys.Browser.Firefox ? 2 : -2;
        if (!this.get_lookupField())
            $common.setBounds(sender.get_element(), elementBounds);
    },
    _hidePopups: function() {
        var components = Sys.Application.getComponents();
        for (var i = 0; i < components.length; i++) {
            var c = components[i];
            if (AjaxControlToolkit.DropDownBehavior.isInstanceOfType(c)) {
                c.hide();
                c.unhover();
            }
            if (AjaxControlToolkit.PopupControlBehavior.isInstanceOfType(c))
                c.hidePopup();
        }
    },
    _bodyKeydown: function(e) {
        if (this._customFilterField) {
            if (e.keyCode == Sys.UI.Key.enter) {
                this.applyCustomFilter();
                e.preventDefault();
            }
            else if (e.keyCode == Sys.UI.Key.esc) this.closeCustomFilter();
        }
        else if (this.get_lookupField())
            if (e.keyCode == Sys.UI.Key.esc) this.hideLookup();
    },
    _filterSourceSelected: function(sender, args, keepContext) {
        for (var i = 0; i < this._externalFilter.length; i++) this._externalFilter[i].Value = null;
        if (Web.DataView.isInstanceOfType(sender))
            this._populateExternalViewFilter(sender);
        else if (this._externalFilter.length > 0)
            this._externalFilter[0].Value = sender.target.value;
        this.applyExternalFilter();
        if (!keepContext) this.set_pageIndex(-1);
        //this._loadPage();
        this.loadPage();
        if (!keepContext) Array.clear(this._selectedKey);
        this.raiseSelected();
    },
    _createExternalFilter: function() {
        this._externalFilter = [];
        var iterator = /(\w+)(,|$)/g;
        if (this.get_filterFields()) {
            var s = match = iterator.exec(this.get_filterFields());
            var match = iterator.exec(s);
            while (match) {
                Array.add(this._externalFilter, { Name: match[1], Value: null });
                match = iterator.exec(s);
            }
        }
    },
    _populateExternalViewFilter: function(view) {
        if (!(view._selectedKey && view._keyFields && view._selectedKey.length == view._keyFields.length)) return;
        for (var i = 0; i < this._externalFilter.length; i++) {
            var filterItem = this._externalFilter[i];
            var found = false;
            for (var j = 0; j < view._keyFields.length; j++) {
                var field = view._keyFields[j];
                if (filterItem.Name == field.Name) {
                    filterItem.Value = view.convertFieldValueToString(field, view._selectedKey[j]);
                    found = true;
                    break;
                }
            }
            if (!found && this.get_controller() != view.get_controller())
                for (j = 0; j < view._allFields.length; j++) {
                field = view._allFields[j];
                if (filterItem.Name == field.Name) {
                    filterItem.Value = view.convertFieldValueToString(field, view.get_selectedRow()[view._allFields[j].Index]);
                    found = true;
                    break;
                }
            }
            if (!found && view._selectedKey.length >= i)
                filterItem.Value = view._selectedKey[i];
        }
    },
    _stopValueChangedTimer: function() {
        if (this._valueChangedInterval) {
            window.clearInterval(this._valueChangedInterval);
            this._valueChangedInterval = null;
        }
    },
    _startValueChangedTimer: function(target) {
        this._stopValueChangedTimer();
        this._valueChangedInterval = window.setInterval(String.format('$find("{0}")._valueChanged()', this.get_id(), target), 400);
    },
    _cloneChangedRow: function() {
        if (this.get_isEditing()) {
            var values = this._collectFieldValues();
            var selectedRow = this.get_isInserting() ? (this._newRow ? this._newRow : []) : this.get_selectedRow();
            var row = Array.clone(selectedRow);
            for (var i = 0; i < values.length; i++) {
                var v = values[i];
                var f = this.findField(v.Name);
                if (f && !f.ReadOnly)
                    row[f.Index] = v.NewValue;
            }
            return row;
        }
        else
            return this.get_selectedRow();
    },
    _updateVisibility: function() {
        if (!this._expressions) return;
        var expressions = [];
        var row = this._cloneChangedRow();
        if (!row) return;
        for (var i = 0; i < this._expressions.length; i++) {
            var exp = expressions[0] = this._expressions[i];
            if (exp.Scope == Web.DynamicExpressionScope.DataFieldVisibility && exp.Type == Web.DynamicExpressionType.ClientScript) {
                var f = this.findField(exp.Target);
                if (f) {
                    var elem = $get(String.format('{0}_ItemContainer{1}', this.get_id(), f.Index));
                    if (elem) {
                        var result = this._evaluateJavaScriptExpressions(expressions, row, false);
                        Sys.UI.DomElement.setVisible(elem, result == true);
                    }
                }
            }
            else if (exp.Scope == Web.DynamicExpressionScope.CategoryVisibility && exp.Type == Web.DynamicExpressionType.ClientScript) {
                var c = this.findCategory(exp.Target);
                if (c) {
                    elem = $get(String.format('{0}_Category{1}', this.get_id(), c.Index));
                    if (elem) {
                        result = this._evaluateJavaScriptExpressions(expressions, row, false);
                        Sys.UI.DomElement.setVisible(elem, result == true);
                    }
                }
            }
        }
    },
    _valueChanged: function() {
        this._stopValueChangedTimer();
        this._updateVisibility();
    },
    _quickFind_focus: function(e) {
        var qf = this.get_quickFindElement();
        if (qf.value == Web.DataViewResources.Grid.QuickFindText)
            qf.value = '';
        Sys.UI.DomElement.removeCssClass(qf, 'Empty');
        Sys.UI.DomElement.removeCssClass(qf, 'NonEmpty');
    },
    _quickFind_blur: function(e) {
        var qf = this.get_quickFindElement();
        if (String.isBlank(qf.value)) {
            qf.value = Web.DataViewResources.Grid.QuickFindText;
            Sys.UI.DomElement.addCssClass(qf, 'Empty');
        }
        else
            Sys.UI.DomElement.addCssClass(qf, 'NonEmpty');
    },
    _quickFind_keydown: function(e) {
        if (e.keyCode == Sys.UI.Key.enter) {
            e.preventDefault();
            var q = this.get_quickFindElement().value.match(/^\s*(.*?)\s*$/);
            this.set_quickFindText(q[1]);
            for (var i = 0; i < this._allFields.length; i++)
                this._allFields[i]._listOfValues = null;
            for (i = 0; i < this._allFields.length; i++) {
                var f = this._allFields[i];
                if (!f.Hidden) {
                    f = this._allFields[f.AliasIndex];
                    if (String.isNullOrEmpty(q[1])) {
                        this.removeFromFilter(f);
                        this.set_pageIndex(-2);
                        this._loadPage();
                    }
                    else {
                        if (f.Type == 'String')
                            this.applyFilter(f, '*', '%' + q[1] + '%');
                        else
                            this.applyFilter(f, '=', q[1]);
                    }
                    break;
                }
            }
        }
    }
}

Web.DataView.registerClass('Web.DataView', Sys.UI.Behavior);

Web.DataView.hideMessage = function() { Web.DataView.showMessage() }

Web.DataView.formatMessage = function(type, message) { return String.format('<table cellpadding="0" cellspacing="0" style="width:100%"><tr><td class="{0}" valign="top">&nbsp;</td><td class="Message">{1}</td></tr></table>', type, message) }

Web.DataView.showMessage = function(message) {
    if (message != null && message.toString().match(/^\s*$/) != null) message = null;
    var bodyTag = document.getElementsByTagName('body')[0];
    if (!Web.DataView.MessageBar) {
        var panel = document.createElement('div');
        panel.id = 'DataView_MessageBar';
        bodyTag.appendChild(panel);
        Sys.UI.DomElement.setVisible(panel, false);
        Sys.UI.DomElement.addCssClass(panel, 'MessageBar');
        Web.DataView.MessageBar = $create(AjaxControlToolkit.AlwaysVisibleControlBehavior, { VerticalOffset: AjaxControlToolkit.VerticalSide.Top }, null, null, panel);
        var b = Sys.UI.DomElement.getBounds(bodyTag);
        if (b.y < 0) b.y = 0;
        Web.DataView.OriginalBodyTopOffset = b.y;
    }
    panel = $get('DataView_MessageBar');
    panel.innerHTML = message ? message : '';
    Sys.UI.DomElement.setVisible(panel, message != null);
    var bounds = Sys.UI.DomElement.getBounds(panel);
    var bodyTop = message ? Web.DataView.OriginalBodyTopOffset + bounds.height : Web.DataView.OriginalBodyTopOffset;
    bodyTag.style.paddingTop = bodyTop + 'px';
    var loginDialog = $get("Membership_Login");
    if (loginDialog) loginDialog.style.marginTop = (bodyTop) + 'px';
}

Web.DataView._tagsWithIndexes = new Array('A', 'AREA', 'BUTTON', 'INPUT', 'OBJECT', 'SELECT', 'TEXTAREA', 'IFRAME');
Web.DataView._delayedLoadingViews = [];

Web.DataView._performDelayedLoading = function() {
    var i = 0;
    while (i < Web.DataView._delayedLoadingViews.length) {
        var v = Web.DataView._delayedLoadingViews[i];
        if (v.get_isDisplayed()) {
            Array.remove(Web.DataView._delayedLoadingViews, v);
            v._loadPage();
        }
        else i++;
    }
}

Web.DataView.find = function(id) {
    var cid = '_' + id;
    var list = Sys.Application.getComponents();
    for (var i = 0; i < list.length; i++) {
        var c = list[i];
        if (Web.DataView.isInstanceOfType(c) && c.get_id().endsWith(cid) || c.get_id() == id) return c;
    }
    return null;
}

Web.DataView.showModal = function(anchor, controller, view, startCommandName, startCommandArgument, baseUrl, servicePath) {
    if (!anchor) {
        var links = document.getElementsByTagName('a', 'input', 'button');
        for (var i = links.length - 1; i >= 0; i--) {
            if (links[i].tabIndex >= 0) {
                anchor = links[i];
                break;
            }
        }
    }
    if (anchor == null) {
        alert('Cannot find an anchor for a modal popup.');
        return;
    }
    if (!baseUrl) baseUrl = Web.DataView._baseUrl;
    if (!servicePath) servicePath = Web.DataView._servicePath;
    var placeholder = this._placeholder = document.createElement('div');
    placeholder.id = String.format('{0}_{1}_Placeholder{2}', controller, view, Sys.Application.getComponents().length);
    document.body.appendChild(placeholder);
    placeholder.className = 'ModalPlaceholder FixedDialog';
    Sys.UI.DomElement.setVisibilityMode(placeholder, Sys.UI.VisibilityMode.hide);
    Sys.UI.DomElement.setVisible(placeholder, false);
    return $create(Web.DataView, { id: controller + '_ModalDataView' + Sys.Application.getComponents().length, baseUrl: baseUrl, servicePath: servicePath,
        controller: controller, viewId: view, showActionBar: false, modalAnchor: anchor, startCommandName: startCommandName, startCommandArgument: startCommandArgument, exitModalStateCommands: ['Cancel']
    }, null, null, placeholder);
}

Web.DataView._initializeDelayedLoading = function() {
    if (Web.DataView._delayedLoadingViews.length > 0)
        Web.DataView._delayedLoadingTimer = window.setInterval('Web.DataView._performDelayedLoading()', 1000);
    updateACT();
}

Web.DataView.DetailsHandler = 'Details.aspx';

Sys.Application.add_load(Web.DataView._initializeDelayedLoading);

function $createDataView(placeholderId, controller, args) {
    var params = { 'id': controller + 'Extender', 'controller': controller, 'baseUrl': './', 'servicePath': 'Services/DataControllerService.asmx' }
    if (args) {
        for (var i = 0; i < args.length; i++)
            params[args[i].name] = args[i].value;
    }
    $create(Web.DataView, params, null, null, $get(placeholderId));
}

function updateACT() {
    $common.getScrolling = function() {
        var x = 0;
        var y = 0;
        if (typeof (window.pageYOffset) == 'number') {
            y = window.pageYOffset;
            x = window.pageXOffset;
        } else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) {
            y = document.body.scrollTop;
            x = document.body.scrollLeft;
        } else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
            y = document.documentElement.scrollTop;
            x = document.documentElement.scrollLeft;
        }
        return new Sys.UI.Point(x, y);
    }
    if (!AjaxControlToolkit.DropDownBehavior.prototype.old_show) {
        AjaxControlToolkit.DropDownBehavior.prototype.old_show = AjaxControlToolkit.DropDownBehavior.prototype.show;
        AjaxControlToolkit.DropDownBehavior.prototype.show = function() {
            this.old_show();
            var clientBounds = $common.getClientBounds();
            var scrolling = $common.getScrolling();
            var dropDownBounds = $common.getBounds(this._dropDownControl);
            if (scrolling.y + clientBounds.height < dropDownBounds.y + dropDownBounds.height) {
                var bounds = $common.getBounds(this._element);
                this._dropDownControl.style.top = bounds.y - dropDownBounds.height + 2;
            }
        }
    }
    if (!AjaxControlToolkit.CalendarBehavior.prototype.old_show) {
        AjaxControlToolkit.CalendarBehavior.prototype.old_show = AjaxControlToolkit.CalendarBehavior.prototype.show;
        AjaxControlToolkit.CalendarBehavior.prototype.show = function() {
            this.old_show();
            var clientBounds = $common.getClientBounds();
            var scrolling = $common.getScrolling();
            var popupDivBounds = $common.getBounds(this._popupDiv);
            if (scrolling.y + clientBounds.height < popupDivBounds.y + popupDivBounds.height) {
                var bounds = $common.getBounds(this._element);
                this._popupDiv.style.top = bounds.y - popupDivBounds.height + 3;
            }
        }
    }
}

if (typeof (Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();

